Skip to content

Commit 1cc9c7d

Browse files
committed
added @ifNotDefined for #793
functions annotated with @ifNotDefined are only called, when no other definition of the function is in scope
1 parent c88e7e7 commit 1cc9c7d

File tree

5 files changed

+96
-6
lines changed

5 files changed

+96
-6
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.Collection;
1616
import java.util.Collections;
1717
import java.util.List;
18+
import java.util.stream.Collectors;
1819

1920

2021
/**
@@ -178,6 +179,11 @@ private static FuncLink searchFunction(String funcName, @Nullable FuncRef node,
178179
return Utils.getFirst(funcs);
179180
}
180181

182+
funcs = ignoreWithIfNotDefinedAnnotation(node, funcs);
183+
if (funcs.size() == 1) {
184+
return Utils.getFirst(funcs);
185+
}
186+
181187
funcs = useLocalPackageIfPossible(node, funcs);
182188
if (funcs.size() == 1) {
183189
return Utils.getFirst(funcs);
@@ -188,6 +194,12 @@ private static FuncLink searchFunction(String funcName, @Nullable FuncRef node,
188194
return Utils.getFirst(funcs);
189195
}
190196

197+
private static List<FuncLink> ignoreWithIfNotDefinedAnnotation(FuncRef node, List<FuncLink> funcs) {
198+
return funcs.stream()
199+
.filter(fl -> !fl.hasIfNotDefinedAnnotation())
200+
.collect(Collectors.toList());
201+
}
202+
191203

192204
private static List<FuncLink> useLocalPackageIfPossible(FuncRef node,
193205
List<FuncLink> funcs) {

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
import de.peeeq.wurstscript.types.WurstType;
77
import de.peeeq.wurstscript.types.WurstTypeUnknown;
88
import de.peeeq.wurstscript.utils.Utils;
9+
import fj.data.Either;
10+
import org.jetbrains.annotations.NotNull;
911

1012
import java.util.ArrayList;
1113
import java.util.Collection;
1214
import java.util.List;
15+
import java.util.stream.Collectors;
1316

1417
public class AttrFunctionSignature {
1518

@@ -37,20 +40,25 @@ private static FunctionSignature filterSigs(
3740
return FunctionSignature.empty;
3841
}
3942

40-
List<FunctionSignature> candidates = new ArrayList<>();
41-
for (FunctionSignature sig : sigs) {
42-
sig = sig.matchAgainstArgs(argTypes, location);
43-
if (sig != null) {
44-
candidates.add(sig);
45-
}
43+
List<FunctionSignature> candidates = filterByArgumentTypes(sigs, argTypes, location);
44+
if (candidates.isEmpty()) {
45+
// parameters match for no element, just return the first signature
46+
return Utils.getFirst(sigs);
47+
} else if (candidates.size() == 1) {
48+
return candidates.get(0);
4649
}
50+
51+
candidates = filterByIfNotDefinedAnnotation(candidates);
4752
if (candidates.isEmpty()) {
4853
// parameters match for no element, just return the first signature
4954
return Utils.getFirst(sigs);
5055
} else if (candidates.size() == 1) {
5156
return candidates.get(0);
5257
}
5358

59+
60+
61+
5462
if (argTypes.stream().noneMatch(t -> t instanceof WurstTypeUnknown)) {
5563
// only show overloading error, if type for all arguments could be determined
5664
StringBuilder alternatives = new StringBuilder();
@@ -63,6 +71,24 @@ private static FunctionSignature filterSigs(
6371
return candidates.get(0);
6472
}
6573

74+
private static List<FunctionSignature> filterByIfNotDefinedAnnotation(List<FunctionSignature> candidates) {
75+
return candidates.stream()
76+
.filter(sig -> !sig.hasIfNotDefinedAnnotation())
77+
.collect(Collectors.toList());
78+
}
79+
80+
@NotNull
81+
private static List<FunctionSignature> filterByArgumentTypes(Collection<FunctionSignature> sigs, List<WurstType> argTypes, StmtCall location) {
82+
List<FunctionSignature> candidates = new ArrayList<>();
83+
for (FunctionSignature sig : sigs) {
84+
sig = sig.matchAgainstArgs(argTypes, location);
85+
if (sig != null) {
86+
candidates.add(sig);
87+
}
88+
}
89+
return candidates;
90+
}
91+
6692
private static boolean isInitTrigFunc(StmtCall e) {
6793
if (e instanceof ExprFunctionCall) {
6894
ExprFunctionCall e2 = (ExprFunctionCall) e;

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/FuncLink.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,8 @@ public boolean equals(Object o) {
276276
public int hashCode() {
277277
return Objects.hash(def);
278278
}
279+
280+
public boolean hasIfNotDefinedAnnotation() {
281+
return def.attrHasAnnotation("ifNotDefined");
282+
}
279283
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,14 @@ public List<TypeParamDef> case_ConstructorDef(ConstructorDef c) {
254254
});
255255
}
256256

257+
public boolean hasIfNotDefinedAnnotation() {
258+
if (trace instanceof HasModifier) {
259+
HasModifier m = (HasModifier) this.trace;
260+
return m.attrHasAnnotation("ifNotDefined");
261+
}
262+
return false;
263+
}
264+
257265
public static class ArgsMatchResult {
258266
private final FunctionSignature sig;
259267
private final ImmutableList<CompileError> errors;

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,44 @@ public void testForInCloseBeforeReturn() {
397397
);
398398
}
399399

400+
@Test
401+
public void testIfNotDefinedAnnotation1() {
402+
testAssertOkLines(true,
403+
"function foo takes integer x returns integer",
404+
" return x + 1",
405+
"endfunction",
406+
"package Test",
407+
"native testSuccess()",
408+
"@ifNotDefined function foo(int x) returns int",
409+
" return x + 2",
410+
"init",
411+
" if foo(3) == 4",
412+
" testSuccess()"
413+
);
414+
}
415+
416+
@Test
417+
public void testIfNotDefinedAnnotation2() {
418+
testAssertOkLines(true,
419+
"package Test",
420+
"native testSuccess()",
421+
"@ifNotDefined function foo(int x) returns int",
422+
" return x + 2",
423+
"init",
424+
" if foo(3) == 5",
425+
" testSuccess()"
426+
);
427+
}
428+
429+
@Test
430+
public void testIfNotDefinedAnnotationNative() {
431+
testAssertOkLines(true,
432+
"native testSuccess takes nothing returns nothing",
433+
"package Test",
434+
"@ifNotDefined native testSuccess()",
435+
"init",
436+
" testSuccess()"
437+
);
438+
}
439+
400440
}

0 commit comments

Comments
 (0)