From e14cbe39bb9ea6faab217ced935ab23c97577ded Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Fri, 25 Oct 2024 16:13:56 +0200 Subject: [PATCH] narrow down the heuristics to not convert "real" fields into arguments and also play well with existing arguments strengthen test expectation in existing tests --- .../jdt/internal/compiler/parser/Parser.java | 7 ++++ .../compiler/parser/RecoveredAnnotation.java | 4 ++ .../compiler/parser/RecoveredMethod.java | 22 +++++++++- .../parser/AnnotationDietRecoveryTest.java | 40 ++++++++++++++----- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java index 6b07efd14d8..865c7b960c3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -6668,6 +6668,13 @@ protected void consumeZeroTypeAnnotations() { // Name ::= SimpleName // TypeAnnotationsopt ::= $empty pushOnTypeAnnotationLengthStack(0); // signal absence of @308 annotations. + if (this.currentElement instanceof RecoveredAnnotation ann + && ann.parent instanceof RecoveredMethod meth + && !meth.foundOpeningBrace + && this.currentToken == TokenNameRPAREN) { + // take note of an incomplete annotation "@Ann(v=)": + meth.incompleteParameterAnnotationSeen = true; + } } // BEGIN_AUTOGENERATED_REGION_CONSUME_RULE // This method is part of an automatic generation : do NOT edit-modify diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java index 101211281ae..95b5dd8a17b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java @@ -191,6 +191,10 @@ public void setKind(int kind) { this.kind = kind; } + public int sourceStart() { + return this.sourceStart; + } + @Override public int sourceEnd() { if (this.annotation == null) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java index 259b903aadd..9e5dea4a78a 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java @@ -15,6 +15,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; @@ -48,6 +49,8 @@ public class RecoveredMethod extends RecoveredElement implements TerminalTokens RecoveredAnnotation[] pendingAnnotations; int pendingAnnotationCount; + public boolean incompleteParameterAnnotationSeen = false; + public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){ super(parent, bracketBalance, parser); this.methodDeclaration = methodDeclaration; @@ -141,18 +144,28 @@ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanc private boolean recoverAsArgument(FieldDeclaration fieldDeclaration) { if (!this.foundOpeningBrace && this.methodDeclaration.declarationSourceEnd == 0 - && this.methodDeclaration.arguments == null) { // misparsed parameter? + && this.incompleteParameterAnnotationSeen) { // misparsed parameter? long position = ((long) fieldDeclaration.sourceStart << 32)+fieldDeclaration.sourceEnd; Argument arg = new Argument(fieldDeclaration.name, position, fieldDeclaration.type, fieldDeclaration.modifiers); - this.methodDeclaration.arguments = new Argument[] { arg }; + if (this.methodDeclaration.arguments == null) { + this.methodDeclaration.arguments = new Argument[] { arg }; + } else { + int len = this.methodDeclaration.arguments.length; + this.methodDeclaration.arguments = Arrays.copyOf(this.methodDeclaration.arguments, len+1); + this.methodDeclaration.arguments[len] = arg; + } int annotCount = this.pendingAnnotationCount; if (this.pendingAnnotations != null) { + int end = 0; arg.annotations = new Annotation[annotCount]; for (int i = 0; i < this.pendingAnnotationCount; i++) { arg.annotations[i] = this.pendingAnnotations[i].annotation; if (i == 0) arg.declarationSourceStart = arg.annotations[i].sourceStart; + end = arg.sourceEnd; } + if (end > 0) + this.methodDeclaration.bodyStart = end + 1; } return true; } @@ -631,6 +644,11 @@ public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengt this.pendingAnnotations = new RecoveredAnnotation[5]; this.pendingAnnotationCount = 0; } else { + if (this.pendingAnnotationCount > 0) { + RecoveredAnnotation lastAnnot = this.pendingAnnotations[this.pendingAnnotationCount-1]; + if (lastAnnot.sourceStart() == annotationStart) + return this; + } if (this.pendingAnnotationCount == this.pendingAnnotations.length) { System.arraycopy( this.pendingAnnotations, diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java index 44c48c6fe00..18ba54146a5 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AnnotationDietRecoveryTest.java @@ -38,6 +38,10 @@ public class AnnotationDietRecoveryTest extends AbstractCompilerTest { private static final boolean CHECK_ALL_PARSE = true; public static boolean optimizeStringLiterals = false; + static { +// TESTS_NAMES = new String[] { "test0025" }; + } + public AnnotationDietRecoveryTest(String testName){ super(testName); } @@ -1210,7 +1214,7 @@ public void test0024() { "public class X {\n" + " public X() {\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation(name) int param2) {\n" + " }\n" + "}\n"; @@ -1220,7 +1224,7 @@ public void test0024() { " public X() {\n" + " super();\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation(name) int param2) {\n" + " }\n" + "}\n"; @@ -1229,7 +1233,13 @@ public void test0024() { expectedDietUnitToString; String expectedCompletionDietUnitToString = - expectedDietUnitToString; + "package a;\n" + + "public class X {\n" + + " public X() {\n" + + " }\n" + + " void foo(int param1) {\n" + + " }\n" + + "}\n"; String testName = ""; checkParse( @@ -1254,7 +1264,7 @@ public void test0025() { "public class X {\n" + " public X() {\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation(name = $missing$) int param2) {\n" + " }\n" + "}\n"; @@ -1264,7 +1274,7 @@ public void test0025() { " public X() {\n" + " super();\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation(name = $missing$) int param2) {\n" + " }\n" + "}\n"; @@ -1272,7 +1282,13 @@ public void test0025() { expectedDietUnitToString; String expectedCompletionDietUnitToString = - expectedDietUnitToString; + "package a;\n" + + "public class X {\n" + + " public X() {\n" + + " }\n" + + " void foo(int param1) {\n" + + " }\n" + + "}\n"; String testName = ""; checkParse( @@ -1297,7 +1313,7 @@ public void test0026() { "public class X {\n" + " public X() {\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation @AnAnnotation1(name1 = \"a\",name2 = $missing$) int param2) {\n" + " }\n" + "}\n"; @@ -1307,7 +1323,7 @@ public void test0026() { " public X() {\n" + " super();\n" + " }\n" + - " void foo(int param1) {\n" + + " void foo(int param1, @AnAnnotation @AnAnnotation1(name1 = \"a\",name2 = $missing$) int param2) {\n" + " }\n" + "}\n"; @@ -1315,7 +1331,13 @@ public void test0026() { expectedDietUnitToString; String expectedCompletionDietUnitToString = - expectedDietUnitToString; + "package a;\n" + + "public class X {\n" + + " public X() {\n" + + " }\n" + + " void foo(int param1) {\n" + + " }\n" + + "}\n"; String testName = ""; checkParse(