mirror of
https://github.com/golang/go
synced 2024-11-18 10:14:45 -07:00
x/tools: support Go 1.9 type aliases
For #18130. Change-Id: Ice695602619dbbf851af970e790f07ff2ac2c141 Reviewed-on: https://go-review.googlesource.com/36623 Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
8524ce5143
commit
6e7ee5a9ec
@ -327,9 +327,9 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
|||||||
return nil, fmt.Errorf("unexpected AST for expr: %T", n)
|
return nil, fmt.Errorf("unexpected AST for expr: %T", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
t := qpos.info.TypeOf(expr)
|
typ := qpos.info.TypeOf(expr)
|
||||||
if t == nil {
|
if typ == nil {
|
||||||
t = types.Typ[types.Invalid]
|
typ = types.Typ[types.Invalid]
|
||||||
}
|
}
|
||||||
constVal := qpos.info.Types[expr].Value
|
constVal := qpos.info.Types[expr].Value
|
||||||
if c, ok := obj.(*types.Const); ok {
|
if c, ok := obj.(*types.Const); ok {
|
||||||
@ -339,11 +339,11 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
|||||||
return &describeValueResult{
|
return &describeValueResult{
|
||||||
qpos: qpos,
|
qpos: qpos,
|
||||||
expr: expr,
|
expr: expr,
|
||||||
typ: t,
|
typ: typ,
|
||||||
constVal: constVal,
|
constVal: constVal,
|
||||||
obj: obj,
|
obj: obj,
|
||||||
methods: accessibleMethods(t, qpos.info.Pkg),
|
methods: accessibleMethods(typ, qpos.info.Pkg),
|
||||||
fields: accessibleFields(t, qpos.info.Pkg),
|
fields: accessibleFields(typ, qpos.info.Pkg),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,48 +425,46 @@ func (r *describeValueResult) JSON(fset *token.FileSet) []byte {
|
|||||||
|
|
||||||
func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
|
func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
|
||||||
var description string
|
var description string
|
||||||
var t types.Type
|
var typ types.Type
|
||||||
switch n := path[0].(type) {
|
switch n := path[0].(type) {
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
t = qpos.info.TypeOf(n)
|
obj := qpos.info.ObjectOf(n).(*types.TypeName)
|
||||||
switch t := t.(type) {
|
typ = obj.Type()
|
||||||
case *types.Basic:
|
if isAlias(obj) {
|
||||||
|
description = "alias of "
|
||||||
|
} else if obj.Pos() == n.Pos() {
|
||||||
|
description = "definition of " // (Named type)
|
||||||
|
} else if _, ok := typ.(*types.Basic); ok {
|
||||||
description = "reference to built-in "
|
description = "reference to built-in "
|
||||||
|
} else {
|
||||||
case *types.Named:
|
description = "reference to " // (Named type)
|
||||||
isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
|
|
||||||
if isDef {
|
|
||||||
description = "definition of "
|
|
||||||
} else {
|
|
||||||
description = "reference to "
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case ast.Expr:
|
case ast.Expr:
|
||||||
t = qpos.info.TypeOf(n)
|
typ = qpos.info.TypeOf(n)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Unreachable?
|
// Unreachable?
|
||||||
return nil, fmt.Errorf("unexpected AST for type: %T", n)
|
return nil, fmt.Errorf("unexpected AST for type: %T", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
description = description + "type " + qpos.typeString(t)
|
description = description + "type " + qpos.typeString(typ)
|
||||||
|
|
||||||
// Show sizes for structs and named types (it's fairly obvious for others).
|
// Show sizes for structs and named types (it's fairly obvious for others).
|
||||||
switch t.(type) {
|
switch typ.(type) {
|
||||||
case *types.Named, *types.Struct:
|
case *types.Named, *types.Struct:
|
||||||
szs := types.StdSizes{WordSize: 8, MaxAlign: 8} // assume amd64
|
szs := types.StdSizes{WordSize: 8, MaxAlign: 8} // assume amd64
|
||||||
description = fmt.Sprintf("%s (size %d, align %d)", description,
|
description = fmt.Sprintf("%s (size %d, align %d)", description,
|
||||||
szs.Sizeof(t), szs.Alignof(t))
|
szs.Sizeof(typ), szs.Alignof(typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &describeTypeResult{
|
return &describeTypeResult{
|
||||||
qpos: qpos,
|
qpos: qpos,
|
||||||
node: path[0],
|
node: path[0],
|
||||||
description: description,
|
description: description,
|
||||||
typ: t,
|
typ: typ,
|
||||||
methods: accessibleMethods(t, qpos.info.Pkg),
|
methods: accessibleMethods(typ, qpos.info.Pkg),
|
||||||
fields: accessibleFields(t, qpos.info.Pkg),
|
fields: accessibleFields(typ, qpos.info.Pkg),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,23 +670,29 @@ func formatMember(obj types.Object, maxname int) string {
|
|||||||
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
||||||
|
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
|
typ := obj.Type()
|
||||||
|
if isAlias(obj) {
|
||||||
|
buf.WriteString(" = ")
|
||||||
|
} else {
|
||||||
|
buf.WriteByte(' ')
|
||||||
|
typ = typ.Underlying()
|
||||||
|
}
|
||||||
|
var typestr string
|
||||||
// Abbreviate long aggregate type names.
|
// Abbreviate long aggregate type names.
|
||||||
var abbrev string
|
switch typ := typ.(type) {
|
||||||
switch t := obj.Type().Underlying().(type) {
|
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
if t.NumMethods() > 1 {
|
if typ.NumMethods() > 1 {
|
||||||
abbrev = "interface{...}"
|
typestr = "interface{...}"
|
||||||
}
|
}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
if t.NumFields() > 1 {
|
if typ.NumFields() > 1 {
|
||||||
abbrev = "struct{...}"
|
typestr = "struct{...}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if abbrev == "" {
|
if typestr == "" {
|
||||||
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
|
typestr = types.TypeString(typ, qualifier)
|
||||||
} else {
|
|
||||||
fmt.Fprintf(&buf, " %s", abbrev)
|
|
||||||
}
|
}
|
||||||
|
buf.WriteString(typestr)
|
||||||
|
|
||||||
case *types.Var:
|
case *types.Var:
|
||||||
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
|
||||||
@ -699,20 +703,26 @@ func formatMember(obj types.Object, maxname int) string {
|
|||||||
func (r *describePackageResult) JSON(fset *token.FileSet) []byte {
|
func (r *describePackageResult) JSON(fset *token.FileSet) []byte {
|
||||||
var members []*serial.DescribeMember
|
var members []*serial.DescribeMember
|
||||||
for _, mem := range r.members {
|
for _, mem := range r.members {
|
||||||
typ := mem.obj.Type()
|
obj := mem.obj
|
||||||
|
typ := obj.Type()
|
||||||
var val string
|
var val string
|
||||||
switch mem := mem.obj.(type) {
|
var alias string
|
||||||
|
switch obj := obj.(type) {
|
||||||
case *types.Const:
|
case *types.Const:
|
||||||
val = mem.Val().String()
|
val = obj.Val().String()
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
typ = typ.Underlying()
|
if isAlias(obj) {
|
||||||
|
alias = "= " // kludgy
|
||||||
|
} else {
|
||||||
|
typ = typ.Underlying()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
members = append(members, &serial.DescribeMember{
|
members = append(members, &serial.DescribeMember{
|
||||||
Name: mem.obj.Name(),
|
Name: obj.Name(),
|
||||||
Type: typ.String(),
|
Type: alias + typ.String(),
|
||||||
Value: val,
|
Value: val,
|
||||||
Pos: fset.Position(mem.obj.Pos()).String(),
|
Pos: fset.Position(obj.Pos()).String(),
|
||||||
Kind: tokenOf(mem.obj),
|
Kind: tokenOf(obj),
|
||||||
Methods: methodsToSerial(r.pkg, mem.methods, fset),
|
Methods: methodsToSerial(r.pkg, mem.methods, fset),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,7 @@ func TestGuru(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, filename := range []string{
|
for _, filename := range []string{
|
||||||
|
"testdata/src/alias/alias.go", // iff guru.HasAlias (go1.9)
|
||||||
"testdata/src/calls/main.go",
|
"testdata/src/calls/main.go",
|
||||||
"testdata/src/describe/main.go",
|
"testdata/src/describe/main.go",
|
||||||
"testdata/src/freevars/main.go",
|
"testdata/src/freevars/main.go",
|
||||||
@ -248,6 +249,9 @@ func TestGuru(t *testing.T) {
|
|||||||
// wording for a "no such file or directory" error.
|
// wording for a "no such file or directory" error.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if filename == "testdata/src/alias/alias.go" && !guru.HasAlias {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
json := strings.Contains(filename, "-json/")
|
json := strings.Contains(filename, "-json/")
|
||||||
queries := parseQueries(t, filename)
|
queries := parseQueries(t, filename)
|
||||||
|
@ -102,16 +102,20 @@ func implements(q *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find all named types, even local types (which can have
|
// Find all named types, even local types (which can have
|
||||||
// methods via promotion) and the built-in "error".
|
// methods due to promotion) and the built-in "error".
|
||||||
var allNamed []types.Type
|
// We ignore aliases 'type M = N' to avoid duplicate
|
||||||
|
// reporting of the Named type N.
|
||||||
|
var allNamed []*types.Named
|
||||||
for _, info := range lprog.AllPackages {
|
for _, info := range lprog.AllPackages {
|
||||||
for _, obj := range info.Defs {
|
for _, obj := range info.Defs {
|
||||||
if obj, ok := obj.(*types.TypeName); ok {
|
if obj, ok := obj.(*types.TypeName); ok && !isAlias(obj) {
|
||||||
allNamed = append(allNamed, obj.Type())
|
if named, ok := obj.Type().(*types.Named); ok {
|
||||||
|
allNamed = append(allNamed, named)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allNamed = append(allNamed, types.Universe.Lookup("error").Type())
|
allNamed = append(allNamed, types.Universe.Lookup("error").Type().(*types.Named))
|
||||||
|
|
||||||
var msets typeutil.MethodSetCache
|
var msets typeutil.MethodSetCache
|
||||||
|
|
||||||
|
15
cmd/guru/isAlias18.go
Normal file
15
cmd/guru/isAlias18.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.9
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
func isAlias(obj *types.TypeName) bool {
|
||||||
|
return false // there are no type aliases before Go 1.9
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasAlias = false
|
15
cmd/guru/isAlias19.go
Normal file
15
cmd/guru/isAlias19.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
func isAlias(obj *types.TypeName) bool {
|
||||||
|
return obj.IsAlias()
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasAlias = true
|
20
cmd/guru/testdata/src/alias/alias.go
vendored
Normal file
20
cmd/guru/testdata/src/alias/alias.go
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Tests of Go 1.9 type aliases.
|
||||||
|
// See go.tools/guru/guru_test.go for explanation.
|
||||||
|
// See alias.golden for expected query results.
|
||||||
|
|
||||||
|
package alias // @describe describe-pkg "alias"
|
||||||
|
|
||||||
|
type I interface{ f() } // @implements implements-I "I"
|
||||||
|
|
||||||
|
type N int
|
||||||
|
func (N) f() {}
|
||||||
|
|
||||||
|
type M = N // @describe describe-def-M "M"
|
||||||
|
var m M // @describe describe-ref-M "M"
|
||||||
|
|
||||||
|
type O N // @describe describe-O "O"
|
||||||
|
|
||||||
|
type P = struct{N} // @describe describe-P "N"
|
||||||
|
|
||||||
|
type U = undefined // @describe describe-U "U"
|
||||||
|
type _ = undefined // @describe describe-undefined "undefined"
|
47
cmd/guru/testdata/src/alias/alias.golden
vendored
Normal file
47
cmd/guru/testdata/src/alias/alias.golden
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
-------- @describe describe-pkg --------
|
||||||
|
definition of package "alias"
|
||||||
|
type I interface{f()}
|
||||||
|
method (I) f()
|
||||||
|
type M = N
|
||||||
|
method (N) f()
|
||||||
|
type N int
|
||||||
|
method (N) f()
|
||||||
|
type O int
|
||||||
|
type P = struct{N}
|
||||||
|
method (struct{N}) f()
|
||||||
|
type U = invalid type
|
||||||
|
var m N
|
||||||
|
|
||||||
|
-------- @implements implements-I --------
|
||||||
|
interface type I
|
||||||
|
is implemented by basic type N
|
||||||
|
|
||||||
|
-------- @describe describe-def-M --------
|
||||||
|
alias of type N (size 8, align 8)
|
||||||
|
defined as int
|
||||||
|
Methods:
|
||||||
|
method (N) f()
|
||||||
|
|
||||||
|
-------- @describe describe-ref-M --------
|
||||||
|
alias of type N (size 8, align 8)
|
||||||
|
defined as int
|
||||||
|
Methods:
|
||||||
|
method (N) f()
|
||||||
|
|
||||||
|
-------- @describe describe-O --------
|
||||||
|
definition of type O (size 8, align 8)
|
||||||
|
No methods.
|
||||||
|
|
||||||
|
-------- @describe describe-P --------
|
||||||
|
type struct{N} (size 8, align 8)
|
||||||
|
Methods:
|
||||||
|
method (struct{N}) f()
|
||||||
|
Fields:
|
||||||
|
N N
|
||||||
|
|
||||||
|
-------- @describe describe-U --------
|
||||||
|
alias of type invalid type
|
||||||
|
|
||||||
|
-------- @describe describe-undefined --------
|
||||||
|
identifier
|
||||||
|
|
54
cmd/guru/testdata/src/alias/main.golden
vendored
54
cmd/guru/testdata/src/alias/main.golden
vendored
@ -1,54 +0,0 @@
|
|||||||
-------- @describe pkg --------
|
|
||||||
definition of package "alias"
|
|
||||||
type S1 struct{aliaslib.T}
|
|
||||||
method (S1) Method(x *int) *int
|
|
||||||
type S2 struct{aliaslib.T}
|
|
||||||
method (S2) Method(x *int) *int
|
|
||||||
alias bad1 => ?
|
|
||||||
alias bad2 => ?
|
|
||||||
const c_ => aliaslib.C
|
|
||||||
func f_ => aliaslib.F
|
|
||||||
type t_ => aliaslib.T
|
|
||||||
var v_ => aliaslib.V
|
|
||||||
var x aliaslib.T
|
|
||||||
|
|
||||||
-------- @describe bad1 --------
|
|
||||||
identifier
|
|
||||||
|
|
||||||
-------- @describe bad2 --------
|
|
||||||
identifier
|
|
||||||
|
|
||||||
-------- @describe v --------
|
|
||||||
definition of var alias v_ int
|
|
||||||
|
|
||||||
-------- @describe t --------
|
|
||||||
alias of type aliaslib.T (size 8, align 8)
|
|
||||||
defined as int
|
|
||||||
Methods:
|
|
||||||
method (T) Method(x *int) *int
|
|
||||||
|
|
||||||
-------- @describe c --------
|
|
||||||
definition of const alias c_ untyped int of value 3
|
|
||||||
|
|
||||||
-------- @describe f --------
|
|
||||||
definition of func alias f_ func()
|
|
||||||
|
|
||||||
-------- @describe s1-field --------
|
|
||||||
reference to field T aliaslib.T
|
|
||||||
defined here
|
|
||||||
Methods:
|
|
||||||
method (T) Method(x *int) *int
|
|
||||||
|
|
||||||
-------- @describe s2-field --------
|
|
||||||
type struct{aliaslib.T} (size 8, align 8)
|
|
||||||
Methods:
|
|
||||||
method (struct{T}) Method(x *int) *int
|
|
||||||
Fields:
|
|
||||||
t_ aliaslib.T
|
|
||||||
|
|
||||||
-------- @describe var-x --------
|
|
||||||
alias of type aliaslib.T (size 8, align 8)
|
|
||||||
defined as int
|
|
||||||
Methods:
|
|
||||||
method (T) Method(x *int) *int
|
|
||||||
|
|
11
cmd/guru/testdata/src/aliaslib/aliaslib.go
vendored
11
cmd/guru/testdata/src/aliaslib/aliaslib.go
vendored
@ -1,11 +0,0 @@
|
|||||||
package aliaslib
|
|
||||||
|
|
||||||
type T int
|
|
||||||
|
|
||||||
func (T) Method(x *int) *int
|
|
||||||
|
|
||||||
func F()
|
|
||||||
|
|
||||||
const C = 3
|
|
||||||
|
|
||||||
var V = 0
|
|
@ -181,11 +181,9 @@ func whicherrs(q *Query) error {
|
|||||||
// typeswitch or assert to. This means finding out
|
// typeswitch or assert to. This means finding out
|
||||||
// if the type pointed to can be seen by us.
|
// if the type pointed to can be seen by us.
|
||||||
//
|
//
|
||||||
// For the purposes of this analysis, the type is always
|
// For the purposes of this analysis, we care only about
|
||||||
// either a Named type or a pointer to one.
|
// TypeNames of Named or pointer-to-Named types.
|
||||||
// There are cases where error can be implemented
|
// We ignore other types (e.g. structs) that implement error.
|
||||||
// by unnamed types, but in that case, we can't assert to
|
|
||||||
// it, so we don't care about it for this analysis.
|
|
||||||
var name *types.TypeName
|
var name *types.TypeName
|
||||||
switch t := conc.(type) {
|
switch t := conc.(type) {
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
|
@ -195,9 +195,10 @@ func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *
|
|||||||
obj := scope.Lookup(name)
|
obj := scope.Lookup(name)
|
||||||
memberFromObject(p, obj, nil)
|
memberFromObject(p, obj, nil)
|
||||||
if obj, ok := obj.(*types.TypeName); ok {
|
if obj, ok := obj.(*types.TypeName); ok {
|
||||||
named := obj.Type().(*types.Named)
|
if named, ok := obj.Type().(*types.Named); ok {
|
||||||
for i, n := 0, named.NumMethods(); i < n; i++ {
|
for i, n := 0, named.NumMethods(); i < n; i++ {
|
||||||
memberFromObject(p, named.Method(i), nil)
|
memberFromObject(p, named.Method(i), nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,7 @@ func ext۰runtime۰Func۰Entry(fr *frame, args []value) value {
|
|||||||
|
|
||||||
// This is a workaround for a bug in go/ssa/testmain.go: it creates
|
// This is a workaround for a bug in go/ssa/testmain.go: it creates
|
||||||
// InternalExamples even for Example functions with no Output comment.
|
// InternalExamples even for Example functions with no Output comment.
|
||||||
// TODO(adonovan): fix (and redesign) testmain.go after Go 1.6.
|
// TODO(adonovan): fix (and redesign) testmain.go..
|
||||||
func ext۰testing۰runExample(fr *frame, args []value) value {
|
func ext۰testing۰runExample(fr *frame, args []value) value {
|
||||||
// This is a stripped down runExample that simply calls the function.
|
// This is a stripped down runExample that simply calls the function.
|
||||||
// It does not capture and compare output nor recover from panic.
|
// It does not capture and compare output nor recover from panic.
|
||||||
@ -448,7 +448,7 @@ func ext۰testing۰runExample(fr *frame, args []value) value {
|
|||||||
|
|
||||||
func ext۰time۰now(fr *frame, args []value) value {
|
func ext۰time۰now(fr *frame, args []value) value {
|
||||||
nano := time.Now().UnixNano()
|
nano := time.Now().UnixNano()
|
||||||
return tuple{int64(nano / 1e9), int32(nano % 1e9), 0}
|
return tuple{int64(nano / 1e9), int32(nano % 1e9), int64(0)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ext۰time۰Sleep(fr *frame, args []value) value {
|
func ext۰time۰Sleep(fr *frame, args []value) value {
|
||||||
|
@ -75,9 +75,6 @@ type Member interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A Type is a Member of a Package representing a package-level named type.
|
// A Type is a Member of a Package representing a package-level named type.
|
||||||
//
|
|
||||||
// Type() returns a *types.Named.
|
|
||||||
//
|
|
||||||
type Type struct {
|
type Type struct {
|
||||||
object *types.TypeName
|
object *types.TypeName
|
||||||
pkg *Package
|
pkg *Package
|
||||||
|
@ -101,14 +101,16 @@ func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Na
|
|||||||
// IMPLEMENTS & METHOD SETS
|
// IMPLEMENTS & METHOD SETS
|
||||||
for _, obj := range info.Defs {
|
for _, obj := range info.Defs {
|
||||||
if obj, ok := obj.(*types.TypeName); ok {
|
if obj, ok := obj.(*types.TypeName); ok {
|
||||||
a.namedType(obj, implements)
|
if named, ok := obj.Type().(*types.Named); ok {
|
||||||
|
a.namedType(named, implements)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) {
|
func (a *analysis) namedType(T *types.Named, implements map[*types.Named]implementsFacts) {
|
||||||
|
obj := T.Obj()
|
||||||
qualifier := types.RelativeTo(obj.Pkg())
|
qualifier := types.RelativeTo(obj.Pkg())
|
||||||
T := obj.Type().(*types.Named)
|
|
||||||
v := &TypeInfoJSON{
|
v := &TypeInfoJSON{
|
||||||
Name: obj.Name(),
|
Name: obj.Name(),
|
||||||
Size: sizes.Sizeof(T),
|
Size: sizes.Sizeof(T),
|
||||||
|
Loading…
Reference in New Issue
Block a user