Skip to content

Commit

Permalink
feat: support another edge case for Java.CharacterExpected
Browse files Browse the repository at this point in the history
  • Loading branch information
nedpals committed Jan 31, 2024
1 parent 9925aa8 commit 7702d52
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 8 deletions.
89 changes: 81 additions & 8 deletions error_templates/java/character_expected_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,51 @@ const (
characterExpectedFixWrapFunction characterExpectedFixKind = iota
)

type characterInsertDirection int

const (
characterInsertDirectionLeft characterInsertDirection = iota
characterInsertDirectionRight
)

type characterExpectedErrorCtx struct {
fixKind characterExpectedFixKind
fixKind characterExpectedFixKind
direction characterInsertDirection
}

var CharacterExpectedError = lib.ErrorTemplate{
Name: "CharacterExpectedError",
Pattern: comptimeErrorPattern(`'(?P<character>\S+)' expected`),
Pattern: comptimeErrorPattern(`'(?P<character>\S+)'(?: or '(?P<altCharacter>\S+)')? expected`),
StackTracePattern: comptimeStackTracePattern,
OnAnalyzeErrorFn: func(cd *lib.ContextData, m *lib.MainError) {
iCtx := characterExpectedErrorCtx{}
iCtx := characterExpectedErrorCtx{
direction: characterInsertDirectionLeft,
}

// TODO: check if node is parsable
rootNode := m.Document.Tree.RootNode()
cursor := sitter.NewTreeCursor(rootNode)
rawNearestMissingNode := nearestMissingNodeFromPos(cursor, m.ErrorNode.StartPos)
nearestMissingNode := lib.WrapNode(m.Document, rawNearestMissingNode)
m.Nearest = nearestMissingNode
if rawNearestMissingNode == nil {
if rawNearestMissingNode2 := nearestNodeFromPos2(cursor, m.ErrorNode.StartPos); rawNearestMissingNode2 != nil {
rawNearestMissingNode = rawNearestMissingNode2
}
}

if rawNearestMissingNode != nil {
if rawNearestMissingNode.IsExtra() {
// go back
rawNearestMissingNode = rawNearestMissingNode.PrevSibling()
}

if rawNearestMissingNode.IsNamed() {
iCtx.direction = characterInsertDirectionRight
}

nearestMissingNode := lib.WrapNode(m.Document, rawNearestMissingNode)
m.Nearest = nearestMissingNode
}

m.Context = iCtx
},
OnGenExplainFn: func(cd *lib.ContextData, gen *lib.ExplainGenerator) {
Expand All @@ -46,15 +74,23 @@ var CharacterExpectedError = lib.ErrorTemplate{
// }
},
OnGenBugFixFn: func(cd *lib.ContextData, gen *lib.BugFixGenerator) {
// ctx := cd.MainError.Context.(characterExpectedErrorCtx)
ctx := cd.MainError.Context.(characterExpectedErrorCtx)

gen.Add("Add the missing character", func(s *lib.BugFixSuggestion) {
s.AddStep("Ensure that the array declaration has the correct syntax by adding the missing `%s`.", cd.Variables["character"]).
AddFix(lib.FixSuggestion{
step := s.AddStep("Ensure that the array declaration has the correct syntax by adding the missing `%s`.", cd.Variables["character"])
if ctx.direction == characterInsertDirectionLeft {
step.AddFix(lib.FixSuggestion{
NewText: cd.Variables["character"],
StartPosition: cd.MainError.Nearest.StartPosition(),
EndPosition: cd.MainError.Nearest.StartPosition(),
})
} else if ctx.direction == characterInsertDirectionRight {
step.AddFix(lib.FixSuggestion{
NewText: cd.Variables["character"],
StartPosition: cd.MainError.Nearest.EndPosition(),
EndPosition: cd.MainError.Nearest.EndPosition(),
})
}
})

// switch ctx.fixKind {
Expand Down Expand Up @@ -82,3 +118,40 @@ var CharacterExpectedError = lib.ErrorTemplate{
// }
},
}

func nearestNodeFromPos2(cursor *sitter.TreeCursor, pos lib.Position) *sitter.Node {
defer cursor.GoToParent()

// hope it executes to avoid stack overflow
if !cursor.GoToFirstChild() {
return nil
}

var nearest *sitter.Node

for {
currentNode := cursor.CurrentNode()
pointA := currentNode.StartPoint()
if pointA.Row+1 > uint32(pos.Line) {
break
}

if (nearest == nil && int(pointA.Row+1) <= pos.Line) || currentNode.StartByte() >= nearest.StartByte() {
nearest = currentNode
}

if currentNode.ChildCount() != 0 {
if nearestFromInner := nearestNodeFromPos2(cursor, pos); nearestFromInner != nil {
if (nearest == nil && int(nearestFromInner.StartPoint().Row+1) <= pos.Line) || nearestFromInner.StartByte() >= nearest.StartByte() {
nearest = nearestFromInner
}
}
}

if !cursor.GoToNextSibling() {
break
}
}

return nearest
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!" // Error: Expected ';'
}
}
30 changes: 30 additions & 0 deletions error_templates/java/test_files/character_expected_call/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: "Call"
template: "Java.CharacterExpectedError"
---
Main.java:3: error: ')' or ',' expected
System.out.println("Hello, World!" // Error: Expected ';'
^
1 error
===
template: "Java.CharacterExpectedError"
---
# CharacterExpectedError
This error occurs when there is an unexpected character in the code, and ')' is expected.
```
public static void main(String[] args) {
System.out.println("Hello, World!" // Error: Expected ';'
^^^^^^^^^^^^^^^
}
}
```
## Steps to fix
### Add the missing character
Ensure that the array declaration has the correct syntax by adding the missing `)`.
```diff
public class Main {
public static void main(String[] args) {
- System.out.println("Hello, World!" // Error: Expected ';'
+ System.out.println("Hello, World!") // Error: Expected ';'
}
}
```

0 comments on commit 7702d52

Please sign in to comment.