Skip to content

Commit 3d4beeb

Browse files
committed
feat(java): support for Java.NoSuchElementException
1 parent 430bb24 commit 3d4beeb

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

error_templates/java/java.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func LoadErrorTemplates(errorTemplates *lib.ErrorTemplates) {
1616
errorTemplates.MustAdd(java.Language, ArithmeticException)
1717
errorTemplates.MustAdd(java.Language, NegativeArraySizeException)
1818
errorTemplates.MustAdd(java.Language, StringIndexOutOfBoundsException)
19+
errorTemplates.MustAdd(java.Language, NoSuchElementException)
1920

2021
// Compile time
2122
errorTemplates.MustAdd(java.Language, PublicClassFilenameMismatchError)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package java
2+
3+
import (
4+
"fmt"
5+
6+
lib "github.com/nedpals/errgoengine"
7+
)
8+
9+
type noSuchElementExceptionCtx struct {
10+
parentNode lib.SyntaxNode
11+
grandParentNode lib.SyntaxNode
12+
}
13+
14+
var NoSuchElementException = lib.ErrorTemplate{
15+
Name: "NoSuchElementException",
16+
Pattern: runtimeErrorPattern("java.util.NoSuchElementException", ""),
17+
OnAnalyzeErrorFn: func(cd *lib.ContextData, m *lib.MainError) {
18+
ctx := noSuchElementExceptionCtx{}
19+
query := `(method_invocation object: (_) name: (identifier) @fn-name arguments: (argument_list) (#eq? @fn-name "next")) @call`
20+
for q := m.Nearest.Query(query); q.Next(); {
21+
if q.CurrentTagName() != "fn-name" {
22+
continue
23+
}
24+
25+
node := q.CurrentNode()
26+
// nCtx.ArrayExprNode = node
27+
// m.Nearest = node.ChildByFieldName("dimensions").NamedChild(0)
28+
m.Nearest = node
29+
}
30+
31+
ctx.parentNode = m.Nearest.Parent() // expr -> method_invocation
32+
33+
// get grandparent node
34+
ctx.grandParentNode = ctx.parentNode.Parent()
35+
if !ctx.grandParentNode.IsNull() {
36+
if ctx.grandParentNode.Type() == "expression_statement" || ctx.grandParentNode.Type() == "variable_declarator" {
37+
ctx.grandParentNode = ctx.grandParentNode.Parent()
38+
}
39+
}
40+
41+
m.Context = ctx
42+
},
43+
OnGenExplainFn: func(cd *lib.ContextData, gen *lib.ExplainGenerator) {
44+
gen.Add("This error occurs when attempting to retrieve an element from an empty collection using an iterator.")
45+
},
46+
OnGenBugFixFn: func(cd *lib.ContextData, gen *lib.BugFixGenerator) {
47+
ctx := cd.MainError.Context.(noSuchElementExceptionCtx)
48+
// TODO: detect the statements that are using the variable to expand the position range of the if statement
49+
50+
gen.Add("Check if the iterator has next elements before calling `next()`", func(s *lib.BugFixSuggestion) {
51+
step := s.AddStep("Ensure that the iterator has elements before attempting to retrieve the next one.")
52+
gpLocation := ctx.grandParentNode.Location()
53+
parentName := ctx.parentNode.ChildByFieldName("object").Text()
54+
// TODO: detect the statements that are using the variable to expand the position range of the if statement
55+
wrapWithCondStatement(
56+
step,
57+
cd.MainError.Document,
58+
"if",
59+
fmt.Sprintf("%s.hasNext()", parentName),
60+
gpLocation,
61+
false,
62+
)
63+
64+
wrapWithCondStatement(
65+
step,
66+
cd.MainError.Document,
67+
"else",
68+
"",
69+
lib.Location{
70+
StartPos: gpLocation.EndPos,
71+
EndPos: gpLocation.EndPos,
72+
},
73+
true,
74+
)
75+
76+
space := getSpace(
77+
cd.MainError.Document,
78+
gpLocation.StartPos.Line, 0, gpLocation.StartPos.Column, true)
79+
80+
step.AddFix(lib.FixSuggestion{
81+
NewText: indentSpace(space, 1) + `System.out.println("No elements in the list.")`,
82+
StartPosition: lib.Position{
83+
Line: gpLocation.EndPos.Line - 2,
84+
},
85+
EndPosition: lib.Position{
86+
Line: gpLocation.EndPos.Line - 2,
87+
},
88+
})
89+
})
90+
},
91+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import java.util.*;
2+
3+
public class Main {
4+
public static void main(String[] args) {
5+
List<String> myList = new ArrayList<>();
6+
Iterator<String> iterator = myList.iterator();
7+
// Attempting to get an element from an empty list
8+
String element = iterator.next();
9+
System.out.println(element);
10+
}
11+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
template: "Java.NoSuchElementException"
2+
---
3+
Exception in thread "main" java.util.NoSuchElementException
4+
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1052)
5+
at Main.main(Main.java:8)
6+
===
7+
template: "Java.NoSuchElementException"
8+
---
9+
# NoSuchElementException
10+
This error occurs when attempting to retrieve an element from an empty collection using an iterator.
11+
```
12+
// Attempting to get an element from an empty list
13+
String element = iterator.next();
14+
^^^^
15+
System.out.println(element);
16+
}
17+
```
18+
## Steps to fix
19+
### Check if the iterator has next elements before calling `next()`
20+
Ensure that the iterator has elements before attempting to retrieve the next one.
21+
```diff
22+
Iterator<String> iterator = myList.iterator();
23+
// Attempting to get an element from an empty list
24+
- String element = iterator.next();
25+
+ if (iterator.hasNext()) {
26+
+ String element = iterator.next();
27+
+ } else {
28+
+ System.out.println("No elements in the list.")
29+
+ }
30+
+
31+
System.out.println(element);
32+
}
33+
```

0 commit comments

Comments
 (0)