Skip to content

Commit

Permalink
Fix error messages related to _
Browse files Browse the repository at this point in the history
Signed-off-by: David Thompson <[email protected]>
  • Loading branch information
datho7561 committed Nov 8, 2023
1 parent bb31692 commit c362ae3
Show file tree
Hide file tree
Showing 15 changed files with 74 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2564,4 +2564,10 @@ public interface IProblem {
* @since 3.35
*/
int SyntheticAccessorNotEnclosingMethod = MethodRelated + 1990;

/**
* @since 3.36
* @noreference preview feature
*/
int FieldNameCannotBeUnderscore = PreviewRelated + 2000;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
Expand Down Expand Up @@ -144,4 +145,15 @@ public void setDepth(int depth) {
public void setFieldIndex(int depth) {
// do nothing by default
}

/**
* Returns true if this variable is an unnamed variable (_) and false otherwise.
*
* @param scope used to determine source level
*/
public boolean isUnnamed(BlockScope scope) {
return this.name.length == 1 && this.name[0] == '_'
&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK21
&& scope.compilerOptions().enablePreviewFeatures;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,14 @@ public TypeBinding bind(MethodScope scope, TypeBinding typeBinding, boolean used
if (existingVariable != null && existingVariable.isValidBinding()){
final boolean localExists = existingVariable instanceof LocalVariableBinding;
if (localExists && this.hiddenVariableDepth == 0) {
if ((this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope()) {
scope.problemReporter().lambdaRedeclaresArgument(this);
} else if (scope.referenceContext instanceof CompactConstructorDeclaration) {
// skip error reporting - hidden params - already reported in record components
} else {
scope.problemReporter().redefineArgument(this);
if (!this.isUnnamed(scope)) {
if ((this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope()) {
scope.problemReporter().lambdaRedeclaresArgument(this);
} else if (scope.referenceContext instanceof CompactConstructorDeclaration) {
// skip error reporting - hidden params - already reported in record components
} else {
scope.problemReporter().redefineArgument(this);
}
}
} else {
boolean isSpecialArgument = false;
Expand Down Expand Up @@ -234,7 +236,7 @@ public TypeBinding resolveForCatch(BlockScope scope) {
}
}
Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
if (existingVariable != null && existingVariable.isValidBinding() && !isUnnamed(scope)) {
if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
scope.problemReporter().redefineArgument(this);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public FieldDeclaration( char[] name, int sourceStart, int sourceEnd) {
}

public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) {
if (this.isUnnamed(initializationScope)) {
initializationScope.problemReporter().fieldNameCannotBeUnderscore(this);
}
if (this.binding != null && !this.binding.isUsed() && this.binding.isOrEnclosedByPrivateType()) {
if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
if (!this.isARecordComponent) // record component used by implicit methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public void resolve(BlockScope scope, boolean isPatternVariable) {
}

Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
if (existingVariable != null && existingVariable.isValidBinding() && !this.isUnnamed(scope)) {
boolean localExists = existingVariable instanceof LocalVariableBinding;
if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope() && this.hiddenVariableDepth == 0) {
scope.problemReporter().lambdaRedeclaresLocal(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void collectPatternVariablesToScope(LocalVariableBinding[] variables, Blo
if (this.resolvedType == null) {
this.resolveType(scope);
}
if (this.local != null && this.local.binding != null) {
if (this.local != null && this.local.binding != null && !this.local.isUnnamed(scope)) {
LocalVariableBinding binding = this.local.binding;
if (variables != null) {
for (LocalVariableBinding variable : variables) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public enum JavaFeature {
new char[][] {},
false),
UNNAMMED_PATTERNS_AND_VARS(ClassFileConstants.JDK21,
Messages.bind(Messages.unnammed_patterns_and_vars),
Messages.bind(Messages.unnamed_patterns_and_vars),
new char[][] {},
true),
UNNAMMED_CLASSES_AND_INSTANCE_MAIN_METHODS(ClassFileConstants.JDK21,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ void computeLocalVariablePositions(int ilocal, int initOffset, CodeStream codeSt
// do not report fake used variable
if (local.useFlag == LocalVariableBinding.UNUSED
&& (local.declaration != null) // unused (and non secret) local
&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable
&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0) // declaration is reachable
&& !local.declaration.isUnnamed(local.declaringScope)) {

if (local.isCatchParameter()) {
problemReporter().unusedExceptionParameter(local.declaration); // report unused catch arguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ records = Records
sealed_types = Sealed Types
pattern_matching_switch = Pattern Matching in Switch
record_patterns = Record Pattern
unnammed_patterns_and_vars = Unnammed Patterns and Variables
unnamed_patterns_and_vars = Unnamed Patterns and Variables
unnamed_classes_and_instance_main_methods = Unnamed Classes and Instance Main Methods
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ protected int actFromTokenOrSynthetic(int previousAct) {
protected boolean parsingJava15Plus;
protected boolean parsingJava17Plus;
protected boolean parsingJava18Plus;
protected boolean parsingJava21Plus;
protected boolean previewEnabled;
protected boolean parsingJava11Plus;
protected int unstackedAct = ERROR_ACTION;
Expand Down Expand Up @@ -1017,6 +1018,7 @@ public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
this.parsingJava15Plus = this.options.sourceLevel >= ClassFileConstants.JDK15;
this.parsingJava17Plus = this.options.sourceLevel >= ClassFileConstants.JDK17;
this.parsingJava18Plus = this.options.sourceLevel >= ClassFileConstants.JDK18;
this.parsingJava21Plus = this.options.sourceLevel >= ClassFileConstants.JDK21;
this.previewEnabled = this.options.sourceLevel == ClassFileConstants.getLatestJDKLevel() && this.options.enablePreviewFeatures;
this.astLengthStack = new int[50];
this.expressionLengthStack = new int[30];
Expand Down Expand Up @@ -7485,9 +7487,9 @@ protected void consumeRule(int act) {
consumePatternListopt();
break;

case 369 : if (DEBUG) { System.out.println("PushLeftBrace ::="); } //$NON-NLS-1$
consumePushLeftBrace();
break;
case 368 : if (DEBUG) { System.out.println("ComponentPatternList ::= ComponentPatternList COMMA..."); } //$NON-NLS-1$
consumePatternList();
break;

case 370 : if (DEBUG) { System.out.println("TypePattern ::= Modifiersopt Type UNDERSCORE"); } //$NON-NLS-1$
consumeTypePattern();
Expand Down Expand Up @@ -9115,8 +9117,13 @@ protected void consumeLambdaHeader() {
if (argument.isReceiver()) {
problemReporter().illegalThis(argument);
}
if (argument.name.length == 1 && argument.name[0] == '_')
problemReporter().illegalUseOfUnderscoreAsAnIdentifier(argument.sourceStart, argument.sourceEnd, true); // true == lambdaParameter
if (this.parsingJava8Plus && !(this.parsingJava21Plus && this.previewEnabled) && argument.name.length == 1 && argument.name[0] == '_') {
if (this.parsingJava21Plus) {
problemReporter().validateJavaFeatureSupport(JavaFeature.UNNAMMED_PATTERNS_AND_VARS, argument.sourceStart, argument.sourceEnd);
} else {
problemReporter().illegalUseOfUnderscoreAsAnIdentifier(argument.sourceStart, argument.sourceEnd, true); // true == lambdaParameter
}
}
}
LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
lexp.setArguments(arguments);
Expand Down Expand Up @@ -13944,8 +13951,12 @@ protected void pushIdentifier(char [] identifier, long position) {
stackLength);
}
this.identifierLengthStack[this.identifierLengthPtr] = 1;
if (this.parsingJava8Plus && identifier.length == 1 && identifier[0] == '_' && !this.processingLambdaParameterList) {
problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, this.parsingJava9Plus);
if (this.parsingJava8Plus && !(this.parsingJava21Plus && this.previewEnabled) && identifier.length == 1 && identifier[0] == '_' && !this.processingLambdaParameterList) {
if (this.parsingJava21Plus) {
problemReporter().validateJavaFeatureSupport(JavaFeature.UNNAMMED_PATTERNS_AND_VARS, (int) (position >>> 32), (int) position);
} else {
problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, this.parsingJava9Plus);
}
}
}
protected void pushIdentifier() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12466,6 +12466,14 @@ public void falseLiteralInGuard(Expression exp) {
exp.sourceStart,
exp.sourceEnd);
}
public void fieldNameCannotBeUnderscore(FieldDeclaration fieldDeclaration) {
this.handle(
IProblem.FieldNameCannotBeUnderscore,
NoArgument,
NoArgument,
fieldDeclaration.sourceStart,
fieldDeclaration.sourceEnd);
}
public boolean scheduleProblemForContext(Runnable problemComputation) {
if (this.referenceContext != null) {
CompilationResult result = this.referenceContext.compilationResult();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,9 @@

1990 = Access to {1}({2}) from the type {0} is emulated by a synthetic accessor method

# Unnamed variables and patterns (preview in Java 21, set for release in Java 22)
2000 = Field name cannot be '_'

### ELABORATIONS
## Access restrictions
78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private Messages() {
public static String sealed_types;
public static String pattern_matching_switch;
public static String record_patterns;
public static String unnammed_patterns_and_vars;
public static String unnamed_patterns_and_vars;
public static String unnamed_classes_and_instance_main_methods;

static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,7 @@ class ProblemAttributes {
expectedProblemAttributes.put("ClassExtendFinalRecord", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("RecordErasureIncompatibilityInCanonicalConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("JavadocInvalidModule", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("FieldNameCannotBeUnderscore", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
StringBuffer failures = new StringBuffer();
StringBuffer correctResult = new StringBuffer(70000);
Field[] fields = (iProblemClass = IProblem.class).getFields();
Expand Down Expand Up @@ -2429,6 +2430,7 @@ class ProblemAttributes {
expectedProblemAttributes.put("ClassExtendFinalRecord", SKIP);
expectedProblemAttributes.put("RecordErasureIncompatibilityInCanonicalConstructor", SKIP);
expectedProblemAttributes.put("JavadocInvalidModule", SKIP);
expectedProblemAttributes.put("FieldNameCannotBeUnderscore", SKIP);

Map constantNamesIndex = new HashMap();
Field[] fields = JavaCore.class.getFields();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7371,6 +7371,10 @@ public void testIntersectionCast() {
public void testUnderScoreParameter() {
String level = this.complianceLevel >= ClassFileConstants.JDK9 ? "ERROR" : "WARNING";
String errorMessage = this.complianceLevel >= ClassFileConstants.JDK9 ? "\'_\' is a keyword from source level 9 onwards, cannot be used as identifier\n" : "\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n";
if (this.complianceLevel >= ClassFileConstants.JDK21) {
errorMessage = "Unnamed Patterns and Variables is a preview feature and disabled by default. Use --enable-preview to enable\n";
}
String otherErrorMessage = this.complianceLevel >= ClassFileConstants.JDK21 ? errorMessage : "\'_\' is a keyword from source level 9 onwards, cannot be used as identifier\n";
this.runNegativeTest(
new String[] {
"X.java",
Expand All @@ -7389,7 +7393,7 @@ public void testUnderScoreParameter() {
"1. ERROR in X.java (at line 6)\n" +
" F f = (int _) -> {\n" +
" ^\n" +
"\'_\' is a keyword from source level 9 onwards, cannot be used as identifier\n" +
otherErrorMessage +
"----------\n" +
"2. "+ level +" in X.java (at line 8)\n" +
" F f2 = _ -> {};\n" +
Expand All @@ -7399,7 +7403,7 @@ public void testUnderScoreParameter() {
"3. ERROR in X.java (at line 8)\n" +
" F f2 = _ -> {};\n" +
" ^\n" +
"\'_\' is a keyword from source level 9 onwards, cannot be used as identifier\n" +
otherErrorMessage +
"----------\n"
);
}
Expand Down

0 comments on commit c362ae3

Please sign in to comment.