Skip to content

Commit

Permalink
fix(tools/spxls): add missing spx definitions and improve resource di…
Browse files Browse the repository at this point in the history
…agnostics (#1179)

Signed-off-by: Aofei Sheng <[email protected]>
  • Loading branch information
aofei authored Dec 27, 2024
1 parent a6b1cef commit b0efe77
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 29 deletions.
14 changes: 6 additions & 8 deletions tools/spxls/internal/server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,19 @@ func (s *Server) spxGetDefinitions(params []SpxGetDefinitionsParams) ([]SpxDefin

// Add other spx definitions.
for _, name := range result.spxPkg.Scope().Names() {
if obj := result.spxPkg.Scope().Lookup(name); obj != nil {
if obj := result.spxPkg.Scope().Lookup(name); obj != nil && obj.Exported() {
name := obj.Name()

var overloadID *string
if _, ok := obj.(*types.Func); ok {
name, overloadID = parseGopFuncName(name)
}

if obj.Exported() {
addDefinitionID(SpxDefinitionIdentifier{
Package: util.ToPtr(spxPkgPath),
Name: util.ToPtr(name),
OverloadID: overloadID,
})
}
addDefinitionID(SpxDefinitionIdentifier{
Package: util.ToPtr(spxPkgPath),
Name: util.ToPtr(name),
OverloadID: overloadID,
})
}
}

Expand Down
20 changes: 0 additions & 20 deletions tools/spxls/internal/server/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,11 +766,6 @@ func (s *Server) inspectSpxSpriteResourceRefAtExpr(result *compileResult, expr g
obj := result.typeInfo.ObjectOf(ident)
if obj != nil {
if !slices.Contains(result.spxSpriteResourceAutoBindings, obj) {
ri.result.addDiagnostics(ri.documentURI, Diagnostic{
Severity: SeverityError,
Range: ri.exprRange,
Message: fmt.Sprintf("cannot find auto-binding for sprite resource %q", obj.Name()),
})
return nil
}
spxSpriteName = obj.Name()
Expand All @@ -779,11 +774,6 @@ func (s *Server) inspectSpxSpriteResourceRefAtExpr(result *compileResult, expr g
}
}
if !ri.validateResourceName(spxSpriteName, SpxResourceTypeSprite) {
ri.result.addDiagnostics(ri.documentURI, Diagnostic{
Severity: SeverityWarning,
Range: ri.exprRange,
Message: "cannot determine sprite name",
})
return nil
}
} else {
Expand All @@ -809,11 +799,6 @@ func (s *Server) inspectSpxSpriteResourceRefAtExpr(result *compileResult, expr g
return nil
}
if !slices.Contains(result.spxSpriteResourceAutoBindings, obj) {
ri.result.addDiagnostics(ri.documentURI, Diagnostic{
Severity: SeverityError,
Range: ri.exprRange,
Message: fmt.Sprintf("cannot find auto-binding for sprite resource %q", obj.Name()),
})
return nil
}
spxSpriteName = obj.Name()
Expand Down Expand Up @@ -961,11 +946,6 @@ func (s *Server) inspectSpxSoundResourceRefAtExpr(result *compileResult, expr go
return nil
}
if !slices.Contains(result.spxSoundResourceAutoBindings, obj) {
ri.result.addDiagnostics(ri.documentURI, Diagnostic{
Severity: SeverityError,
Range: ri.exprRange,
Message: fmt.Sprintf("cannot find auto-binding for sound resource %q", obj.Name()),
})
return nil
}
spxSoundName = obj.Name()
Expand Down
64 changes: 63 additions & 1 deletion tools/spxls/internal/server/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_completion
func (s *Server) textDocumentCompletion(params *CompletionParams) ([]CompletionItem, error) {
result, _, astFile, err := s.compileAndGetASTFileForDocumentURI(params.TextDocument.URI)
result, spxFile, astFile, err := s.compileAndGetASTFileForDocumentURI(params.TextDocument.URI)
if err != nil {
if errors.Is(err, errNoValidSpxFiles) || errors.Is(err, errNoMainSpxFile) {
return nil, nil
Expand All @@ -40,6 +40,7 @@ func (s *Server) textDocumentCompletion(params *CompletionParams) ([]CompletionI

ctx := &completionContext{
result: result,
spxFile: spxFile,
astFile: astFile,
pos: pos,
innermostScope: innermostScope,
Expand All @@ -66,6 +67,7 @@ const (
// completionContext represents the context for completion operations.
type completionContext struct {
result *compileResult
spxFile string
astFile *gopast.File
pos goptoken.Pos
innermostScope *types.Scope
Expand Down Expand Up @@ -256,6 +258,7 @@ func (ctx *completionContext) collectGeneralCompletions() ([]CompletionItem, err

// Add all visible objects in the scope.
for scope := ctx.innermostScope; scope != nil; scope = scope.Parent() {
isInMainScope := ctx.innermostScope == ctx.fileScope && scope == ctx.result.mainPkg.Scope()
for _, name := range scope.Names() {
obj := scope.Lookup(name)
if obj == nil || !obj.Exported() && obj.Pkg() != ctx.result.mainPkg {
Expand All @@ -274,6 +277,65 @@ func (ctx *completionContext) collectGeneralCompletions() ([]CompletionItem, err
case *types.PkgName:
addItems(NewSpxDefinitionForPkg(ctx.result, obj))
}

isThis := name == "this"
isSpxFileMatch := ctx.spxFile == name+".spx" || (ctx.spxFile == ctx.result.mainSpxFile && name == "Game")
isMainScopeObj := isInMainScope && isSpxFileMatch
if !isThis && !isMainScopeObj {
continue
}

typ := unwrapPointerType(obj.Type())
if _, ok := typ.Underlying().(*types.Struct); !ok {
continue
}
walkStruct(typ, func(named *types.Named, namedParents []*types.Named, member types.Object) {
memberPkgPath := member.Pkg().Path()
if !member.Exported() && memberPkgPath != "main" {
return
}

switch member := member.(type) {
case *types.Var:
addItems(NewSpxDefinitionForVar(ctx.result, member, ""))
case *types.Func:
recvTypeName := named.Obj().Name()
if memberPkgPath == spxPkgPath {
if recvTypeName != "SpriteImpl" && recvTypeName != "Game" {
for _, namedParent := range namedParents {
if namedParent.Obj().Pkg().Path() != spxPkgPath {
continue
}
namedParentName := namedParent.Obj().Name()
if namedParentName == "SpriteImpl" || namedParentName == "Game" {
recvTypeName = namedParentName
break
}
}
}
if recvTypeName == "SpriteImpl" {
recvTypeName = "Sprite"
}
}
addItems(NewSpxDefinitionsForFunc(ctx.result, member, recvTypeName)...)
}
})
}
}

// Add other spx definitions.
for _, name := range ctx.result.spxPkg.Scope().Names() {
if obj := ctx.result.spxPkg.Scope().Lookup(name); obj != nil && obj.Exported() {
switch obj := obj.(type) {
case *types.Var:
addItems(NewSpxDefinitionForVar(ctx.result, obj, ""))
case *types.Const:
addItems(NewSpxDefinitionForConst(ctx.result, obj))
case *types.TypeName:
addItems(NewSpxDefinitionForType(ctx.result, obj))
case *types.Func:
addItems(NewSpxDefinitionsForFunc(ctx.result, obj, "")...)
}
}
}

Expand Down

0 comments on commit b0efe77

Please sign in to comment.