Skip to content

Commit

Permalink
Workaround: Fix panic due to anonymous structs (#96)
Browse files Browse the repository at this point in the history
Co-authored-by: Varun Gandhi <[email protected]>
  • Loading branch information
mmanela and varungandhi-src authored Apr 29, 2024
1 parent a5b080c commit ba632a7
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 2 deletions.
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Run SCIP-GO",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "cmd/scip-go",
"cwd": "${input:path}",
}
],
"inputs": [
{
"id": "path",
"description": "Please enter the path to the project to index",
"default": "",
"type": "promptString"
}
]
}
17 changes: 15 additions & 2 deletions internal/lookup/lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"

"github.com/sourcegraph/scip-go/internal/newtypes"
"github.com/sourcegraph/scip-go/internal/output"
"github.com/sourcegraph/scip-go/internal/symbols"
"github.com/sourcegraph/scip/bindings/go/scip"
"golang.org/x/tools/go/packages"
Expand Down Expand Up @@ -44,11 +45,23 @@ func (p *Package) SymbolsForFile(file *token.File) []*scip.SymbolInformation {
return documentSymbols
}

var emittedLogLine = map[token.Pos]struct{}{}
var emittedLogLineMu sync.Mutex

func (p *Package) Set(pos token.Pos, symbol *scip.SymbolInformation) {
// TODO: Could remove this once we are 100% confident we're not overlapping...
if original, ok := p.fields[pos]; ok {
if original != symbol {
panic(fmt.Sprintf("Cannot add pos to new symbol: %s %s", original, symbol))
// Workaround for handling symbol names when multiple
// fields are defined in the same statement with the same anonymous
// struct type. By ignoring this case, the last field name will
// be used for the type name.
// Ideal fix: https://github.com/sourcegraph/scip-go/issues/95
emittedLogLineMu.Lock()
if _, ok := emittedLogLine[pos]; !ok {
output.Logf("[scip.lookup] Overriding original symbol %s with %s at %v", original.Symbol, symbol.Symbol, p.pkg.Fset.Position(pos))
emittedLogLine[pos] = struct{}{}
}
emittedLogLineMu.Unlock()
}
}

Expand Down
47 changes: 47 additions & 0 deletions internal/testdata/snapshots/input/testdata/anonymous_structs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package testdata

import "fmt"

type TypeContainingAnonymousStructs struct {
a, b struct {
x int
y string
}
c struct {
X int
Y string
}
}

func funcContainingAnonymousStructs() {
d := struct {
x int
y string
}{
x: 1,
y: "one",
}

var e struct {
x int
y string
}

e.x = 2
e.y = "two"

var f TypeContainingAnonymousStructs
f.a.x = 3
f.a.y = "three"
f.b.x = 4
f.b.y = "four"
f.c.X = 5
f.c.Y = "five"

fmt.Printf("> %s, %s\n", d.x, d.y)
fmt.Printf("> %s, %s\n", e.x, e.y)

fmt.Printf("> %s, %s\n", f.a.x, f.a.y)
fmt.Printf("> %s, %s\n", f.b.x, f.b.y)
fmt.Printf("> %s, %s\n", f.c.X, f.c.Y)
}
137 changes: 137 additions & 0 deletions internal/testdata/snapshots/output/testdata/anonymous_structs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package testdata
// ^^^^^^^^ reference 0.1.test `sg/testdata`/

import "fmt"
// ^^^ reference github.com/golang/go/src go1.22 fmt/

type TypeContainingAnonymousStructs struct {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#
// documentation ```go
// documentation ```go
a, b struct {
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.
// documentation ```go
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.
// documentation ```go
x int
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.x.
// documentation ```go
y string
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.y.
// documentation ```go
}
c struct {
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.
// documentation ```go
X int
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.X.
// documentation ```go
Y string
// ^ definition 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.Y.
// documentation ```go
}
}

func funcContainingAnonymousStructs() {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/funcContainingAnonymousStructs().
// documentation ```go
d := struct {
// ^ definition local 0
x int
// ^ definition local 1
y string
// ^ definition local 2
}{
x: 1,
// ^ reference local 1
y: "one",
// ^ reference local 2
}

var e struct {
// ^ definition local 3
x int
// ^ definition local 4
y string
// ^ definition local 5
}

e.x = 2
// ^ reference local 3
// ^ reference local 4
e.y = "two"
// ^ reference local 3
// ^ reference local 5

var f TypeContainingAnonymousStructs
// ^ definition local 6
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#
f.a.x = 3
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.x.
f.a.y = "three"
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.y.
f.b.x = 4
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.x.
f.b.y = "four"
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.y.
f.c.X = 5
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.X.
f.c.Y = "five"
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.Y.

fmt.Printf("> %s, %s\n", d.x, d.y)
// ^^^ reference github.com/golang/go/src go1.22 fmt/
// ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf().
// ^ reference local 0
// ^ reference local 1
// ^ reference local 0
// ^ reference local 2
fmt.Printf("> %s, %s\n", e.x, e.y)
// ^^^ reference github.com/golang/go/src go1.22 fmt/
// ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf().
// ^ reference local 3
// ^ reference local 4
// ^ reference local 3
// ^ reference local 5

fmt.Printf("> %s, %s\n", f.a.x, f.a.y)
// ^^^ reference github.com/golang/go/src go1.22 fmt/
// ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf().
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.x.
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.y.
fmt.Printf("> %s, %s\n", f.b.x, f.b.y)
// ^^^ reference github.com/golang/go/src go1.22 fmt/
// ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf().
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.x.
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#a.b.y.
fmt.Printf("> %s, %s\n", f.c.X, f.c.Y)
// ^^^ reference github.com/golang/go/src go1.22 fmt/
// ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf().
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.X.
// ^ reference local 6
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.
// ^ reference 0.1.test `sg/testdata`/TypeContainingAnonymousStructs#c.Y.
}

0 comments on commit ba632a7

Please sign in to comment.