Skip to content

Commit

Permalink
polish:
Browse files Browse the repository at this point in the history
+ new error msg for duplicate explicit constructor call
+ remove unnecessary checks
+ code comments
  • Loading branch information
stephan-herrmann committed Jul 13, 2024
1 parent dc1360e commit 8b5b645
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2658,4 +2658,9 @@ public interface IProblem {
*/
int MessageSendInEarlyConstructionContext = PreviewRelated + 2027;

/**
* @since 3.39
* @noreference preview feature
*/
int DuplicateExplicitConstructorCall = PreviewRelated + 2028;
}
Original file line number Diff line number Diff line change
Expand Up @@ -544,9 +544,7 @@ public TypeBinding resolveType(BlockScope scope) {
}

protected void checkPreConstructorContext(BlockScope scope) {
if (this.type != null
&& this.type.resolvedType instanceof ReferenceBinding currentType
&& currentType.hasEnclosingInstanceContext()) {
if (this.type != null && this.type.resolvedType instanceof ReferenceBinding currentType) {
TypeBinding uninitialized = scope.getMatchingUninitializedType(currentType, !currentType.isLocalType());
if (uninitialized != null)
scope.problemReporter().allocationInEarlyConstructionContext(this, this.resolvedType, uninitialized);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ public void resolveStatements() {
super.resolveStatements();
}

private ExplicitConstructorCall getLateConstructorCall() {
ExplicitConstructorCall getLateConstructorCall() {
if (!JavaFeature.FLEXIBLE_CONSTRUCTOR_BODIES.matchesCompliance(this.scope.compilerOptions()))
return null;
if (this.constructorCall != null && !this.constructorCall.isImplicitSuper()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.JavaFeature;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
Expand Down Expand Up @@ -321,15 +322,22 @@ public void resolve(BlockScope scope) {
}
boolean isFirstStatement = true;
boolean hasError = false;
ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
if (methodDeclaration == null || !methodDeclaration.isConstructor()) {
hasError = true;
} else if (((ConstructorDeclaration) methodDeclaration).constructorCall != this) {
} else if (constructorDeclaration.constructorCall != this) {
isFirstStatement = false;
hasError = !scope.isInsideEarlyConstructionContext(null, false);
}
if (hasError) {
if (!(methodDeclaration instanceof CompactConstructorDeclaration)) {// already flagged for CCD
scope.problemReporter().invalidExplicitConstructorCall(this);
ExplicitConstructorCall lateConstructorCall = constructorDeclaration.getLateConstructorCall();
if (lateConstructorCall != null && lateConstructorCall != this
&& JavaFeature.FLEXIBLE_CONSTRUCTOR_BODIES.isSupported(scope.compilerOptions())) {
scope.problemReporter().duplicateExplicitConstructorCall(this);
} else {
scope.problemReporter().invalidExplicitConstructorCall(this);
}
}
// fault-tolerance
if (this.qualification != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public enum JavaFeature {
* JEP 482. The primary enabling check is in ConstructorDeclaration.getLateConstructor().
* If that method returns non-null, then ClassScope.enterEarlyConstructionContext() will follow,
* which enables further analysis and actions.
* In particular, when scope.isInsideEarlyConstructionContext() answers true,
* then we can be sure that availability of this feature has been checked / reported.
*/
FLEXIBLE_CONSTRUCTOR_BODIES(ClassFileConstants.JDK23,
Messages.bind(Messages.flexible_constructor_bodies),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ public class ClassScope extends Scope {
/**
* This is the primary flag for detection of early construction contexts (JEP 482).
* It is temporarily set on the scope of a class while processing statements of this class's
* early construction context (during resolveType() and during generateCode())
* early construction context (during resolveType(), analyseCode() and generateCode())
* <p>Main access is via {@link Scope#enterEarlyConstructionContext()}, {@link Scope#leaveEarlyConstructionContext()}
* and {@link Scope#isInsideEarlyConstructionContext(TypeBinding, boolean)}.</p>
* <p>For the case of {@link LambdaExpression} this information is captured during resolve
* into {@code scopesInEarlyConstruction}, for use during generateCode(), which doesn't have the
* scope of the lambda declaration.
* context of the lambda declaration.
* </p>
*/
public boolean insideEarlyConstructionContext = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2535,6 +2535,9 @@ public ModuleBinding module() {
}

public boolean hasEnclosingInstanceContext() {
// This method intentionally disregards early construction contexts (JEP 482).
// Details of how each outer level is handled are coordinated in
// TypeDeclaration.manageEnclosingInstanceAccessIfNecessary().
if (isStatic())
return false;
if (isNestedType())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4240,6 +4240,14 @@ public void invalidExplicitConstructorCall(ASTNode location) {
location.sourceStart,
location.sourceEnd);
}
public void duplicateExplicitConstructorCall(ASTNode location) {
this.handle(
IProblem.DuplicateExplicitConstructorCall,
NoArgument,
NoArgument,
location.sourceStart,
location.sourceEnd);
}
public void invalidExpressionAsStatement(Expression expression){
this.handle(
IProblem.InvalidExpressionAsStatement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,7 @@
2025 = Cannot use ''{0}'' in an early construction context (except in a simple field assignment)
2026 = Cannot instantiate class {0} in an early construction context of class {1}
2027 = Cannot invoke method {0}() in an early construction context
2028 = Constructor cannot have more than one explicit constructor call

### ELABORATIONS
## Access restrictions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,7 @@ class ProblemAttributes {
expectedProblemAttributes.put("AllocationInEarlyConstructionContext", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("MessageSendInEarlyConstructionContext", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("DisallowedStatementInEarlyConstructionContext", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("DuplicateExplicitConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("NamedPatternVariablesDisallowedHere", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("OperandStackExceeds64KLimit", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("OperandStackSizeInappropriate", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
Expand Down Expand Up @@ -2479,6 +2480,7 @@ class ProblemAttributes {
expectedProblemAttributes.put("AllocationInEarlyConstructionContext", SKIP);
expectedProblemAttributes.put("MessageSendInEarlyConstructionContext", SKIP);
expectedProblemAttributes.put("DisallowedStatementInEarlyConstructionContext", SKIP);
expectedProblemAttributes.put("DuplicateExplicitConstructorCall", SKIP);
expectedProblemAttributes.put("NamedPatternVariablesDisallowedHere", SKIP);
expectedProblemAttributes.put("OperandStackExceeds64KLimit", SKIP);
expectedProblemAttributes.put("OperandStackSizeInappropriate", SKIP);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1917,4 +1917,28 @@ class C4 { // not early for C3
""";
runner.runNegativeTest();
}

public void testDuplicateCalls() {
// but no access to outer this from local class
Runner runner = new Runner(false);
runner.testFiles = new String[] {
"X.java",
"""
class X {
X() {
System.out.println();
super();
super(); // illegal
}
}
"""
};
runner.expectedCompilerLog = "----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" super(); // illegal\n" +
" ^^^^^^^^\n" +
"Constructor cannot have more than one explicit constructor call\n" +
"----------\n";
runner.runNegativeTest();
}
}

0 comments on commit 8b5b645

Please sign in to comment.