Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / godoc / search.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/godoc/search.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/godoc/search.go
new file mode 100644 (file)
index 0000000..0e7509a
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+       "bytes"
+       "fmt"
+       "net/http"
+       "regexp"
+       "strings"
+)
+
+type SearchResult struct {
+       Query string
+       Alert string // error or warning message
+
+       // identifier matches
+       Pak HitList       // packages matching Query
+       Hit *LookupResult // identifier matches of Query
+       Alt *AltWords     // alternative identifiers to look for
+
+       // textual matches
+       Found    int         // number of textual occurrences found
+       Textual  []FileLines // textual matches of Query
+       Complete bool        // true if all textual occurrences of Query are reported
+       Idents   map[SpotKind][]Ident
+}
+
+func (c *Corpus) Lookup(query string) SearchResult {
+       result := &SearchResult{Query: query}
+
+       index, timestamp := c.CurrentIndex()
+       if index != nil {
+               // identifier search
+               if r, err := index.Lookup(query); err == nil {
+                       result = r
+               } else if err != nil && !c.IndexFullText {
+                       // ignore the error if full text search is enabled
+                       // since the query may be a valid regular expression
+                       result.Alert = "Error in query string: " + err.Error()
+                       return *result
+               }
+
+               // full text search
+               if c.IndexFullText && query != "" {
+                       rx, err := regexp.Compile(query)
+                       if err != nil {
+                               result.Alert = "Error in query regular expression: " + err.Error()
+                               return *result
+                       }
+                       // If we get maxResults+1 results we know that there are more than
+                       // maxResults results and thus the result may be incomplete (to be
+                       // precise, we should remove one result from the result set, but
+                       // nobody is going to count the results on the result page).
+                       result.Found, result.Textual = index.LookupRegexp(rx, c.MaxResults+1)
+                       result.Complete = result.Found <= c.MaxResults
+                       if !result.Complete {
+                               result.Found-- // since we looked for maxResults+1
+                       }
+               }
+       }
+
+       // is the result accurate?
+       if c.IndexEnabled {
+               if ts := c.FSModifiedTime(); timestamp.Before(ts) {
+                       // The index is older than the latest file system change under godoc's observation.
+                       result.Alert = "Indexing in progress: result may be inaccurate"
+               }
+       } else {
+               result.Alert = "Search index disabled: no results available"
+       }
+
+       return *result
+}
+
+// SearchResultDoc optionally specifies a function returning an HTML body
+// displaying search results matching godoc documentation.
+func (p *Presentation) SearchResultDoc(result SearchResult) []byte {
+       return applyTemplate(p.SearchDocHTML, "searchDocHTML", result)
+}
+
+// SearchResultCode optionally specifies a function returning an HTML body
+// displaying search results matching source code.
+func (p *Presentation) SearchResultCode(result SearchResult) []byte {
+       return applyTemplate(p.SearchCodeHTML, "searchCodeHTML", result)
+}
+
+// SearchResultTxt optionally specifies a function returning an HTML body
+// displaying search results of textual matches.
+func (p *Presentation) SearchResultTxt(result SearchResult) []byte {
+       return applyTemplate(p.SearchTxtHTML, "searchTxtHTML", result)
+}
+
+// HandleSearch obtains results for the requested search and returns a page
+// to display them.
+func (p *Presentation) HandleSearch(w http.ResponseWriter, r *http.Request) {
+       query := strings.TrimSpace(r.FormValue("q"))
+       result := p.Corpus.Lookup(query)
+
+       var contents bytes.Buffer
+       for _, f := range p.SearchResults {
+               contents.Write(f(p, result))
+       }
+
+       var title string
+       if haveResults := contents.Len() > 0; haveResults {
+               title = fmt.Sprintf(`Results for query: %v`, query)
+               if !p.Corpus.IndexEnabled {
+                       result.Alert = ""
+               }
+       } else {
+               title = fmt.Sprintf(`No results found for query %q`, query)
+       }
+
+       body := bytes.NewBuffer(applyTemplate(p.SearchHTML, "searchHTML", result))
+       body.Write(contents.Bytes())
+
+       p.ServePage(w, Page{
+               Title:    title,
+               Tabtitle: query,
+               Query:    query,
+               Body:     body.Bytes(),
+               GoogleCN: googleCN(r),
+       })
+}
+
+func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
+       w.Header().Set("Content-Type", "application/opensearchdescription+xml")
+       data := map[string]interface{}{
+               "BaseURL": fmt.Sprintf("http://%s", r.Host),
+       }
+       applyTemplateToResponseWriter(w, p.SearchDescXML, &data)
+}
+
+// tocColCount returns the no. of columns
+// to split the toc table to.
+func tocColCount(result SearchResult) int {
+       tocLen := tocLen(result)
+       colCount := 0
+       // Simple heuristic based on visual aesthetic in manual testing.
+       switch {
+       case tocLen <= 10:
+               colCount = 1
+       case tocLen <= 20:
+               colCount = 2
+       case tocLen <= 80:
+               colCount = 3
+       default:
+               colCount = 4
+       }
+       return colCount
+}
+
+// tocLen calculates the no. of items in the toc table
+// by going through various fields in the SearchResult
+// that is rendered in the UI.
+func tocLen(result SearchResult) int {
+       tocLen := 0
+       for _, val := range result.Idents {
+               if len(val) != 0 {
+                       tocLen++
+               }
+       }
+       // If no identifiers, then just one item for the header text "Package <result.Query>".
+       // See searchcode.html for further details.
+       if len(result.Idents) == 0 {
+               tocLen++
+       }
+       if result.Hit != nil {
+               if len(result.Hit.Decls) > 0 {
+                       tocLen += len(result.Hit.Decls)
+                       // We need one extra item for the header text "Package-level declarations".
+                       tocLen++
+               }
+               if len(result.Hit.Others) > 0 {
+                       tocLen += len(result.Hit.Others)
+                       // We need one extra item for the header text "Local declarations and uses".
+                       tocLen++
+               }
+       }
+       // For "textual occurrences".
+       tocLen++
+       return tocLen
+}