[tools] gopls: add test cases for embedded fields in struct literals

1 view
Skip to first unread message

Hyang-Ah Hana Kim (Gerrit)

unread,
Apr 6, 2026, 5:35:11 PM (2 days ago) Apr 6
to goph...@pubsubhelper.golang.org, Hyang-Ah Hana Kim, golang-co...@googlegroups.com

Hyang-Ah Hana Kim has uploaded the change for review

Commit message

gopls: add test cases for embedded fields in struct literals

Go1.27 supports direct reference to embedded fields in struct literals.
Gopls needs to handle Completion, Hover, Fill Struct,
Go To Definition, Diagnostics.

For golang/go#78553
Change-Id: If20dfc0fbfd41c1b9cb05a87845f3cc739d3e01c

Change diff

diff --git a/gopls/internal/analysis/fillstruct/fillstruct_test.go b/gopls/internal/analysis/fillstruct/fillstruct_test.go
index e0ad83d..41b456c 100644
--- a/gopls/internal/analysis/fillstruct/fillstruct_test.go
+++ b/gopls/internal/analysis/fillstruct/fillstruct_test.go
@@ -11,6 +11,7 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/gopls/internal/analysis/fillstruct"
+ "golang.org/x/tools/internal/testenv"
)

// analyzer allows us to test the fillstruct code action using the analysistest
@@ -34,3 +35,10 @@
testdata := analysistest.TestData()
analysistest.Run(t, testdata, analyzer, "a", "typeparams")
}
+
+func TestIssue9859(t *testing.T) {
+ testenv.NeedsGo1Point(t, 27)
+ t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")
+ testdata := analysistest.TestData()
+ analysistest.Run(t, testdata, analyzer, "issue9859")
+}
diff --git a/gopls/internal/analysis/fillstruct/testdata/src/issue9859/issue9859.go b/gopls/internal/analysis/fillstruct/testdata/src/issue9859/issue9859.go
new file mode 100644
index 0000000..b01bba5
--- /dev/null
+++ b/gopls/internal/analysis/fillstruct/testdata/src/issue9859/issue9859.go
@@ -0,0 +1,18 @@
+// Copyright 2026 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.
+
+package issue9859
+
+type E struct {
+ A int
+}
+
+type T struct {
+ E
+}
+
+// Current behavior: fillstruct thinks E is missing because it only looks at top-level fields.
+// Expected behavior for issue 9859: T{A: 1} should be considered fully populated (or at least A should be recognized).
+// For now, we expect it to report missing fields because it doesn't support the new syntax.
+var _ = T{A: 1} // want `T literal has missing fields`
diff --git a/gopls/internal/test/integration/completion/issue9859_test.go b/gopls/internal/test/integration/completion/issue9859_test.go
new file mode 100644
index 0000000..0db5d39
--- /dev/null
+++ b/gopls/internal/test/integration/completion/issue9859_test.go
@@ -0,0 +1,64 @@
+// Copyright 2026 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.
+
+package completion
+
+import (
+ "testing"
+
+ . "golang.org/x/tools/gopls/internal/test/integration"
+ "golang.org/x/tools/internal/testenv"
+)
+
+// TestIssue9859Completion tests completions for direct reference to embedded fields in struct literals.
+// Ref: go.dev/issues/9859
+func TestIssue9859Completion(t *testing.T) {
+ testenv.NeedsGo1Point(t, 27) // requires at least go1.22 for some features, but gotip is preferred.
+
+ const files = `
+-- go.mod --
+module mod.com
+
+go 1.22
+-- main.go --
+package main
+
+type E1 struct {
+ A int
+}
+
+type E2 struct {
+ E1
+ B int
+}
+
+type T struct {
+ E2
+ C int
+}
+
+func main() {
+ _ = T{
+
+ }
+}
+`
+ Run(t, files, func(t *testing.T, env *Env) {
+ t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")
+
+ env.OpenFile("main.go")
+ env.Await(env.DoneWithOpen())
+
+ // Trigger completion inside T completion.
+ loc := env.RegexpSearch("main.go", `T\{\n\t\t()`)
+ completions := env.Completion(loc)
+
+ // We expect to see fields from embedded structs: A, B, and direct fields: C, E2.
+ want := []string{"A", "B", "C", "E2"}
+ diff := compareCompletionLabels(want, completions.Items)
+ if diff != "" {
+ t.Fatal(diff)
+ }
+ })
+}
diff --git a/gopls/internal/test/integration/diagnostics/issue9859_test.go b/gopls/internal/test/integration/diagnostics/issue9859_test.go
new file mode 100644
index 0000000..a4d19b4
--- /dev/null
+++ b/gopls/internal/test/integration/diagnostics/issue9859_test.go
@@ -0,0 +1,54 @@
+// Copyright 2026 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.
+
+package diagnostics
+
+import (
+ "testing"
+
+ . "golang.org/x/tools/gopls/internal/test/integration"
+ "golang.org/x/tools/internal/testenv"
+)
+
+// TestIssue9859Diagnostics tests that direct reference to embedded fields in struct literals does not produce error diagnostics.
+// Ref: go.dev/issues/9859
+func TestIssue9859Diagnostics(t *testing.T) {
+ testenv.NeedsGo1Point(t, 27)
+
+ const src = `
+-- go.mod --
+module mod.com
+
+go 1.22
+-- main.go --
+package main
+
+type E1 struct {
+ A int
+}
+
+type T struct {
+ E1
+}
+
+func main() {
+ _ = T{
+ A: 1,
+ }
+}
+`
+ Run(t, src, func(t *testing.T, env *Env) {
+ t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")
+
+ env.OpenFile("main.go")
+ env.Await(
+ env.DoneWithOpen(),
+ )
+
+ // Expect no diagnostics (errors) for this file.
+ env.Await(
+ NoDiagnostics(ForFile("main.go")),
+ )
+ })
+}
diff --git a/gopls/internal/test/integration/hover/issue9859_test.go b/gopls/internal/test/integration/hover/issue9859_test.go
new file mode 100644
index 0000000..23137d7
--- /dev/null
+++ b/gopls/internal/test/integration/hover/issue9859_test.go
@@ -0,0 +1,64 @@
+// Copyright 2026 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.
+
+package hover
+
+import (
+ "strings"
+ "testing"
+
+ . "golang.org/x/tools/gopls/internal/test/integration"
+ "golang.org/x/tools/internal/testenv"
+)
+
+// TestIssue9859Hover tests hover for direct reference to embedded fields in struct literals.
+// Ref: go.dev/issues/9859
+func TestIssue9859Hover(t *testing.T) {
+ testenv.NeedsGo1Point(t, 27)
+
+ const src = `
+-- go.mod --
+module mod.com
+
+go 1.22
+-- main.go --
+package main
+
+type E1 struct {
+ A int
+}
+
+type T struct {
+ E1
+}
+
+func main() {
+ _ = T{
+ A: 1,
+ }
+}
+`
+ Run(t, src, func(t *testing.T, env *Env) {
+ t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")
+
+ env.OpenFile("main.go")
+ env.Await(env.DoneWithOpen())
+
+ // Search for "A" in the struct literal.
+ // We need to be specific to match the "A" in "A: 1".
+ loc := env.RegexpSearch("main.go", `\bA\b:`)
+ // The search returns the range for "A:". We want to hover over "A".
+ loc.Range.End.Character = loc.Range.Start.Character + 1
+
+ content, _ := env.Hover(loc)
+
+ if content == nil {
+ t.Fatal("hover returned nil")
+ }
+
+ if !strings.Contains(content.Value, "A") {
+ t.Errorf("expected hover content to contain 'A', got: %v", content.Value)
+ }
+ })
+}
diff --git a/gopls/internal/test/integration/misc/issue9859_def_test.go b/gopls/internal/test/integration/misc/issue9859_def_test.go
new file mode 100644
index 0000000..0f31a51
--- /dev/null
+++ b/gopls/internal/test/integration/misc/issue9859_def_test.go
@@ -0,0 +1,61 @@
+// Copyright 2026 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.
+
+package misc
+
+import (
+ "testing"
+
+ . "golang.org/x/tools/gopls/internal/test/integration"
+ "golang.org/x/tools/internal/testenv"
+)
+
+// TestIssue9859Definition tests "Go to Definition" for direct reference to embedded fields in struct literals.
+// Ref: go.dev/issues/9859
+func TestIssue9859Definition(t *testing.T) {
+ testenv.NeedsGo1Point(t, 27)
+
+ const src = `
+-- go.mod --
+module mod.com
+
+go 1.22
+-- main.go --
+package main
+
+type E1 struct {
+ A int
+}
+
+type T struct {
+ E1
+}
+
+func main() {
+ _ = T{
+ A: 1,
+ }
+}
+`
+ Run(t, src, func(t *testing.T, env *Env) {
+ t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")
+
+ env.OpenFile("main.go")
+ env.Await(env.DoneWithOpen())
+
+ // Search for "A" in the struct literal "A: 1".
+ loc := env.RegexpSearch("main.go", `\bA\b:`)
+ loc.Range.End.Character = loc.Range.Start.Character + 1
+
+ defLoc := env.FirstDefinition(loc)
+
+ // Expected definition is the field A in E1.
+ expectedLoc := env.RegexpSearch("main.go", `\bA\b int`)
+ expectedLoc.Range.End.Character = expectedLoc.Range.Start.Character + 1
+
+ if defLoc != expectedLoc {
+ t.Errorf("Definition: got %+v, want %+v", defLoc, expectedLoc)
+ }
+ })
+}

