diff --git a/gopls/internal/regtest/misc/hover_test.go b/gopls/internal/regtest/misc/hover_test.go index 7a361f9150..79e60e2751 100644 --- a/gopls/internal/regtest/misc/hover_test.go +++ b/gopls/internal/regtest/misc/hover_test.go @@ -9,6 +9,7 @@ import ( "testing" . "golang.org/x/tools/internal/lsp/regtest" + "golang.org/x/tools/internal/testenv" ) func TestHoverUnexported(t *testing.T) { @@ -56,3 +57,34 @@ func main() { } }) } + +func TestHoverIntLiteral(t *testing.T) { + testenv.NeedsGo1Point(t, 13) + const source = ` +-- main.go -- +package main + +var ( + bigBin = 0b1001001 +) + +var hex = 0xe34e + +func main() { +} +` + Run(t, source, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + hexExpected := "58190" + got, _ := env.Hover("main.go", env.RegexpSearch("main.go", "hex")) + if got != nil && !strings.Contains(got.Value, hexExpected) { + t.Errorf("Hover: missing expected field '%s'. Got:\n%q", hexExpected, got.Value) + } + + binExpected := "73" + got, _ = env.Hover("main.go", env.RegexpSearch("main.go", "bigBin")) + if got != nil && !strings.Contains(got.Value, binExpected) { + t.Errorf("Hover: missing expected field '%s'. Got:\n%q", binExpected, got.Value) + } + }) +} diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go index be2bfe209b..d3be0989ef 100644 --- a/internal/lsp/source/hover.go +++ b/internal/lsp/source/hover.go @@ -117,6 +117,16 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation, } h.Signature = prefix + h.Signature } + + // Check if the variable is an integer whose value we can present in a more + // user-friendly way, i.e. `var hex = 0xe34e` becomes `var hex = 58190` + if spec, ok := x.(*ast.ValueSpec); ok && len(spec.Values) > 0 { + if lit, ok := spec.Values[0].(*ast.BasicLit); ok && len(spec.Names) > 0 { + val := constant.MakeFromLiteral(types.ExprString(lit), lit.Kind, 0) + h.Signature = fmt.Sprintf("var %s = %s", spec.Names[0], val) + } + } + case types.Object: // If the variable is implicitly declared in a type switch, we need to // manually generate its object string. @@ -454,6 +464,15 @@ func formatVar(node ast.Spec, obj types.Object, decl *ast.GenDecl) *HoverInforma if comment == nil { comment = spec.Comment } + + // We need the AST nodes for variable declarations of basic literals with + // associated values so that we can augment their hover with more information. + if _, ok := obj.(*types.Var); ok && spec.Type == nil && len(spec.Values) > 0 { + if _, ok := spec.Values[0].(*ast.BasicLit); ok { + return &HoverInformation{source: spec, comment: comment} + } + } + return &HoverInformation{source: obj, comment: comment} }