@@ -78,55 +78,87 @@ func Definition(ctx context.Context, snapshot Snapshot, fh FileHandle, position
78
78
79
79
// Handle objects with no position: builtin, unsafe.
80
80
if ! obj .Pos ().IsValid () {
81
- var pgf * ParsedGoFile
82
- if obj .Parent () == types .Universe {
83
- // pseudo-package "builtin"
84
- builtinPGF , err := snapshot .BuiltinFile (ctx )
85
- if err != nil {
86
- return nil , err
87
- }
88
- pgf = builtinPGF
89
-
90
- } else if obj .Pkg () == types .Unsafe {
91
- // package "unsafe"
92
- unsafe := snapshot .Metadata ("unsafe" )
93
- if unsafe == nil {
94
- return nil , fmt .Errorf ("no metadata for package 'unsafe'" )
95
- }
96
- uri := unsafe .GoFiles [0 ]
97
- fh , err := snapshot .ReadFile (ctx , uri )
98
- if err != nil {
99
- return nil , err
100
- }
101
- pgf , err = snapshot .ParseGo (ctx , fh , ParseFull &^SkipObjectResolution )
102
- if err != nil {
103
- return nil , err
104
- }
81
+ return builtinDefinition (ctx , snapshot , obj )
82
+ }
105
83
106
- } else {
107
- return nil , bug .Errorf ("internal error: no position for %v" , obj .Name ())
108
- }
109
- // Inv: pgf ∈ {builtin,unsafe}.go
84
+ // Finally, map the object position.
85
+ loc , err := mapPosition (ctx , pkg .FileSet (), snapshot , obj .Pos (), adjustedObjEnd (obj ))
86
+ if err != nil {
87
+ return nil , err
88
+ }
89
+ return []protocol.Location {loc }, nil
90
+ }
110
91
111
- // Use legacy (go/ast) object resolution.
112
- astObj := pgf .File .Scope .Lookup (obj .Name ())
92
+ // builtinDefinition returns the location of the fake source
93
+ // declaration of a built-in in {builtin,unsafe}.go.
94
+ func builtinDefinition (ctx context.Context , snapshot Snapshot , obj types.Object ) ([]protocol.Location , error ) {
95
+ // getDecl returns the file-level declaration of name
96
+ // using legacy (go/ast) object resolution.
97
+ getDecl := func (file * ast.File , name string ) (ast.Node , error ) {
98
+ astObj := file .Scope .Lookup (name )
113
99
if astObj == nil {
114
100
// Every built-in should have documentation syntax.
115
- return nil , bug .Errorf ("internal error: no object for %s" , obj . Name () )
101
+ return nil , bug .Errorf ("internal error: no object for %s" , name )
116
102
}
117
103
decl , ok := astObj .Decl .(ast.Node )
118
104
if ! ok {
119
105
return nil , bug .Errorf ("internal error: no declaration for %s" , obj .Name ())
120
106
}
121
- loc , err := pgf .PosLocation (decl .Pos (), decl .Pos ()+ token .Pos (len (obj .Name ())))
107
+ return decl , nil
108
+ }
109
+
110
+ var (
111
+ pgf * ParsedGoFile
112
+ decl ast.Node
113
+ err error
114
+ )
115
+ if obj .Pkg () == types .Unsafe {
116
+ // package "unsafe":
117
+ // parse $GOROOT/src/unsafe/unsafe.go
118
+ unsafe := snapshot .Metadata ("unsafe" )
119
+ if unsafe == nil {
120
+ return nil , fmt .Errorf ("no metadata for package 'unsafe'" )
121
+ }
122
+ uri := unsafe .GoFiles [0 ]
123
+ fh , err := snapshot .ReadFile (ctx , uri )
122
124
if err != nil {
123
125
return nil , err
124
126
}
125
- return []protocol.Location {loc }, nil
127
+ pgf , err = snapshot .ParseGo (ctx , fh , ParseFull &^SkipObjectResolution )
128
+ if err != nil {
129
+ return nil , err
130
+ }
131
+
132
+ decl , err = getDecl (pgf .File , obj .Name ())
133
+ } else {
134
+ // pseudo-package "builtin":
135
+ // use parsed $GOROOT/src/builtin/builtin.go
136
+ pgf , err = snapshot .BuiltinFile (ctx )
137
+ if err != nil {
138
+ return nil , err
139
+ }
140
+
141
+ if obj .Parent () == types .Universe {
142
+ // built-in function or type
143
+ decl , err = getDecl (pgf .File , obj .Name ())
144
+
145
+ } else if obj .Name () == "Error" {
146
+ // error.Error method
147
+ decl , err = getDecl (pgf .File , "error" )
148
+ if err != nil {
149
+ return nil , err
150
+ }
151
+ decl = decl .(* ast.TypeSpec ).Type .(* ast.InterfaceType ).Methods .List [0 ]
152
+
153
+ } else {
154
+ return nil , bug .Errorf ("unknown built-in %v" , obj )
155
+ }
156
+ }
157
+ if err != nil {
158
+ return nil , err
126
159
}
127
160
128
- // Finally, map the object position.
129
- loc , err := mapPosition (ctx , pkg .FileSet (), snapshot , obj .Pos (), adjustedObjEnd (obj ))
161
+ loc , err := pgf .PosLocation (decl .Pos (), decl .Pos ()+ token .Pos (len (obj .Name ())))
130
162
if err != nil {
131
163
return nil , err
132
164
}
0 commit comments