Change information

Files:
  • M gopls/internal/analysis/fillstruct/fillstruct_test.go
  • A gopls/internal/analysis/fillstruct/testdata/src/issue9859/issue9859.go
  • A gopls/internal/test/integration/completion/issue9859_test.go
  • A gopls/internal/test/integration/diagnostics/issue9859_test.go
  • A gopls/internal/test/integration/hover/issue9859_test.go
  • A gopls/internal/test/integration/misc/issue9859_def_test.go
Change size: L
Delta: 6 files changed, 269 insertions(+), 0 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: tools
Gerrit-Branch: master
Gerrit-Change-Id: If20dfc0fbfd41c1b9cb05a87845f3cc739d3e01c
Gerrit-Change-Number: 763220
Gerrit-PatchSet: 1
Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Alan Donovan (Gerrit)

unread,
Apr 8, 2026, 11:37:12 PM (3 hours ago) Apr 8
to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Hongxiang Jiang, golang-co...@googlegroups.com
Attention needed from Hongxiang Jiang and Hyang-Ah Hana Kim

Alan Donovan added 5 comments

Patchset-level comments
File-level comment, Patchset 1 (Latest):
Alan Donovan . resolved

Thanks for getting this work started!

File gopls/internal/test/integration/completion/issue9859_test.go
Line 47, Patchset 1 (Latest): Run(t, files, func(t *testing.T, env *Env) {

t.Skip("Skipping as this feature is not yet implemented. Ref: go.dev/issues/78553")

env.OpenFile("main.go")
env.Await(env.DoneWithOpen())


// Trigger completion inside T completion.
loc := env.RegexpSearch("main.go", `T\{\n\t\t()`)
completions := env.Completion(loc)


// We expect to see fields from embedded structs: A, B, and direct fields: C, E2.
want := []string{"A", "B", "C", "E2"}
diff := compareCompletionLabels(want, completions.Items)
if diff != "" {
t.Fatal(diff)
}
})
Alan Donovan . unresolved

