Skip to content

Commit

Permalink
Adjust variable identifier ranges.
Browse files Browse the repository at this point in the history
Refactor tests to be more semantic.
  • Loading branch information
pherrymason committed Jan 14, 2024
1 parent 9576e8b commit b1b968a
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 64 deletions.
43 changes: 43 additions & 0 deletions server/lsp/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package lsp

import (
"fmt"
idx "github.com/pherrymason/c3-lsp/lsp/indexables"
"github.com/stretchr/testify/assert"
"testing"
)

func assertSameRange(t *testing.T, expected idx.Range, actual idx.Range, msg string) {
assert.Equal(t, expected.Start, actual.Start, fmt.Sprint(msg, " start"))
assert.Equal(t, expected.Start, actual.Start, fmt.Sprint(msg, " end"))
}

func assertSameFunction(t *testing.T, expected *idx.Function, actual *idx.Function) {
assert.Equal(t, expected.FunctionType(), actual.FunctionType(), expected.GetName())
assert.Equal(t, expected.GetName(), actual.GetName())
assert.Equal(t, expected.GetReturnType(), actual.GetReturnType(), expected.GetName())
assert.Equal(t, expected.ArgumentIds(), actual.ArgumentIds(), expected.GetName())
assert.Equal(t, expected.GetDocumentURI(), actual.GetDocumentURI(), expected.GetName())

assertSameRange(t, expected.GetDeclarationRange(), actual.GetDeclarationRange(), fmt.Sprint("Function declaration range:", expected.GetName()))
assertSameRange(t, expected.GetDocumentRange(), actual.GetDocumentRange(), fmt.Sprint("Function document range:", expected.GetName()))

assert.Equal(t, expected.GetKind(), actual.GetKind(), expected.GetName())
assert.Equal(t, expected.Variables, actual.Variables, expected.GetName())
assert.Equal(t, expected.Enums, actual.Enums, expected.GetName())
assert.Equal(t, expected.Structs, actual.Structs, expected.GetName())

assert.Equal(t, keys(expected.ChildrenFunctions), keys(actual.ChildrenFunctions))
for key, value := range expected.ChildrenFunctions {
assertSameFunction(t, value, actual.ChildrenFunctions[key])
}
}

func createStruct(docId string, name string, members []idx.StructMember, idRange idx.Range) idx.Indexable {
return idx.NewStruct(
name,
members,
docId,
idRange,
)
}
67 changes: 67 additions & 0 deletions server/lsp/indexables/enumBuilder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package indexables

import protocol "github.com/tliron/glsp/protocol_3_16"

type EnumBuilder struct {
enum Enum
}

func NewEnumBuilder(name string, baseType string, docId string) *EnumBuilder {
return &EnumBuilder{
enum: Enum{
name: name,
baseType: baseType,
BaseIndexable: BaseIndexable{
documentURI: docId,
Kind: protocol.CompletionItemKindEnum,
},
},
}
}

func (eb *EnumBuilder) WithIdentifierRange(lineStart uint, CharStart uint, lineEnd uint, CharEnd uint) *EnumBuilder {
eb.enum.BaseIndexable.identifierRange = NewRange(lineStart, CharStart, lineEnd, CharEnd)
return eb
}

func (eb *EnumBuilder) WithDocumentRange(lineStart uint, CharStart uint, lineEnd uint, CharEnd uint) *EnumBuilder {
eb.enum.BaseIndexable.documentRange = NewRange(lineStart, CharStart, lineEnd, CharEnd)
return eb
}

func (eb *EnumBuilder) WithEnumerator(enumerator Enumerator) *EnumBuilder {
eb.enum.enumerators = append(eb.enum.enumerators, enumerator)

return eb
}

func (eb *EnumBuilder) Build() *Enum {
return &eb.enum
}

// EnumeratorBuilder
type EnumeratorBuilder struct {
enumerator Enumerator
}

func NewEnumeratorBuilder(name string, docId string) *EnumeratorBuilder {
return &EnumeratorBuilder{
enumerator: Enumerator{
name: name,
value: "",
BaseIndexable: BaseIndexable{
documentURI: docId,
Kind: protocol.CompletionItemKindEnumMember,
},
},
}
}

func (eb *EnumeratorBuilder) WithIdentifierRange(lineStart uint, CharStart uint, lineEnd uint, CharEnd uint) *EnumeratorBuilder {
eb.enumerator.BaseIndexable.identifierRange = NewRange(lineStart, CharStart, lineEnd, CharEnd)
return eb
}

func (eb *EnumeratorBuilder) Build() Enumerator {
return eb.enumerator
}
8 changes: 8 additions & 0 deletions server/lsp/indexables/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func newFunctionType(fType FunctionType, name string, returnType string, argumen
}
}

func (f Function) FunctionType() FunctionType {
return f.fType
}

func (f Function) GetName() string {
return f.name
}
Expand All @@ -58,6 +62,10 @@ func (f Function) GetReturnType() string {
return f.returnType
}

func (f Function) ArgumentIds() []string {
return f.argumentIds
}

func (f Function) GetKind() protocol.CompletionItemKind {
return f.Kind
}
Expand Down
35 changes: 35 additions & 0 deletions server/lsp/indexables/variableBuilder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package indexables

import protocol "github.com/tliron/glsp/protocol_3_16"

type VariableBuilder struct {
variable Variable
}

// NewVariableBuilder
func NewVariableBuilder(name string, variableType string, docId string) *VariableBuilder {
return &VariableBuilder{
variable: Variable{
Name: name,
Type: variableType,
BaseIndexable: BaseIndexable{
documentURI: docId,
Kind: protocol.CompletionItemKindVariable,
},
},
}
}

func (vb *VariableBuilder) WithDocumentRange(lineStart uint, CharStart uint, lineEnd uint, CharEnd uint) *VariableBuilder {
vb.variable.BaseIndexable.documentRange = NewRange(lineStart, CharStart, lineEnd, CharEnd)
return vb
}

func (vb *VariableBuilder) WithIdentifierRange(lineStart uint, CharStart uint, lineEnd uint, CharEnd uint) *VariableBuilder {
vb.variable.BaseIndexable.identifierRange = NewRange(lineStart, CharStart, lineEnd, CharEnd)
return vb
}

func (vb *VariableBuilder) Build() Variable {
return vb.variable
}
92 changes: 41 additions & 51 deletions server/lsp/language_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,47 +87,6 @@ func newDeclarationParams(docId string, line protocol.UInteger, char protocol.UI
WorkDoneProgressParams: protocol.WorkDoneProgressParams{},
}
}
func createVariable(docId string, name string, baseType string, sL uint, sC uint, eL uint, eC uint) idx.Indexable {
return idx.Variable{
Name: name,
Type: baseType,
BaseIndexable: idx.NewBaseIndexable(
docId,
idx.NewRange(sL, sC, eL, eC),
idx.NewRange(sL, sC, eL, eC),
protocol.CompletionItemKindVariable,
),
}
}

func createEnum(docId string, name string, variants []idx.Enumerator, idRange [4]uint, docRange [4]uint) *idx.Enum {
enum := idx.NewEnum(
name,
"",
variants,
idx.NewRange(idRange[0], idRange[1], idRange[2], idRange[3]),
idx.NewRange(docRange[0], docRange[1], docRange[2], docRange[3]),
docId,
)

return &enum
}

func createEnumerator(name string, docId string, pRange [4]uint) idx.Enumerator {
enumerator := idx.NewEnumerator(name, "", idx.NewRange(pRange[0], pRange[1], pRange[2], pRange[3]), docId)

return enumerator
}

func createStruct(docId string, name string, members []idx.StructMember, idRange idx.Range) idx.Indexable {
return idx.NewStruct(
name,
members,
docId,
idRange,
)
}

func TestLanguage_FindSymbolDeclarationInWorkspace_symbol_same_scope(t *testing.T) {
cases := []struct {
name string
Expand All @@ -141,24 +100,43 @@ func TestLanguage_FindSymbolDeclarationInWorkspace_symbol_same_scope(t *testing.
`int value=1;value=3;`,
"value",
0, 13,
createVariable("x", "value", "int", 0, 4, 0, 9)},
idx.NewVariableBuilder("value", "int", "x").
WithIdentifierRange(0, 4, 0, 9).
WithDocumentRange(0, 0, 0, 12).
Build()},
{
"enum declaration",
`enum Colors = { RED, BLUE, GREEN };Colors foo = RED;`,
"Colors",
0, 36,
createEnum("x", "Colors", []idx.Enumerator{
idx.NewEnumerator("RED", "", idx.NewRange(0, 16, 0, 19), "x"),
idx.NewEnumerator("BLUE", "", idx.NewRange(0, 21, 0, 25), "x"),
idx.NewEnumerator("GREEN", "", idx.NewRange(0, 27, 0, 32), "x"),
}, [4]uint{0, 5, 0, 11}, [4]uint{0, 0, 0, 34}),
idx.NewEnumBuilder("Colors", "", "x").
WithIdentifierRange(0, 5, 0, 11).
WithDocumentRange(0, 0, 0, 34).
WithEnumerator(
idx.NewEnumeratorBuilder("RED", "x").
WithIdentifierRange(0, 16, 0, 19).
Build(),
).
WithEnumerator(
idx.NewEnumeratorBuilder("BLUE", "x").
WithIdentifierRange(0, 21, 0, 25).
Build(),
).
WithEnumerator(
idx.NewEnumeratorBuilder("GREEN", "x").
WithIdentifierRange(0, 27, 0, 32).
Build(),
).
Build(),
},
{
"enum enumerator",
`enum Colors = { RED, BLUE, GREEN };Colors foo = RED;`,
"RED",
0, 49,
createEnumerator("RED", "x", [4]uint{0, 16, 0, 19}),
idx.NewEnumeratorBuilder("RED", "x").
WithIdentifierRange(0, 16, 0, 19).
Build(),
},
{
"struct",
Expand Down Expand Up @@ -208,7 +186,11 @@ func TestLanguage_FindSymbolDeclarationInWorkspace_variable_same_scope(t *testin

symbol, _ := language.FindSymbolDeclarationInWorkspace(doc.URI, "value", params.Position)

expectedSymbol := idx.NewVariable("value", "int", "x", idx.NewRange(1, 6, 1, 11), idx.NewRange(1, 6, 1, 11))
expectedSymbol := idx.NewVariableBuilder("value", "int", "x").
WithIdentifierRange(1, 6, 1, 11).
WithDocumentRange(1, 2, 1, 16).
Build()

assert.Equal(t, expectedSymbol, symbol)
}

Expand All @@ -233,7 +215,11 @@ func TestLanguage_FindSymbolDeclarationInWorkspace_variable_outside_current_func

symbol, _ := language.FindSymbolDeclarationInWorkspace(doc.URI, "value", params.Position)

expectedSymbol := idx.NewVariable("value", "int", "x", idx.NewRange(1, 6, 1, 11), idx.NewRange(1, 6, 1, 11))
expectedSymbol := idx.NewVariableBuilder("value", "int", "x").
WithIdentifierRange(1, 6, 1, 11).
WithDocumentRange(1, 2, 1, 16).
Build()

assert.Equal(t, expectedSymbol, symbol)
}

Expand All @@ -259,7 +245,11 @@ func TestLanguage_FindSymbolDeclarationInWorkspace_variable_outside_current_file

symbol, _ := language.FindSymbolDeclarationInWorkspace(doc.URI, "value", params.Position)

expectedSymbol := idx.NewVariable("value", "int", "y", idx.NewRange(0, 4, 0, 9), idx.NewRange(0, 4, 0, 9))
expectedSymbol := idx.NewVariableBuilder("value", "int", "y").
WithIdentifierRange(0, 4, 0, 9).
WithDocumentRange(0, 0, 0, 14).
Build()

assert.Equal(t, expectedSymbol, symbol)
}

Expand Down
18 changes: 11 additions & 7 deletions server/lsp/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (p *Parser) ExtractSymbols(doc *Document) idx.Function {
if nodeType == "identifier" {
switch c.Node.Parent().Type() {
case "var_declaration":
variable := p.nodeToVariable(doc, c.Node, sourceCode, content)
variable := p.nodeToVariable(doc, c.Node.Parent(), c.Node, sourceCode, content)
scopeTree.AddVariables([]idx.Variable{
variable,
})
Expand All @@ -107,10 +107,14 @@ func (p *Parser) ExtractSymbols(doc *Document) idx.Function {
return scopeTree
}

func (p *Parser) nodeToVariable(doc *Document, identifierNode *sitter.Node, sourceCode []byte, content string) idx.Variable {
func (p *Parser) nodeToVariable(doc *Document, variableNode *sitter.Node, identifierNode *sitter.Node, sourceCode []byte, content string) idx.Variable {
typeNode := identifierNode.PrevSibling()
typeNodeContent := typeNode.Content(sourceCode)
variable := idx.NewVariable(content, typeNodeContent, doc.URI, idx.NewRangeFromSitterPositions(identifierNode.StartPoint(), identifierNode.EndPoint()), idx.NewRangeFromSitterPositions(identifierNode.StartPoint(), identifierNode.EndPoint()))
variable := idx.NewVariable(
content,
typeNodeContent,
doc.URI,
idx.NewRangeFromSitterPositions(identifierNode.StartPoint(), identifierNode.EndPoint()), idx.NewRangeFromSitterPositions(variableNode.StartPoint(), variableNode.EndPoint()))

return variable
}
Expand All @@ -127,10 +131,10 @@ func (p *Parser) nodeToFunction(doc *Document, node *sitter.Node, sourceCode []b
switch argNode.Type() {
case "parameter":
for j := uint32(0); j < argNode.ChildCount(); j++ {
arggNode := argNode.Child(int(j))
switch arggNode.Type() {
identifierNode := argNode.Child(int(j))
switch identifierNode.Type() {
case "identifier":
arguments = append(arguments, p.nodeToVariable(doc, arggNode, sourceCode, arggNode.Content(sourceCode)))
arguments = append(arguments, p.nodeToVariable(doc, argNode, identifierNode, sourceCode, identifierNode.Content(sourceCode)))
}
}
}
Expand Down Expand Up @@ -238,7 +242,7 @@ func (p *Parser) FindVariableDeclarations(doc *Document, node *sitter.Node) []id

if _, exists := found[content]; !exists {
found[content] = true
variable := p.nodeToVariable(doc, c.Node, sourceCode, content)
variable := p.nodeToVariable(doc, c.Node.Parent(), c.Node, sourceCode, content)
identifiers = append(identifiers, variable)
}
}
Expand Down
Loading

0 comments on commit b1b968a

Please sign in to comment.