Skip to content

Commit 598d990

Browse files
[Records 2.0] Alternate generation of synthetic component accessors and record override methods. (eclipse-jdt#3954)
Avoid generating duplicate methods in the first place rather than generate, detect duplication and delete which is clunky. * Fixes eclipse-jdt#3901
1 parent ed79bb8 commit 598d990

File tree

11 files changed

+187
-370
lines changed

11 files changed

+187
-370
lines changed

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ClassFile.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,7 +2345,9 @@ public void completeMethodInfo(
23452345
AbstractMethodDeclaration methodDeclaration = binding.sourceMethod();
23462346
if (methodDeclaration != null) {
23472347
if ((methodDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
2348-
Argument[] arguments = methodDeclaration.arguments;
2348+
AbstractVariableDeclaration[] arguments = binding.isCompactConstructor() ?
2349+
getRecordComponents(binding.declaringClass) : methodDeclaration.arguments;
2350+
23492351
if (arguments != null) {
23502352
completeArgumentAnnotationInfo(arguments, allTypeAnnotationContexts);
23512353
}
@@ -3758,7 +3760,7 @@ private int addBootStrapRecordEntry(int localContentsOffset, TypeDeclaration typ
37583760

37593761
assert type instanceof SourceTypeBinding;
37603762
SourceTypeBinding sourceType = (SourceTypeBinding) type;
3761-
FieldBinding[] recordComponents = sourceType.getImplicitComponentFields();
3763+
RecordComponentBinding[] recordComponents = sourceType.components();
37623764

37633765
int numArgs = 2 + recordComponents.length;
37643766
this.contents[numArgsLocation++] = (byte) (numArgs >> 8);
@@ -3776,10 +3778,10 @@ private int addBootStrapRecordEntry(int localContentsOffset, TypeDeclaration typ
37763778
if (recordComponents.length * 2 + localContentsOffset >= this.contents.length) {
37773779
resizeContents(recordComponents.length * 2);
37783780
}
3779-
for (FieldBinding field : recordComponents) {
3781+
for (RecordComponentBinding component : recordComponents) {
37803782
int methodHandleIndex = this.constantPool.literalIndexForMethodHandleFieldRef(
37813783
ClassFileConstants.MethodHandleRefKindGetField,
3782-
recordName, field.name, field.type.signature());
3784+
recordName, component.name, component.type.signature());
37833785

37843786
this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8);
37853787
this.contents[localContentsOffset++] = (byte) methodHandleIndex;

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,11 +701,30 @@ public void resolveJavadoc() {
701701
@Override
702702
public void resolve(ClassScope upperScope) {
703703

704-
if (this.isCompactConstructor() && !upperScope.referenceContext.isRecord()) {
705-
upperScope.problemReporter().compactConstructorsOnlyInRecords(this);
706-
return;
704+
if (this.binding != null && this.binding.isCanonicalConstructor()) {
705+
RecordComponentBinding[] rcbs = upperScope.referenceContext.binding.components();
706+
for (int i = 0; i < rcbs.length; ++i) {
707+
TypeBinding mpt = this.binding.parameters[i];
708+
TypeBinding rct = rcbs[i].type;
709+
if (TypeBinding.notEquals(mpt, rct))
710+
upperScope.problemReporter().recordErasureIncompatibilityInCanonicalConstructor(this.arguments[i].type);
711+
}
712+
713+
if (!this.binding.isAsVisible(this.binding.declaringClass))
714+
this.scope.problemReporter().recordCanonicalConstructorVisibilityReduced(this);
715+
if (this.typeParameters != null && this.typeParameters.length > 0)
716+
this.scope.problemReporter().recordCanonicalConstructorShouldNotBeGeneric(this);
717+
if (this.binding.thrownExceptions != null && this.binding.thrownExceptions.length > 0)
718+
this.scope.problemReporter().recordCanonicalConstructorHasThrowsClause(this);
719+
if (this.isCompactConstructor()) {
720+
if (!upperScope.referenceContext.isRecord())
721+
upperScope.problemReporter().compactConstructorsOnlyInRecords(this);
722+
} else {
723+
for (int i = 0; i < rcbs.length; i++)
724+
if (!CharOperation.equals(this.arguments[i].name, rcbs[i].name))
725+
this.scope.problemReporter().recordIllegalParameterNameInCanonicalConstructor(rcbs[i], this.arguments[i]);
726+
}
707727
}
708-
709728
super.resolve(upperScope);
710729
}
711730
/*

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordComponent.java

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,11 @@
1616
import java.util.List;
1717
import org.eclipse.jdt.internal.compiler.ASTVisitor;
1818
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationCollector;
19-
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
2019
import org.eclipse.jdt.internal.compiler.codegen.AnnotationContext;
2120
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
22-
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
23-
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
2421
import org.eclipse.jdt.internal.compiler.lookup.Binding;
2522
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26-
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
27-
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
2823
import org.eclipse.jdt.internal.compiler.lookup.RecordComponentBinding;
29-
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
3024
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
3125
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
3226

@@ -39,6 +33,7 @@ public RecordComponent(
3933
int sourceStart,
4034
int sourceEnd) {
4135

36+
4237
this.name = name;
4338
this.sourceStart = sourceStart;
4439
this.sourceEnd = sourceEnd;
@@ -54,28 +49,11 @@ public RecordComponent(char[] name, long posNom, TypeReference tr, int modifiers
5449
}
5550
}
5651

57-
@Override
58-
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
59-
//TODO: Add error checking if relevant.
60-
return flowInfo;
61-
}
62-
63-
public void checkModifiers() {
64-
65-
//only potential valid modifier is <<final>>
66-
if (((this.modifiers & ExtraCompilerModifiers.AccJustFlag) & ~ClassFileConstants.AccFinal) != 0)
67-
//AccModifierProblem -> other (non-visibility problem)
68-
//AccAlternateModifierProblem -> duplicate modifier
69-
//AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
70-
71-
this.modifiers = (this.modifiers & ~ExtraCompilerModifiers.AccAlternateModifierProblem) | ExtraCompilerModifiers.AccModifierProblem;
72-
}
73-
7452
@Override
7553
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
7654

7755
if ((this.bits & IsReachable) == 0) {
78-
return; // TODO: can this ever happen?
56+
return;
7957
}
8058
codeStream.recordPositionsFrom(codeStream.position, this.sourceStart);
8159
}
@@ -117,18 +95,6 @@ public void resolve(BlockScope scope) {
11795
TypeBinding resolvedAnnotationType = annotation.resolvedType;
11896
if (resolvedAnnotationType != null && (resolvedAnnotationType.getAnnotationTagBits() & TagBits.AnnotationForTypeUse) != 0) {
11997
this.bits |= ASTNode.HasTypeAnnotations;
120-
// also update the accessor's return type:
121-
if (this.binding != null && this.binding.declaringRecord != null) {
122-
for (MethodBinding methodBinding : this.binding.declaringRecord.methods()) {
123-
if (methodBinding instanceof SyntheticMethodBinding) {
124-
SyntheticMethodBinding smb = (SyntheticMethodBinding) methodBinding;
125-
if (smb.purpose == SyntheticMethodBinding.FieldReadAccess && smb.recordComponentBinding == this.binding) {
126-
smb.returnType = this.binding.type;
127-
break;
128-
}
129-
}
130-
}
131-
}
13298
break;
13399
}
134100
}

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,8 +1334,8 @@ public void fdiv() {
13341334
this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv;
13351335
}
13361336

1337-
public void fieldAccess(byte opcode, FieldBinding fieldBinding, TypeBinding declaringClass) {
1338-
if (declaringClass == null) declaringClass = fieldBinding.declaringClass;
1337+
public void fieldAccess(byte opcode, VariableBinding fieldBinding, TypeBinding declaringClass) {
1338+
if (declaringClass == null) declaringClass = fieldBinding.getDeclaringClass();
13391339
if ((declaringClass.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
13401340
Util.recordNestedType(this.classFile, declaringClass);
13411341
}
@@ -2862,7 +2862,7 @@ public void generateSyntheticBodyForEnumInitializationMethod(SyntheticMethodBind
28622862
return_();
28632863
}
28642864
public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessMethod) {
2865-
FieldBinding fieldBinding = accessMethod.targetReadField;
2865+
VariableBinding fieldBinding = accessMethod.targetReadField;
28662866
// target method declaring class may not be accessible (247953);
28672867
TypeBinding declaringClass = accessMethod.purpose == SyntheticMethodBinding.SuperFieldReadAccess
28682868
? accessMethod.declaringClass.superclass()
@@ -3025,7 +3025,7 @@ ReferenceBinding findDirectSuperTypeTowards(SyntheticMethodBinding accessMethod,
30253025
public void generateSyntheticBodyForSwitchTable(SyntheticMethodBinding methodBinding) {
30263026
ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
30273027
final BranchLabel nullLabel = new BranchLabel(this);
3028-
FieldBinding syntheticFieldBinding = methodBinding.targetReadField;
3028+
VariableBinding syntheticFieldBinding = methodBinding.targetReadField;
30293029
fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
30303030
dup();
30313031
ifnull(nullLabel);
@@ -3152,11 +3152,11 @@ public void generateSyntheticBodyForRecordCanonicalConstructor(SyntheticMethodBi
31523152
aload_0();
31533153
invoke(Opcodes.OPC_invokespecial, superCons, superClass);
31543154
int resolvedPosition;
3155-
FieldBinding[] fields = declaringClass.getImplicitComponentFields();
3155+
VariableBinding[] fields = declaringClass.components();
31563156
int len = fields != null ? fields.length : 0;
31573157
resolvedPosition = 1;
31583158
for (int i = 0; i < len; ++i) {
3159-
FieldBinding field = fields[i];
3159+
VariableBinding field = fields[i];
31603160
aload_0();
31613161
TypeBinding type = field.type;
31623162
load(type, resolvedPosition);

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,6 @@ void buildMethods() {
487487
if (hasAbstractMethods)
488488
problemReporter().abstractMethodInConcreteClass(sourceType);
489489
}
490-
if (sourceType.isRecord()) {
491-
methodBindings = sourceType.checkAndAddSyntheticRecordMethods(methodBindings, count);
492-
count = methodBindings.length;
493-
}
494490
if (count != methodBindings.length)
495491
System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
496492
sourceType.tagBits &= ~(TagBits.AreMethodsSorted|TagBits.AreMethodsComplete); // in case some static imports reached already into this type

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -332,15 +332,19 @@ public long getAnnotationTagBits() {
332332
return originalField.tagBits;
333333
}
334334

335-
public final boolean isDefault() {
336-
return !isPublic() && !isProtected() && !isPrivate();
335+
@Override
336+
public ReferenceBinding getDeclaringClass() {
337+
return this.declaringClass;
337338
}
338-
/* Answer true if the receiver is a deprecated field
339-
*/
340339

341340
/* Answer true if the receiver has default visibility
342341
*/
342+
public final boolean isDefault() {
343+
return !isPublic() && !isProtected() && !isPrivate();
344+
}
343345

346+
/* Answer true if the receiver is a deprecated field
347+
*/
344348
public final boolean isDeprecated() {
345349
return (this.modifiers & ClassFileConstants.AccDeprecated) != 0;
346350
}
@@ -370,12 +374,7 @@ public final boolean isProtected() {
370374
public final boolean isPublic() {
371375
return (this.modifiers & ClassFileConstants.AccPublic) != 0;
372376
}
373-
/* Answer true if the receiver is a static field
374-
*/
375377

376-
public final boolean isStatic() {
377-
return (this.modifiers & ClassFileConstants.AccStatic) != 0;
378-
}
379378
/* Answer true if the receiver is not defined in the source of the declaringClass
380379
*/
381380

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/RecordComponentBinding.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ public long getAnnotationTagBits() {
9898
return originalRecordComponentBinding.tagBits;
9999
}
100100

101+
@Override
102+
public ReferenceBinding getDeclaringClass() {
103+
return this.declaringRecord;
104+
}
105+
101106
public final boolean isDeprecated() {
102107
return (this.modifiers & ClassFileConstants.AccDeprecated) != 0;
103108
}

0 commit comments

Comments
 (0)