Skip to content

Commit

Permalink
Support for type aliases
Browse files Browse the repository at this point in the history
Fixes #71 and supercedes #69. Handles the case described in
#69 (comment), i.e.

```
$ cat <<EOF | ./godef -i -o 106
package main
import "encoding/json"
func xxxx() {
    type foo = json.Encoder
    x := new(foo)
    _ = x.Encode
}
EOF
/usr/lib/go-1.10/src/encoding/json/stream.go:195:21
```

i.e. it correctly finds the definition of `x.Encode` (offset 106 is on the `E`)

Also:

```
$ cat <<EOF | ./godef -i -o 91
package main
import "encoding/json"
func xxxx() {
    type foo = json.Encoder
    x := new(foo)
    _ = x.Encode
}
EOF

4:10
```

Where offset 91 is the `f` in `new(foo)` and `4:10` is the `json.Encoder`
  • Loading branch information
Ian Campbell committed Mar 23, 2018
1 parent b692db1 commit 8faf556
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 3 deletions.
1 change: 1 addition & 0 deletions go/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ type (
TypeSpec struct {
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
Assign token.Pos // position of '=', if any
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
Comment *CommentGroup // line comments; or nil
}
Expand Down
6 changes: 5 additions & 1 deletion go/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2027,8 +2027,12 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, decl *ast.GenDecl, _ int) a
// at the identifier in the TypeSpec and ends at the end of the innermost
// containing block.
// (Global identifiers are resolved in a separate phase after parsing.)
spec := &ast.TypeSpec{doc, ident, nil, p.lineComment}
spec := &ast.TypeSpec{doc, ident, token.NoPos, nil, p.lineComment}
p.declare(spec, p.topScope, ast.Typ, ident)
if p.tok == token.ASSIGN {
spec.Assign = p.pos
p.next()
}
typ := p.parseType()
p.expectSemi() // call before accessing p.linecomment
spec.Type = typ
Expand Down
1 change: 1 addition & 0 deletions go/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var validPrograms = []interface{}{
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
`package p; type T []int; type U = T; func f() int { return U{42}[0] };`,
`package p; var a = T{{1, 2}, {3, 4}}`,
`package p; func f() { select { case <- c: case c <- d: case c <- <- d: case <-c <- d: } };`,
`package p; func f() { if ; true {} };`,
Expand Down
12 changes: 10 additions & 2 deletions go/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ func (ctxt *exprTypeContext) exprType(n ast.Node, expectTuple bool, pkg string)
if obj == nil || obj.Kind == ast.Bad {
break
}
// A type object represents itself.
if obj.Kind == ast.Typ {
// A non-aliased type object represents itself.
if obj.Kind == ast.Typ && !isTypeAlias(obj) {
// Objects in the universal scope don't live
// in any package.
if parser.Universe.Lookup(obj.Name) == obj {
Expand Down Expand Up @@ -871,6 +871,14 @@ func isNamedType(typ Type) bool {
return typ.Underlying(false).Node != typ.Node
}

func isTypeAlias(obj *ast.Object) bool {
if obj.Kind != ast.Typ {
return false
}
ts, ok := obj.Decl.(*ast.TypeSpec)
return ok && ts.Assign.IsValid()
}

func fields2type(fields *ast.FieldList) ast.Node {
if fields == nil {
return MultiValue{nil}
Expand Down

0 comments on commit 8faf556

Please sign in to comment.