This test could be expressed as one-liner in the marker test framework; see gopls/internal/test/marker/testdata/completion/*.txt for examples. (You can express NeedsGo1Point using `-min_go=go1.27` in `-- flags --` archive section.)

File gopls/internal/test/integration/diagnostics/issue9859_test.go
Line 41, Patchset 1 (Latest): Run(t, src, func(t *testing.T, env *Env) {
Alan Donovan . unresolved

ditto (`@diag`, not that you'll need it!)

File gopls/internal/test/integration/hover/issue9859_test.go
Line 42, Patchset 1 (Latest): Run(t, src, func(t *testing.T, env *Env) {
Alan Donovan . unresolved

ditto (`@hover`)

File gopls/internal/test/integration/misc/issue9859_def_test.go
Line 41, Patchset 1 (Latest): Run(t, src, func(t *testing.T, env *Env) {
Alan Donovan . unresolved

ditto (`@def`)

Open in Gerrit

Related details

Attention is currently required from:
  • Hongxiang Jiang
  • Hyang-Ah Hana Kim
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: tools
    Gerrit-Branch: master
    Gerrit-Change-Id: If20dfc0fbfd41c1b9cb05a87845f3cc739d3e01c
    Gerrit-Change-Number: 763220
    Gerrit-PatchSet: 1
    Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
    Gerrit-Reviewer: Alan Donovan <adon...@google.com>
    Gerrit-Reviewer: Hongxiang Jiang <hxj...@golang.org>
    Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
    Gerrit-Attention: Hongxiang Jiang <hxj...@golang.org>
    Gerrit-Comment-Date: Thu, 09 Apr 2026 03:37:08 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages