@@ -21,10 +21,10 @@ import (
21
21
// As such it indicates that other definitions could be worth checking.
22
22
var ErrNoLinkname = errors .New ("no linkname directive found" )
23
23
24
- // LinknameDefinition finds the definition of the linkname directive in fh at pos.
24
+ // LinknameDefinition finds the definition of the linkname directive in m at pos.
25
25
// If there is no linkname directive at pos, returns ErrNoLinkname.
26
- func LinknameDefinition (ctx context.Context , snapshot Snapshot , fh FileHandle , from protocol.Position ) ([]protocol.Location , error ) {
27
- pkgPath , name , _ := parseLinkname (ctx , snapshot , fh , from )
26
+ func LinknameDefinition (ctx context.Context , snapshot Snapshot , m * protocol. Mapper , from protocol.Position ) ([]protocol.Location , error ) {
27
+ pkgPath , name , _ := parseLinkname (m , from )
28
28
if pkgPath == "" {
29
29
return nil , ErrNoLinkname
30
30
}
@@ -44,34 +44,46 @@ func LinknameDefinition(ctx context.Context, snapshot Snapshot, fh FileHandle, f
44
44
// If successful, it returns
45
45
// - package path referenced
46
46
// - object name referenced
47
- // - byte offset in fh of the start of the link target
47
+ // - byte offset in mapped file of the start of the link target
48
48
// of the linkname directives 2nd argument.
49
49
//
50
50
// If the position is not in the second argument of a go:linkname directive,
51
51
// or parsing fails, it returns "", "", 0.
52
- func parseLinkname (ctx context.Context , snapshot Snapshot , fh FileHandle , pos protocol.Position ) (pkgPath , name string , targetOffset int ) {
53
- // TODO(adonovan): opt: parsing isn't necessary here.
54
- // We're only looking for a line comment.
55
- pgf , err := snapshot .ParseGo (ctx , fh , ParseFull )
52
+ func parseLinkname (m * protocol.Mapper , pos protocol.Position ) (pkgPath , name string , targetOffset int ) {
53
+ lineStart , err := m .PositionOffset (protocol.Position {Line : pos .Line , Character : 0 })
56
54
if err != nil {
57
55
return "" , "" , 0
58
56
}
59
-
60
- offset , err := pgf .Mapper .PositionOffset (pos )
57
+ lineEnd , err := m .PositionOffset (protocol.Position {Line : pos .Line + 1 , Character : 0 })
61
58
if err != nil {
62
59
return "" , "" , 0
63
60
}
64
61
62
+ directive := string (m .Content [lineStart :lineEnd ])
63
+ // (Assumes no leading spaces.)
64
+ if ! strings .HasPrefix (directive , "//go:linkname" ) {
65
+ return "" , "" , 0
66
+ }
67
+ // Sometimes source code (typically tests) has another
68
+ // comment after the directive, trim that away.
69
+ if i := strings .LastIndex (directive , "//" ); i != 0 {
70
+ directive = strings .TrimSpace (directive [:i ])
71
+ }
72
+
65
73
// Looking for pkgpath in '//go:linkname f pkgpath.g'.
66
74
// (We ignore 1-arg linkname directives.)
67
- directive , end := findLinknameAtOffset (pgf , offset )
68
75
parts := strings .Fields (directive )
69
76
if len (parts ) != 3 {
70
77
return "" , "" , 0
71
78
}
72
79
73
80
// Inside 2nd arg [start, end]?
74
81
// (Assumes no trailing spaces.)
82
+ offset , err := m .PositionOffset (pos )
83
+ if err != nil {
84
+ return "" , "" , 0
85
+ }
86
+ end := lineStart + len (directive )
75
87
start := end - len (parts [2 ])
76
88
if ! (start <= offset && offset <= end ) {
77
89
return "" , "" , 0
@@ -87,31 +99,6 @@ func parseLinkname(ctx context.Context, snapshot Snapshot, fh FileHandle, pos pr
87
99
return linkname [:dot ], linkname [dot + 1 :], start
88
100
}
89
101
90
- // findLinknameAtOffset returns the first linkname directive on line and its end offset.
91
- // Returns "", 0 if the offset is not in a linkname directive.
92
- func findLinknameAtOffset (pgf * ParsedGoFile , offset int ) (string , int ) {
93
- for _ , grp := range pgf .File .Comments {
94
- for _ , com := range grp .List {
95
- if strings .HasPrefix (com .Text , "//go:linkname" ) {
96
- p := safetoken .Position (pgf .Tok , com .Pos ())
97
-
98
- // Sometimes source code (typically tests) has another
99
- // comment after the directive, trim that away.
100
- text := com .Text
101
- if i := strings .LastIndex (text , "//" ); i != 0 {
102
- text = strings .TrimSpace (text [:i ])
103
- }
104
-
105
- end := p .Offset + len (text )
106
- if p .Offset <= offset && offset < end {
107
- return text , end
108
- }
109
- }
110
- }
111
- }
112
- return "" , 0
113
- }
114
-
115
102
// findLinkname searches dependencies of packages containing fh for an object
116
103
// with linker name matching the given package path and name.
117
104
func findLinkname (ctx context.Context , snapshot Snapshot , pkgPath PackagePath , name string ) (Package , * ParsedGoFile , token.Pos , error ) {
0 commit comments