mirror of
https://github.com/golang/go
synced 2024-11-19 02:04:42 -07:00
0a33398bd9
Modified the way highlights are tested to allow for author to explicitly mark the matches. Also added highlighting for fields and methods. Used type checking in addition to ast to get better matching. Worked with @stamblerre Updates #34496 Change-Id: I462703e0011c4e0a4b98016e9c25af9bf1ead0b9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/207899 Run-TryBot: Rohan Challa <rohan@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
// Copyright 2019 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 source
|
|
|
|
import (
|
|
"context"
|
|
"go/ast"
|
|
|
|
"golang.org/x/tools/go/ast/astutil"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
"golang.org/x/tools/internal/span"
|
|
"golang.org/x/tools/internal/telemetry/trace"
|
|
errors "golang.org/x/xerrors"
|
|
)
|
|
|
|
func Highlight(ctx context.Context, view View, uri span.URI, pos protocol.Position) ([]protocol.Range, error) {
|
|
ctx, done := trace.StartSpan(ctx, "source.Highlight")
|
|
defer done()
|
|
|
|
f, err := view.GetFile(ctx, uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, cphs, err := view.CheckPackageHandles(ctx, f)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cph, err := WidestCheckPackageHandle(cphs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pkg, err := cph.Check(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var ph ParseGoHandle
|
|
for _, file := range pkg.Files() {
|
|
if file.File().Identity().URI == f.URI() {
|
|
ph = file
|
|
}
|
|
}
|
|
if ph == nil {
|
|
return nil, errors.Errorf("no ParseGoHandle for %s", f.URI())
|
|
}
|
|
file, m, _, err := ph.Parse(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
spn, err := m.PointSpan(pos)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rng, err := spn.Range(m.Converter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
path, _ := astutil.PathEnclosingInterval(file, rng.Start, rng.Start)
|
|
if len(path) == 0 {
|
|
return nil, errors.Errorf("no enclosing position found for %v:%v", int(pos.Line), int(pos.Character))
|
|
}
|
|
result := []protocol.Range{}
|
|
id, ok := path[0].(*ast.Ident)
|
|
if !ok {
|
|
// If the cursor is not within an identifier, return empty results.
|
|
return result, nil
|
|
}
|
|
idObj := pkg.GetTypesInfo().ObjectOf(id)
|
|
|
|
ast.Inspect(path[len(path)-1], func(node ast.Node) bool {
|
|
n, ok := node.(*ast.Ident)
|
|
if !ok {
|
|
return true
|
|
}
|
|
if n.Name != id.Name {
|
|
return true
|
|
}
|
|
if n.Obj != id.Obj {
|
|
return true
|
|
}
|
|
|
|
nodeObj := pkg.GetTypesInfo().ObjectOf(n)
|
|
if nodeObj != idObj {
|
|
return false
|
|
}
|
|
|
|
if rng, err := nodeToProtocolRange(ctx, view, m, n); err == nil {
|
|
result = append(result, rng)
|
|
}
|
|
return true
|
|
})
|
|
return result, nil
|
|
}
|