diff --git a/internal/document/document.go b/internal/document/document.go index 91f969e..a5d7985 100644 --- a/internal/document/document.go +++ b/internal/document/document.go @@ -7,8 +7,11 @@ import ( "go/doc" "go/token" "go/types" + "os" "strings" + "sync" + "github.com/charmbracelet/log" "github.com/sourcegraph/scip-go/internal/lookup" "github.com/sourcegraph/scip-go/internal/symbols" "github.com/sourcegraph/scip/bindings/go/scip" @@ -169,7 +172,6 @@ func typeStringForObject(obj types.Object) (signature string, extra string) { case *types.Const: return fmt.Sprintf("%s = %s", types.ObjectString(v, packageQualifier), v.Val()), "" - // TODO: We had this case in previous iterations // case *PkgDeclaration: // return fmt.Sprintf("package %s", v.name), "" @@ -181,23 +183,44 @@ func typeStringForObject(obj types.Object) (signature string, extra string) { return types.ObjectString(obj, packageQualifier), "" } +var loggedGODEBUGWarning sync.Once + // formatTypeSignature returns a brief description of the given struct or interface type. func formatTypeSignature(obj *types.TypeName) string { switch obj.Type().Underlying().(type) { case *types.Struct: if obj.IsAlias() { - switch obj.Type().(type) { - case *types.Named: - original := obj.Type().(*types.Named).Obj() - var pkg string - if obj.Pkg().Name() != original.Pkg().Name() { - pkg = original.Pkg().Name() + "." + switch ty := obj.Type().(type) { + case *types.Alias: + switch rhs := ty.Rhs().(type) { + case *types.Alias: + original := rhs.Obj() + var pkg string + if obj.Pkg().Name() != original.Pkg().Name() { + pkg = original.Pkg().Name() + "." + } + return fmt.Sprintf("type %s = %s%s", obj.Name(), pkg, original.Name()) + case *types.Named: + original := rhs.Obj() + var pkg string + if obj.Pkg().Name() != original.Pkg().Name() { + pkg = original.Pkg().Name() + "." + } + return fmt.Sprintf("type %s = %s%s", obj.Name(), pkg, original.Name()) + case *types.Struct: + return fmt.Sprintf("type %s = struct", obj.Name()) + } + default: + if val := os.Getenv("GODEBUG"); strings.Contains(val, "gotypealias=0") { + loggedGODEBUGWarning.Do(func() { + log.Warn("Running with GODEBUG=gotypealias=0, this may cause incorrect hover docs") + }) + } else { + log.Warn("IsAlias() is true but Type() is not Alias; please report this as a bug", + "obj", obj.String(), "obj.Type()", ty.String()) } - return fmt.Sprintf("type %s = %s%s", obj.Name(), pkg, original.Name()) - - case *types.Struct: - return fmt.Sprintf("type %s = struct", obj.Name()) } + } return fmt.Sprintf("type %s struct", obj.Name()) diff --git a/internal/testdata/snapshots/input/alias/main.go b/internal/testdata/snapshots/input/alias/main.go index d19f558..b4d2db7 100644 --- a/internal/testdata/snapshots/input/alias/main.go +++ b/internal/testdata/snapshots/input/alias/main.go @@ -5,5 +5,9 @@ package main type ( T struct{} U = T + V = U S U + Z int32 ) + +func f(u U) {} diff --git a/internal/testdata/snapshots/output/alias/main.go b/internal/testdata/snapshots/output/alias/main.go index 80e406b..dbf2548 100755 --- a/internal/testdata/snapshots/output/alias/main.go +++ b/internal/testdata/snapshots/output/alias/main.go @@ -23,7 +23,7 @@ // ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# // documentation // > ```go -// > type U struct +// > type U = T // > ``` // documentation // > Check that we don't panic @@ -33,6 +33,20 @@ // > struct{} // > ``` // ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/T# + V = U +// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/V# +// documentation +// > ```go +// > type V = U +// > ``` +// documentation +// > Check that we don't panic +// > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 +// documentation +// > ```go +// > struct{} +// > ``` +// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# S U // ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/S# // documentation @@ -47,5 +61,23 @@ // > struct{} // > ``` // ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# + Z int32 +// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/Z# +// documentation +// > Check that we don't panic +// > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 +// documentation +// > ```go +// > int32 +// > ``` ) + func f(u U) {} +// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). +// documentation +// > ```go +// > func f(u U) +// > ``` +// ^ definition local 0 +// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# + diff --git a/internal/testdata/snapshots/output/testdata/data.go b/internal/testdata/snapshots/output/testdata/data.go index 13f121f..3e82e8e 100755 --- a/internal/testdata/snapshots/output/testdata/data.go +++ b/internal/testdata/snapshots/output/testdata/data.go @@ -244,7 +244,7 @@ // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/TestEqualsStruct# // documentation // > ```go -// > type TestEqualsStruct struct +// > type TestEqualsStruct = struct // > ``` // documentation // > ```go diff --git a/internal/testdata/snapshots/output/testdata/typealias.go b/internal/testdata/snapshots/output/testdata/typealias.go index a1f652e..db0228f 100755 --- a/internal/testdata/snapshots/output/testdata/typealias.go +++ b/internal/testdata/snapshots/output/testdata/typealias.go @@ -11,7 +11,7 @@ // ^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/SecretBurger# // documentation // > ```go -// > type SecretBurger struct +// > type SecretBurger = secret.Burger // > ``` // documentation // > Type aliased doc @@ -28,7 +28,7 @@ // ^^^^^^^^^ definition 0.1.test `sg/testdata`/BadBurger# // documentation // > ```go -// > type BadBurger struct +// > type BadBurger = struct // > ``` // documentation // > ```go