Skip to content

Commit

Permalink
Fix #4877 where the groovy parser would fail to parse variables whose…
Browse files Browse the repository at this point in the history
… names started with "def"
  • Loading branch information
sambsnyd committed Jan 10, 2025
1 parent e69e8ca commit fa1fc56
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ public void visitNotExpression(NotExpression expression) {
public void visitDeclarationExpression(DeclarationExpression expression) {
Space prefix = whitespace();
Optional<MultiVariable> multiVariable = maybeMultiVariable();
List<J.Modifier> modifiers = getModifiers();
List<J.Modifier> modifiers = getModifiers(expression.getVariableExpression());
TypeTree typeExpr = visitVariableExpressionType(expression.getVariableExpression());

J.VariableDeclarations.NamedVariable namedVariable;
Expand Down Expand Up @@ -1438,25 +1438,28 @@ private Optional<MultiVariable> maybeMultiVariable() {
return Optional.empty();
}

private List<J.Modifier> getModifiers() {
private List<J.Modifier> getModifiers(Variable variable) {
String varName = variable.getName();
List<J.Modifier> modifiers = new ArrayList<>();
int saveCursor = cursor;
Space prefix = whitespace();
while (source.startsWith("def", cursor) || source.startsWith("var", cursor) || source.startsWith("final", cursor)) {
if (source.startsWith("var", cursor)) {
modifiers.add(new J.Modifier(randomId(), prefix, Markers.EMPTY, "var", J.Modifier.Type.LanguageExtension, emptyList()));
skip("var");
} else if (source.startsWith("def", cursor)) {
modifiers.add(new J.Modifier(randomId(), prefix, Markers.EMPTY, "def", J.Modifier.Type.LanguageExtension, emptyList()));
skip("def");
} else if (source.startsWith("final", cursor)) {
modifiers.add(new J.Modifier(randomId(), prefix, Markers.EMPTY, "final", J.Modifier.Type.LanguageExtension, emptyList()));
skip("final");
} else {
break;
}
Set<String> possibleModifiers = new LinkedHashSet<>(modifierNameToType.keySet());
String currentModifier = possibleModifiers.stream().filter(modifierName -> source.startsWith(modifierName, cursor))
.findFirst()
.orElse(null);
while (currentModifier != null) {
possibleModifiers.remove(currentModifier);
modifiers.add(new J.Modifier(randomId(), prefix, Markers.EMPTY, currentModifier, modifierNameToType.get(currentModifier), emptyList()));
skip(currentModifier);
saveCursor = cursor;
prefix = whitespace();
currentModifier = possibleModifiers.stream()
.filter(modifierName ->
// Try to avoid confusing a variable name with an incidentally similar modifier keyword
(varName.length() < modifierName.length() || !source.startsWith(varName, cursor)) &&
source.startsWith(modifierName, cursor))
.findFirst()
.orElse(null);
}
cursor = saveCursor;
return modifiers;
Expand Down Expand Up @@ -1513,7 +1516,7 @@ public void visitForLoop(ForStatement forLoop) {
} else {
Parameter param = forLoop.getVariable();
Space paramFmt = whitespace();
List<J.Modifier> modifiers = getModifiers();
List<J.Modifier> modifiers = getModifiers(param);
TypeTree paramType = param.getOriginType().getColumnNumber() >= 0 ? visitTypeTree(param.getOriginType()) : null;
JRightPadded<J.VariableDeclarations.NamedVariable> paramName = JRightPadded.build(
new J.VariableDeclarations.NamedVariable(randomId(), whitespace(), Markers.EMPTY,
Expand Down Expand Up @@ -2773,4 +2776,22 @@ private static ClassNode staticType(Parameter parameter) {
return inferred;
}
}

private static final Map<String, J.Modifier.Type> modifierNameToType;
static {
modifierNameToType = new LinkedHashMap<>();
modifierNameToType.put("def", J.Modifier.Type.LanguageExtension);
modifierNameToType.put("var", J.Modifier.Type.LanguageExtension);
modifierNameToType.put("public", J.Modifier.Type.Public);
modifierNameToType.put("protected", J.Modifier.Type.Protected);
modifierNameToType.put("private", J.Modifier.Type.Private);
modifierNameToType.put("abstract", J.Modifier.Type.Abstract);
modifierNameToType.put("static", J.Modifier.Type.Static);
modifierNameToType.put("final", J.Modifier.Type.Final);
modifierNameToType.put("volatile", J.Modifier.Type.Volatile);
modifierNameToType.put("synchronized", J.Modifier.Type.Synchronized);
modifierNameToType.put("native", J.Modifier.Type.Native);
modifierNameToType.put("default", J.Modifier.Type.Default);
modifierNameToType.put("strictfp", J.Modifier.Type.Strictfp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,14 @@ void defAndExplicitReturnType() {
)
);
}

@Issue("https://github.com/openrewrite/rewrite/issues/4877")
@Test
void defVariableStartsWithDef() {
rewriteRun(
groovy("""
def defaultPublicStaticFinal = 0
""")
);
}
}

0 comments on commit fa1fc56

Please sign in to comment.