Commit Graph

9 Commits

Author SHA1 Message Date
Alan Donovan b929f3bf4d internal/span: make NewRange accept File, not FileSet
span.NewRange now accepts a *token.File and two token.Pos.
It is the caller's responsibility to look up the File
in the FileSet, if necessary (it usually isn't), and to
ensure the Pos values are valid.  Ditto NewMappedRange.

This reduces the creep of Snapshot into functions that
have no need to know about it. Also the bug.Report call
in NewRange has been pushed up into the caller and
logically eliminated in all but one case.

I think we should aim for the invariant that functions that
operate on a single file should accept a *token.File, not
a FileSet; only functions that operate on sets of files
(e.g. type checking, analysis) should use a FileSet.
This is not always possible: some public functions
accept a FileSet only to re-lookup a single file already
known to the caller; if necessary we could provide token.File
variants of these.

This may ultimately allow us to create a new FileSet per
call to the parser, so that Files and FileSets are in
1:1 correspondance and there is no global FileSet.
(It currently grows without bound, on the order of kilobytes
per keystroke.) FileSets containing multiple files,
needed when we interact with the type checker and analysis,
may be temporarily synthesized on demand from a set of Files,
analogous to mmap'ing a few files into a blank address space.

Also:
- replace File.Position(pos).Line by File.Line(pos)
- replace pos == token.NoPos by pos.IsValid()
- avoid fishy token.Pos conversions in link.go
- other minor simplifications

Change-Id: Ia3119e0ac7e193801fbafa81c8f48acfa14e9ae4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/409935
Auto-Submit: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-06 19:40:50 +00:00
Muir Manders ffc70b9ac1 lsp/completion: fix ranking of *types.PkgName candidates
In Go 1.18 types.AssignableTo() started reporting that an invalid type
is assignable to any interface. *types.PkgName (i.e. an import at the
top of the file) has an invalid type for its Type(), so we started
thinking all in scope imports were great candidates when the expected
type was an interface.

Fix by wrapping the AssignableTo (and AssertableTo) to explicitly
return false if either operand is invalid.

Updates golang/go#53595

Change-Id: Ie5a84b7f410ff5c73c6b7870e052bafaf3e21e99
Reviewed-on: https://go-review.googlesource.com/c/tools/+/415595
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
2022-07-01 14:13:48 +00:00
Robert Findley d7e01c038e internal/lsp/source/completion: use typeutil.Map for short-circuiting
While working on golang/go#52715, I discovered an infinite recursion in
gopls' completion logic: eachField assumes a finiteness of type pointers.

It is almost certainly a go/types bug that type-checked types expand
infinitely, but nevertheless we should use the more accurate
typeutil.Map for short-circuiting our search.

Change-Id: Ib1c7125e624f42882869acd4e0476e317d4da056
Reviewed-on: https://go-review.googlesource.com/c/tools/+/404335
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
2022-05-06 16:24:14 +00:00
Muir Manders fa7afc95f2 lsp/completion: improve generic func arg ranking
In cases like:

    func foo[A int|string](a A) {}

    foo[_](<>)

We now prefer ints and strings at <> by matching against the type
constraint. Note that even if "_" is replaced with "int", we still
prefer strings since the type checker doesn't seem to want to
instantiate foo unless the params check out.

Change-Id: I0e7acfef0775752a96fcfe23e7e2e3d939820eee
Reviewed-on: https://go-review.googlesource.com/c/tools/+/394017
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Auto-Submit: Peter Weinberger <pjw@google.com>
2022-04-22 20:11:24 +00:00
Russ Cox 2bbdb7a52e gopls, internal/lsp: gofmt
Gofmt to update doc comments to the new formatting.

(There are so many files in x/tools I am breaking up the
gofmt'ing into multiple CLs.)

For golang/go#51082.

Change-Id: Ife11502fe1e59a04d53dba9edccd3043e57f9ae8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/399358
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
2022-04-12 17:41:31 +00:00
Muir Manders 09058ab085 internal/lsp/source/completion: add postfix snippet completions
Postfix snippets are artificial methods that allow the user to compose
common operations in an "argument oriented" fashion. For example,
instead of "sort.Slice(someSlice, ...)" a user can expand
"someSlice.sort!". The snippet labels end in "!" to make it clearer
they do something potentially unexpected. The postfix snippets have
low scores so they should not interfere with normal completions.

The snippets are represented (almost) entirely as Go text/template
templates. This way the user can create custom snippets to match their
general preferences or to capture common patterns in their codebase.
There is currently no way for the user to create snippets, but it
could be accomplished with a configuration file, custom LSP command,
or similar.

I started by implementing a variety of snippets to help flesh out the
various facilities needed by the templates. The most interesting
template capabilities are:
 - The ability to import packages as necessary (e.g. "sort" must be
   imported to call sort.Slice()).
 - The ability to generate unique variable names to avoid accidental
   shadowing issues.
 - The ability to weave LSP snippets into the template. Currently,
   only {{.Cursor}} is exposed, which corresponds to the snippet's
   final tab stop.

Briefly, these are the postfix snippets in this commit:
 - foo.sort => sort.Slice(foo, func(...){}) (slices)
 - foo.last => foo[len(foo)-1] (slices)
 - foo.reverse (slices)
 - foo.range => for i, v := range foo {} (slices/maps)
 - foo.append
     This snippet inserts a self-assignment append statement when
     appropriate, otherwise just an append expression.
 - foo.copy creates a copy of a slice
 - foo.clear empties out a map
 - foo.keys creates slice of keys
 - foo().var assigns result value(s) to variables
 - foo.print prints foo to stdout

Some of these are probably not very useful in practice, and I'm sure
there are lots of great ones I didn't think of.

Updates golang/go#39507.

Change-Id: I9ecc748aa79c0d47fa6ff72d4ea671e917a2d5d6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/272586
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2021-03-29 17:27:46 +00:00
Muir Manders a835c872fc internal/lsp/source: omit assign stmt LHS in RHS completion
In the below example:

    fooBar := fooB<>

We will no longer suggest "fooBar" at <>.

Fixes golang/go#39203.

Change-Id: Ie1450397ce3de4f21fb0862c1a4f0fe2812325fd
Reviewed-on: https://go-review.googlesource.com/c/tools/+/275693
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Robert Findley <rfindley@google.com>
2020-12-07 20:43:33 +00:00
Muir Manders ca1c149215 internal/lsp: offer type converted completion candidates
For example:

    func wantsInt64(int64)            {}
    func wantsDuration(time.Duration) {}

    func _() {
      for i := range []string{} {
        // inserts "i" as "int64(i)"
        wantsInt64(i<>)

        // inserts "i" as "time.Duration(i)"
        wantsDuration(i<>)
      }
    }

Type converted candidates have a significant score penalty so they
should never outrank a directly assignable candidate, other factors
being equal.

To minimize false positive completions, we don't offer converted
candidates if either:
- The candidate is a deep completion into another package. This avoids
  random "float64(somepkg.SomeVar)" popping up when completing a
  float64.
- Don't offer to convert ints to strings since that's not normally
  what the user wants.

After going back and forth I decided not to include the type
conversion in the candidate label. This means you will just see the
candidate "i" in the completion popup instead of "float64(i)". Type
names add a lot of noise to the candidate list.

I also tweaked the untyped constant penalty to interplay better with
the new type conversion penalty. I wanted untyped constants to be
ranked above type conversion candidates since they are directly
assignable, so I reduced untyped constants' penalty. However, to
continue suppressing untyped constants from random other packages, I
applied a similar heuristic to above where we give a bigger penalty if
the untyped constant is a deep completion from another package.

Fixes golang/go#42764.

Updates golang/go#39207 (untyped constant penalty tweak may improve
this situation).

Change-Id: I565114b3a1c9628285d07200b9dfc45c61e5d898
Reviewed-on: https://go-review.googlesource.com/c/tools/+/272286
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Trust: Robert Findley <rfindley@google.com>
Trust: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-11-30 20:04:59 +00:00
Danish Dua acefd226e2 internal/lsp/source: move completion to its own package
Completion is slowly becoming a large part of internal/lsp/source and it
makes sense to move to its own seperate package inside source to make
future refactors easier. As a part of this change, any unexported
members from source required by completion are now exported. Util
functions only required by completion are moved from
internal/lsp/source/util.go to internal/lsp/source/completion/util.go.

Change-Id: I6b7405ec598c910545e649bb0e6aa02ffa653b38
Reviewed-on: https://go-review.googlesource.com/c/tools/+/253178
Run-TryBot: Danish Dua <danishdua@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-09-08 19:19:08 +00:00