mirror of
https://github.com/golang/go
synced 2024-11-18 16:04:44 -07:00
internal/lsp: fix for limitations of export data
It is impossible to reconstruct a line and column correctly from export data, so we have to attempt to find open and process the file in order to guess what the original pos was when we have one that originated in export data. This occurs in any time in go to definition when the target is not in the same pacakge as the source. Change-Id: Ib2ee404d4f1c39d8bd7f1fbc2096d8d6cbeed6f8 Reviewed-on: https://go-review.googlesource.com/c/150044 Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
d1f8dbfb0b
commit
1aef897494
@ -17,9 +17,9 @@ import (
|
||||
)
|
||||
|
||||
func (p Position) Format(f fmt.State, c rune) {
|
||||
fmt.Fprintf(f, "%d", int(p.Line))
|
||||
fmt.Fprintf(f, "%d", int(p.Line)+1)
|
||||
if p.Character >= 0 {
|
||||
fmt.Fprintf(f, ":%d", int(p.Character))
|
||||
fmt.Fprintf(f, ":%d", int(p.Character)+1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ func (r Range) Format(f fmt.State, c rune) {
|
||||
case r.Start == r.End || r.End.Line < 0:
|
||||
fmt.Fprintf(f, "%v", r.Start)
|
||||
case r.End.Line == r.Start.Line:
|
||||
fmt.Fprintf(f, "%v¦%d", r.Start, int(r.End.Character))
|
||||
fmt.Fprintf(f, "%v¦%d", r.Start, int(r.End.Character)+1)
|
||||
default:
|
||||
fmt.Fprintf(f, "%v¦%v", r.Start, r.End)
|
||||
}
|
||||
|
@ -5,11 +5,13 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
)
|
||||
@ -43,10 +45,7 @@ func Definition(ctx context.Context, f *File, pos token.Pos) (Range, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return Range{
|
||||
Start: obj.Pos(),
|
||||
End: obj.Pos() + token.Pos(len([]byte(obj.Name()))), // TODO: use real range of obj
|
||||
}, nil
|
||||
return objToRange(f.view.Config.Fset, obj), nil
|
||||
}
|
||||
|
||||
// ident returns the ident plus any extra information needed
|
||||
@ -93,3 +92,30 @@ func checkIdentifier(f *ast.File, pos token.Pos) (ident, error) {
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func objToRange(fSet *token.FileSet, obj types.Object) Range {
|
||||
p := obj.Pos()
|
||||
f := fSet.File(p)
|
||||
pos := f.Position(p)
|
||||
if pos.Column == 1 {
|
||||
// Column is 1, so we probably do not have full position information
|
||||
// Currently exportdata does not store the column.
|
||||
// For now we attempt to read the original source and find the identifier
|
||||
// within the line. If we find it we patch the column to match its offset.
|
||||
// TODO: we have probably already added the full data for the file to the
|
||||
// fileset, we ought to track it rather than adding it over and over again
|
||||
// TODO: if we parse from source, we will never need this hack
|
||||
if src, err := ioutil.ReadFile(pos.Filename); err == nil {
|
||||
newF := fSet.AddFile(pos.Filename, -1, len(src))
|
||||
newF.SetLinesForContent(src)
|
||||
lineStart := lineStart(newF, pos.Line)
|
||||
offset := newF.Offset(lineStart)
|
||||
col := bytes.Index(src[offset:], []byte(obj.Name()))
|
||||
p = newF.Pos(offset + col)
|
||||
}
|
||||
}
|
||||
return Range{
|
||||
Start: p,
|
||||
End: p + token.Pos(len([]byte(obj.Name()))), // TODO: use real range of obj
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user