gopls/internal/golang: implement type definition for builtin types
Currently, type definition queries on builtin types such as int
and bool return no results.
Meanwhile, type definition queries on the builtin "error" return
the same location as a normal definition query - its
fake declaration in {builtin,unsafe}.go.
We should make this behavior consistent across all builtin types
by returning the source declaration for both definition and type
definition queries.
diff --git a/gopls/internal/golang/type_definition.go b/gopls/internal/golang/type_definition.go
index 48b62fe..1e3d2c3 100644
--- a/gopls/internal/golang/type_definition.go
+++ b/gopls/internal/golang/type_definition.go
@@ -69,6 +69,25 @@
if t == nil {
return nil, fmt.Errorf("no enclosing expression has a type")
}
+ if _, ok := t.(*types.Basic); ok {
+ objects, err := objectsAt(pkg.TypesInfo(), cur)
+ if err != nil {
+ return nil, err
+ }
+ obj := objects[0].obj
+ if isBuiltin(obj) {
+ // Returns fake source declaration in {builtin,unsafe}.go.
+ pgf, ident, err := builtinDecl(ctx, snapshot, obj)
+ if err != nil {
+ return nil, err
+ }
+ loc, err := pgf.NodeLocation(ident)
+ if err != nil {
+ return nil, err
+ }
+ return []protocol.Location{loc}, nil
+ }
+ }
tname := typeToObject(t)
if tname == nil {
return nil, fmt.Errorf("cannot find type name from type %s", t)
diff --git a/gopls/internal/test/marker/testdata/typedef/typedef.txt b/gopls/internal/test/marker/testdata/typedef/typedef.txt
index 940b275..1245892 100644
--- a/gopls/internal/test/marker/testdata/typedef/typedef.txt
+++ b/gopls/internal/test/marker/testdata/typedef/typedef.txt
@@ -45,7 +45,7 @@
func F3() (Struct, int, bool, error) { return Struct{}, 0, false, nil }
func F4() (**int, Int, bool, *error) { return nil, 0, false, nil }
func F5() (int, float64, error, Struct) { return 0, 0, nil, Struct{} }
-func F6() (int, float64, ***Struct, error) { return 0, 0, nil, nil }
+func F6() (int, float64, ***Struct, error) { return 0, 0, nil, nil } //@ typedef("int", BUILTIN), typedef("float64", BUILTIN), typedef("error", BUILTIN)
func _() {
F1() //@typedef("F1", Int)
@@ -57,6 +57,7 @@
f := func() Int { return 0 }
f() //@typedef("f", Int)
+ _ = append([]int{1, 2}, 3) //@ typedef("append", BUILTIN)
}
// https://github.com/golang/go/issues/38589#issuecomment-620350922
@@ -77,7 +78,7 @@
// And in this one, it's the composite literal enclosing the
// KeyValueExpr denoted by the colon (which must not be adjacent
- // to either they key or the value!).
+ // to either the key or the value!).
_ = Struct{Field : ""} //@typedef(":", Struct)
}
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
if _, ok := t.(*types.Basic); ok {If `typeToObject` also reported TypeNames for Basic types (currently it does not), would the existing logic do the right thing? ObjectLocation already knows how to handle built-ins.
objects, err := objectsAt(pkg.TypesInfo(), cur)This value of cur comes from L34, not the assignments to the loop variable (also named cur) at L45, so I think the behavior will be inconsistent with other types. I think using typeToObject might be a better solution.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Commit-Queue | +1 |
If `typeToObject` also reported TypeNames for Basic types (currently it does not), would the existing logic do the right thing? ObjectLocation already knows how to handle built-ins.
Added the *types.Basic case to typeToObject
This value of cur comes from L34, not the assignments to the loop variable (also named cur) at L45, so I think the behavior will be inconsistent with other types. I think using typeToObject might be a better solution.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
obj := types.Universe.Lookup(typ.Name())You can kill two stones with one bird: if Lookup returns nil, then the type test will (safely) fail:
```
tname, ok := types.Universe.Lookup(typ.Name()).(*types.TypeName)
```
F5() //@typedef(re"F5()", Struct, BUILTIN, BUILTIN, BUILTIN)This reads nicely, but the marker test currently only checks for set-equality, so neither the order nor cardinality of each item actually matters. (There's an argument that since the LSP result is an ordered list, our tests should use list semantics, at least optionally.)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
You can kill two stones with one bird: if Lookup returns nil, then the type test will (safely) fail:
```
tname, ok := types.Universe.Lookup(typ.Name()).(*types.TypeName)
```
Done
F5() //@typedef(re"F5()", Struct, BUILTIN, BUILTIN, BUILTIN)This reads nicely, but the marker test currently only checks for set-equality, so neither the order nor cardinality of each item actually matters. (There's an argument that since the LSP result is an ordered list, our tests should use list semantics, at least optionally.)
Good to know! I updated the marker test docs as well (a "set" or "list" of locations was actually already specified for every marker except typedef)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +2 |
for set-equality, so the order and cardinality of locations does not matter. Ofspace, not hyphen
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Could you delete the TODO from
`gopls/internal/golang/type_definition.go`
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +2 |
Could you delete the TODO from
`gopls/internal/golang/type_definition.go`
Unresolved.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Commit-Queue | +1 |
Hongxiang JiangCould you delete the TODO from
`gopls/internal/golang/type_definition.go`
Unresolved.
Done
for set-equality, so the order and cardinality of locations does not matter. OfMadeline Kalilspace, not hyphen
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |