Skip to content

Commit

Permalink
Fix bug when parsing self arguments appearing in functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
pherrymason committed Jan 14, 2024
1 parent c4b90d5 commit 6700bca
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ Using tree-sitter grammar rules from https://github.com/zweimach/tree-sitter-c3
- [ ] Index Symbols
- [x] Variables & type
- [x] Functions
- [ ] Function arguments
- [x] Function arguments
- [x] Function return type
- [x] Enums + Enumerators
- [ ] base type
- [x] Structs
- [ ] Struct members
- [x] Struct members
- [ ] Struct methods
- [ ] imports
- [ ] macros: **Needs to update grammar.js**
Expand Down
2 changes: 1 addition & 1 deletion server/grammar/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ module.exports = grammar({
parameter: ($) =>
choice(
seq(
$._type,
field("type",$._type),
optional(seq($.identifier, optional(seq("=", $._initializer))))
),
seq(optional($._type), $.identifier, optional(seq("=", $._initializer)))
Expand Down
43 changes: 35 additions & 8 deletions server/lsp/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,7 @@ func (p *Parser) nodeToFunction(doc *Document, node *sitter.Node, sourceCode []b
argNode := parameters.Child(int(i))
switch argNode.Type() {
case "parameter":
for j := uint32(0); j < argNode.ChildCount(); j++ {
identifierNode := argNode.Child(int(j))
switch identifierNode.Type() {
case "identifier":
arguments = append(arguments, p.nodeToVariable(doc, argNode, identifierNode, sourceCode, identifierNode.Content(sourceCode)))
}
}
arguments = append(arguments, p.nodeToArgument(doc, argNode, sourceCode))
}
}

Expand All @@ -157,6 +151,40 @@ func (p *Parser) nodeToFunction(doc *Document, node *sitter.Node, sourceCode []b
return symbol
}

// nodeToArgument Very similar to nodeToVariable, but arguments have optional identifiers (for example when using `self` for struct methods)
func (p *Parser) nodeToArgument(doc *Document, argNode *sitter.Node, sourceCode []byte) idx.Variable {
var identifier string = ""
var idRange idx.Range
var argType string = ""
if argNode.ChildCount() == 2 {
if argNode.Child(0).Type() == "identifier" {
// argument without type
idNode := argNode.Child(0)
identifier = idNode.Content(sourceCode)
idRange = idx.NewRangeFromSitterPositions(idNode.StartPoint(), idNode.EndPoint())
} else {
// first node is type
argType = argNode.Child(0).Content(sourceCode)

idNode := argNode.Child(1)
identifier = idNode.Content(sourceCode)
idRange = idx.NewRangeFromSitterPositions(idNode.StartPoint(), idNode.EndPoint())
}
} else if argNode.ChildCount() == 1 {
idNode := argNode.Child(0)
identifier = idNode.Content(sourceCode)
idRange = idx.NewRangeFromSitterPositions(idNode.StartPoint(), idNode.EndPoint())
}

variable := idx.NewVariable(
identifier,
argType,
doc.URI,
idRange, idx.NewRangeFromSitterPositions(argNode.StartPoint(), argNode.EndPoint()))

return variable
}

func (p *Parser) nodeToStruct(doc *Document, node *sitter.Node, sourceCode []byte) idx.Struct {
nameNode := node.Child(1)
name := nameNode.Content(sourceCode)
Expand Down Expand Up @@ -191,7 +219,6 @@ func (p *Parser) nodeToEnum(doc *Document, node *sitter.Node, sourceCode []byte)
baseType := ""
bodyIndex := int(nodesCount - 1)

// p.logger.Debug(fmt.Sprint(node.Content(sourceCode), ": Child count:", nodesCount))
enum := idx.NewEnum(
nameNode.Content(sourceCode),
baseType,
Expand Down
21 changes: 21 additions & 0 deletions server/lsp/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ func TestExtractSymbols_finds_function_declaration_identifiers(t *testing.T) {
}
fn int test2(int number, char ch) {
return 2;
}
fn Object* UserStruct.method(&self, int* pointer) {
return 1;
}`
docId := "x"
doc := NewDocumentFromString(docId, source)
Expand Down Expand Up @@ -218,6 +221,23 @@ func TestExtractSymbols_finds_function_declaration_identifiers(t *testing.T) {
WithDocumentRange(3, 1, 5, 2).
Build()

functionMethod := idx.NewFunctionBuilder("method", "Object*", "x").
WithArgument(
idx.NewVariableBuilder("self", "", "x").
WithIdentifierRange(6, 31, 6, 35).
WithDocumentRange(6, 31, 6, 35).
Build(),
).
WithArgument(
idx.NewVariableBuilder("pointer", "int*", "x").
WithIdentifierRange(6, 42, 6, 49).
WithDocumentRange(6, 37, 6, 49).
Build(),
).
WithIdentifierRange(6, 23, 6, 29).
WithDocumentRange(6, 1, 8, 2).
Build()

root := idx.NewAnonymousScopeFunction(
"main",
docId,
Expand All @@ -229,6 +249,7 @@ func TestExtractSymbols_finds_function_declaration_identifiers(t *testing.T) {

assertSameFunction(t, &function1, tree.ChildrenFunctions["test"])
assertSameFunction(t, &function2, tree.ChildrenFunctions["test2"])
assertSameFunction(t, &functionMethod, tree.ChildrenFunctions["method"])
}

func keys[K comparable, V any](m map[K]V) []K {
Expand Down

0 comments on commit 6700bca

Please sign in to comment.