From 7702d52bc782476f153656dded662487a2bae3e8 Mon Sep 17 00:00:00 2001 From: Ned Palacios Date: Wed, 31 Jan 2024 21:41:27 +0800 Subject: [PATCH] feat: support another edge case for Java.CharacterExpected --- .../java/character_expected_error.go | 89 +++++++++++++++++-- .../character_expected_call/Main.java | 5 ++ .../character_expected_call/test.txt | 30 +++++++ 3 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 error_templates/java/test_files/character_expected_call/Main.java create mode 100644 error_templates/java/test_files/character_expected_call/test.txt diff --git a/error_templates/java/character_expected_error.go b/error_templates/java/character_expected_error.go index 4dbc4bc..05caa4a 100644 --- a/error_templates/java/character_expected_error.go +++ b/error_templates/java/character_expected_error.go @@ -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\S+)' expected`), + Pattern: comptimeErrorPattern(`'(?P\S+)'(?: or '(?P\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) { @@ -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 { @@ -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 +} diff --git a/error_templates/java/test_files/character_expected_call/Main.java b/error_templates/java/test_files/character_expected_call/Main.java new file mode 100644 index 0000000..7779689 --- /dev/null +++ b/error_templates/java/test_files/character_expected_call/Main.java @@ -0,0 +1,5 @@ +public class Main { + public static void main(String[] args) { + System.out.println("Hello, World!" // Error: Expected ';' + } +} diff --git a/error_templates/java/test_files/character_expected_call/test.txt b/error_templates/java/test_files/character_expected_call/test.txt new file mode 100644 index 0000000..2d7d7dc --- /dev/null +++ b/error_templates/java/test_files/character_expected_call/test.txt @@ -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 ';' + } +} +```