Skip to content

Commit 0b3cd2d

Browse files
peqWareditorGit
andcommitted
added check for iterator method in foreach (closes #866)
test case contributed by Wareditor Co-authored-by: Wareditor <[email protected]>
1 parent 15083fc commit 0b3cd2d

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrForEachStatement.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ public static Optional<FuncLink> calcIterator(StmtForIn forEach) {
2424
// find the 'hasNext' function without parameters
2525
if (!iteratorFunc.isPresent()) {
2626
forEach.getIn().addError("For loop target " + itrType + " doesn't provide a iterator() function");
27+
} else {
28+
FuncLink f = iteratorFunc.get();
29+
if (f.isStatic() && !itrType.isStaticRef()) {
30+
iterationTarget.addError("Cannot use static iterator method from " + itrType + " on dynamic value.");
31+
} else if (!f.isStatic() && itrType.isStaticRef()) {
32+
iterationTarget.addError("Cannot use dynamic iterator method from " + itrType + " without a dynamic value.");
33+
}
2734
}
2835
return iteratorFunc;
2936
}
@@ -36,6 +43,11 @@ public static Optional<FuncLink> calcHasNext(StmtForEach forEach) {
3643
Optional<FuncLink> nextFunc = hasNext.stream().filter(nl -> nl.getParameterTypes().isEmpty()).findFirst();
3744
if (!nextFunc.isPresent()) {
3845
forEach.getIn().addError("For loop iterator doesn't provide a hasNext() function that returns boolean");
46+
} else {
47+
FuncLink f = nextFunc.get();
48+
if (f.isStatic()) {
49+
forEach.addError("Cannot use a foreach loop here, because the 'hasNext' method " + iteratorType + " is static.");
50+
}
3951
}
4052
return nextFunc;
4153
}
@@ -49,6 +61,11 @@ public static Optional<FuncLink> calcGetNext(StmtForEach forEach) {
4961
Optional<FuncLink> nextFunc = next.stream().filter(nl -> nl.getParameterTypes().isEmpty()).findFirst();
5062
if (!nextFunc.isPresent()) {
5163
forEach.getIn().addError("Target of for-loop '" + forEach.getIn().attrTyp().getName() + "' doesn't provide a proper next() function");
64+
} else {
65+
FuncLink f = nextFunc.get();
66+
if (f.isStatic()) {
67+
forEach.addError("Cannot use a foreach loop here, because the 'next' method " + iteratorType + " is static.");
68+
}
5269
}
5370
return nextFunc;
5471
}
@@ -65,6 +82,11 @@ public static Optional<FuncLink> calcClose(StmtForEach forEach) {
6582
Optional<FuncLink> closeFunc = close.stream().filter(nl -> nl.getParameterTypes().isEmpty()).findFirst();
6683
if (!closeFunc.isPresent()) {
6784
forEach.getIn().addError("Target of for-loop <" + forEach.getIn().attrTyp().getName() + " doesn't provide a proper close() function");
85+
} else {
86+
FuncLink f = closeFunc.get();
87+
if (f.isStatic()) {
88+
forEach.addError("Cannot use a foreach loop here, because the 'close' method " + iteratorType + " is static.");
89+
}
6890
}
6991
return closeFunc;
7092
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeNamedScope.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,4 @@ protected boolean isNullable() {
237237
}
238238

239239

240-
}
240+
}

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/NewFeatureTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,31 @@ public void testForInCloseBeforeReturn() {
648648
);
649649
}
650650

651+
@Test
652+
public void testIteratorStatic() { // see #866
653+
testAssertErrorsLines(false, "Cannot use static iterator method from A on dynamic value.",
654+
"package Test",
655+
"class A",
656+
" static B itr",
657+
" static function iterator() returns B",
658+
" return itr",
659+
" construct()",
660+
" itr = new B()",
661+
"",
662+
"public class B",
663+
" construct()",
664+
" function hasNext() returns boolean",
665+
" return true",
666+
" function next() returns int",
667+
" return 0",
668+
" function close()",
669+
"",
670+
"init",
671+
" let list = new A()",
672+
" for i in list"
673+
);
674+
}
675+
651676
@Test
652677
public void testIfNotDefinedAnnotation1() {
653678
testAssertOkLines(true,

0 commit comments

Comments
 (0)