Skip to content

Commit

Permalink
[Reconciler][Sealed types] Extra errors in editor that go away on fil…
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran authored Oct 21, 2024
1 parent 1511df2 commit 3f5517e
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,6 @@ && isTypeUseDeprecated(type, scope)) {
public boolean isTypeReference() {
return true;
}
public boolean isSynthetic() {
return false;
}
public boolean isWildcard() {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,7 @@ else if (subType.module() != sealedTypeModule)
void connectPermittedTypes() {
SourceTypeBinding sourceType = this.referenceContext.binding;

if (this.referenceContext.permittedTypes != null && (this.referenceContext.permittedTypes.length == 0 || !this.referenceContext.permittedTypes[0].isSynthetic())) {
if (this.referenceContext.permittedTypes != null) {
sourceType.setPermittedTypes(Binding.NO_PERMITTED_TYPES);
try {
sourceType.tagBits |= TagBits.SealingTypeHierarchy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3062,6 +3062,22 @@ public RecordComponentBinding[] setComponents(RecordComponentBinding[] comps) {
return this.permittedTypes = permittedTypes;
}

private void setImplicitPermittedType(SourceTypeBinding permittedType) {
ReferenceBinding[] typesPermitted = this.permittedTypes();
int sz = typesPermitted == null ? 0 : typesPermitted.length;
if (this.scope.referenceCompilationUnit() == permittedType.scope.referenceCompilationUnit()) {
if (sz == 0) {
typesPermitted = new ReferenceBinding[] { permittedType };
} else {
System.arraycopy(typesPermitted, 0, typesPermitted = new ReferenceBinding[sz + 1], 0, sz);
typesPermitted[sz] = permittedType;
}
this.setPermittedTypes(typesPermitted);
} else if (sz == 0) {
this.setPermittedTypes(Binding.NO_PERMITTED_TYPES);
}
}

// Propagate writes to all annotated variants so the clones evolve along.
public ReferenceBinding setSuperClass(ReferenceBinding superClass) {

Expand All @@ -3075,31 +3091,14 @@ public ReferenceBinding setSuperClass(ReferenceBinding superClass) {
annotatedType.superclass = superClass;
}
}
if (superClass != null && superClass.actualType() instanceof SourceTypeBinding sourceSuperType && sourceSuperType.isSealed()
&& (sourceSuperType.scope.referenceContext.permittedTypes == null || (sourceSuperType.scope.referenceContext.permittedTypes.length > 0 && sourceSuperType.scope.referenceContext.permittedTypes[0].isSynthetic()))) {
if (superClass != null && superClass.actualType() instanceof SourceTypeBinding sourceSuperType && sourceSuperType.isSealed() && sourceSuperType.scope.referenceContext.permittedTypes == null) {
sourceSuperType.setImplicitPermittedType(this);
if (this.isAnonymousType() && superClass.isEnum())
this.modifiers |= ClassFileConstants.AccFinal;
}
return this.superclass = superClass;
}

private void setImplicitPermittedType(SourceTypeBinding permittedType) {
ReferenceBinding[] typesPermitted = this.permittedTypes();
int sz = typesPermitted == null ? 0 : typesPermitted.length;
if (this.scope.referenceCompilationUnit() == permittedType.scope.referenceCompilationUnit()) {
if (sz == 0) {
typesPermitted = new ReferenceBinding[] { permittedType };
} else {
System.arraycopy(typesPermitted, 0, typesPermitted = new ReferenceBinding[sz + 1], 0, sz);
typesPermitted[sz] = permittedType;
}
this.setPermittedTypes(typesPermitted);
} else if (sz == 0) {
this.setPermittedTypes(Binding.NO_PERMITTED_TYPES);
}
}

// Propagate writes to all annotated variants so the clones evolve along.
public ReferenceBinding [] setSuperInterfaces(ReferenceBinding [] superInterfaces) {

Expand All @@ -3115,8 +3114,7 @@ private void setImplicitPermittedType(SourceTypeBinding permittedType) {
}
for (int i = 0, length = superInterfaces == null ? 0 : superInterfaces.length; i < length; i++) {
ReferenceBinding superInterface = superInterfaces[i];
if (superInterface.actualType() instanceof SourceTypeBinding sourceSuperType && sourceSuperType.isSealed()
&& (sourceSuperType.scope.referenceContext.permittedTypes == null || (sourceSuperType.scope.referenceContext.permittedTypes.length > 0 && sourceSuperType.scope.referenceContext.permittedTypes[0].isSynthetic()))) {
if (superInterface.actualType() instanceof SourceTypeBinding sourceSuperType && sourceSuperType.isSealed() && sourceSuperType.scope.referenceContext.permittedTypes == null) {
sourceSuperType.setImplicitPermittedType(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public void test004() throws Exception {
createFile( "/SealedTypes/src/X.java", fileContent);
ICompilationUnit unit = getCompilationUnit("/SealedTypes/src/X.java");
IType[] types = unit.getTypes();
assertEquals("Incorret no of types", 3, types.length);
assertEquals("Incorrect no of types", 3, types.length);
for (IType iType : types) {
if (iType.getElementName().equals("I")) {
assertTrue("modifier should contain sealed", iType.isSealed());
Expand All @@ -160,6 +160,137 @@ public void test004() throws Exception {
deleteProject("SealedTypes");
}
}
// Test implicitly permitted sub types in Source Type
public void test004_2() throws Exception {
String[] permitted = new String[] {"Maybe.Maybe1", "Maybe.Maybe2"};
try {
IJavaProject project = createJavaProject("SealedTypes");
project.open(null);
String fileContent =
"""
interface SuperInt {}
abstract sealed class Maybe {
final class Maybe1 extends Maybe {}
final class Maybe2 extends Maybe implements SuperInt {}
}
class Test {
void testMaybe(Maybe maybe) {
if (maybe == null) return;
}
}
""";

createFile( "/SealedTypes/src/X.java", fileContent);
ICompilationUnit unit = getCompilationUnit("/SealedTypes/src/X.java");
IType[] types = unit.getTypes();
assertEquals("Incorrect no of types", 3, types.length);
for (IType iType : types) {
if (iType.getElementName().equals("Maybe")) {
assertTrue("modifier should contain sealed", iType.isSealed());
String[] permittedSubtypeNames = iType.getPermittedSubtypeNames();
assertEquals("incorrect permitted sub types", permitted.length, permittedSubtypeNames.length);
for (int i = 0; i < permitted.length; i++) {
assertEquals("incorrect permitted sub type", permitted[i], permittedSubtypeNames[i]);
}
}
}
}
finally {
deleteProject("SealedTypes");
}
}

// Test implicitly permitted sub types in Source Type
public void test004_3() throws Exception {
String[] permitted = new String[] {"Maybe.Maybe1", "Maybe.Maybe2"};
try {
IJavaProject project = createJavaProject("SealedTypes");
project.open(null);
String fileContent =
"""
interface SuperInt {}
sealed interface Maybe {
final class Maybe1 implements Maybe {}
non-sealed interface Maybe2 extends Maybe {}
}
class Test {
void testMaybe(Maybe maybe) {
if (maybe == null) return;
}
}
""";

createFile( "/SealedTypes/src/X.java", fileContent);
ICompilationUnit unit = getCompilationUnit("/SealedTypes/src/X.java");
IType[] types = unit.getTypes();
assertEquals("Incorrect no of types", 3, types.length);
for (IType iType : types) {
if (iType.getElementName().equals("Maybe")) {
assertTrue("modifier should contain sealed", iType.isSealed());
String[] permittedSubtypeNames = iType.getPermittedSubtypeNames();
assertEquals("incorrect permitted sub types", permitted.length, permittedSubtypeNames.length);
for (int i = 0; i < permitted.length; i++) {
assertEquals("incorrect permitted sub type", permitted[i], permittedSubtypeNames[i]);
}
}
}
}
finally {
deleteProject("SealedTypes");
}
}

// Test implicitly permitted sub types in Source Type
public void test004_4() throws Exception {
String[] permitted = new String[] {"Maybe.Maybe1", "Maybe.Maybe2"};
try {
IJavaProject project = createJavaProject("SealedTypes");
project.open(null);
String fileContent =
"""
interface SuperInt {}
abstract sealed class Maybe<N extends Number> {
final class Maybe1 extends Maybe<Long> {}
final class Maybe2 extends Maybe<Long> implements SuperInt {}
}
class Test {
void testMaybe(Maybe<?> maybe) {
if (maybe == null) return;
zork();
}
}
""";

createFile( "/SealedTypes/src/X.java", fileContent);
ICompilationUnit unit = getCompilationUnit("/SealedTypes/src/X.java");
IType[] types = unit.getTypes();
assertEquals("Incorrect no of types", 3, types.length);
for (IType iType : types) {
if (iType.getElementName().equals("Maybe")) {
assertTrue("modifier should contain sealed", iType.isSealed());
String[] permittedSubtypeNames = iType.getPermittedSubtypeNames();
assertEquals("incorrect permitted sub types", permitted.length, permittedSubtypeNames.length);
for (int i = 0; i < permitted.length; i++) {
assertEquals("incorrect permitted sub type", permitted[i], permittedSubtypeNames[i]);
}
}
}
}
finally {
deleteProject("SealedTypes");
}
}


// Test explicitly permitted sub types in binary
public void test005() throws Exception {
String[] permitted = new String[] {"p.X", "p.Y"};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ protected void notifySourceElementRequestor(ImportReference importReference, boo
}

@Override
protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {
protected void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit, TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {
if (typeDeclaration instanceof CompletionOnAnnotationOfType) return;
super.notifySourceElementRequestor(typeDeclaration, notifyTypePresence, declaringType, currentPackage);
super.notifySourceElementRequestor(parsedUnit, typeDeclaration, notifyTypePresence, declaringType, currentPackage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.eclipse.jdt.internal.compiler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor.ParameterInfo;
Expand Down Expand Up @@ -52,12 +53,12 @@ public TypeDeclaration peekDeclaringType() {
}
@Override
public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
notifySourceElementRequestor(typeDeclaration, true, peekDeclaringType(), this.currentPackage);
notifySourceElementRequestor(null, typeDeclaration, true, peekDeclaringType(), this.currentPackage);
return false; // don't visit members as this was done during notifySourceElementRequestor(...)
}
@Override
public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
notifySourceElementRequestor(typeDeclaration, true, peekDeclaringType(), this.currentPackage);
notifySourceElementRequestor(null, typeDeclaration, true, peekDeclaringType(), this.currentPackage);
return false; // don't visit members as this was done during notifySourceElementRequestor(...)
}
}
Expand Down Expand Up @@ -136,8 +137,44 @@ protected char[] getSuperclassName(TypeDeclaration typeDeclaration) {
TypeReference superclass = typeDeclaration.superclass;
return superclass != null ? CharOperation.concatWith(superclass.getParameterizedTypeName(), '.') : null;
}
protected char[][] getPermittedSubTypes(TypeDeclaration typeDeclaration) {
return extractTypeReferences(typeDeclaration.permittedTypes);
private void gatherPermittedTypesOf(TypeDeclaration potentialSubtype, TypeDeclaration sealedType, List<char []> list, char [] prefix) {
if (potentialSubtype != sealedType) {
char[][] qName = potentialSubtype.superclass == null ? null : potentialSubtype.superclass.getTypeName();
if (qName != null && CharOperation.equals(qName[qName.length - 1], sealedType.name)) {
char [] subTypeName = CharOperation.concat(prefix, potentialSubtype.name, '.');
list.add(subTypeName);
}
if (potentialSubtype.superInterfaces != null) {
for (TypeReference ref : potentialSubtype.superInterfaces) {
qName = ref.getTypeName();
if (CharOperation.equals(qName[qName.length - 1], sealedType.name)) {
char [] subTypeName = CharOperation.concat(prefix, potentialSubtype.name, '.');
list.add(subTypeName);
break;
}
}
}
}
if (potentialSubtype.memberTypes != null) {
for (int i = 0, size = potentialSubtype.memberTypes.length; i < size; i++) {
char [] prefixNow = CharOperation.concat(prefix, potentialSubtype.name, '.');
gatherPermittedTypesOf(potentialSubtype.memberTypes[i], sealedType, list, prefixNow);
}
}
}
protected char[][] getPermittedSubTypes(CompilationUnitDeclaration parsedUnit, TypeDeclaration sealedType) {

if (sealedType.permittedTypes != null)
return extractTypeReferences(sealedType.permittedTypes);

// compute implicit permitted types on the fly.
List<char []> list = new ArrayList();
if (parsedUnit != null) { // == null for local types.
for (TypeDeclaration type : parsedUnit.types) {
gatherPermittedTypesOf(type, sealedType, list, CharOperation.NO_CHAR);
}
}
return list.toArray(new char[list.size()][]);
}
protected char[][] getThrownExceptions(AbstractMethodDeclaration methodDeclaration) {
return extractTypeReferences(methodDeclaration.thrownExceptions);
Expand Down Expand Up @@ -455,7 +492,7 @@ public void notifySourceElementRequestor(
notifySourceElementRequestor(importRef, false);
}
} else if (node instanceof TypeDeclaration && !new String(parsedUnit.getFileName()).endsWith(TypeConstants.MODULE_INFO_FILE_NAME_STRING)) {
notifySourceElementRequestor((TypeDeclaration)node, true, null, currentPackage);
notifySourceElementRequestor(parsedUnit, (TypeDeclaration)node, true, null, currentPackage);
} else if (node instanceof ModuleDeclaration) {
notifySourceElementRequestor(parsedUnit.moduleDeclaration);
}
Expand Down Expand Up @@ -640,7 +677,7 @@ protected void notifySourceElementRequestor(ModuleDeclaration moduleDeclaration)
// }
//
//}
protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {
protected void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit, TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {

if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return;

Expand Down Expand Up @@ -704,7 +741,7 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
typeInfo.extraFlags = ExtraFlags.getExtraFlags(typeDeclaration);
typeInfo.node = typeDeclaration;
if ((currentModifiers & ExtraCompilerModifiers.AccSealed) != 0) {
typeInfo.permittedSubtypes = getPermittedSubTypes(typeDeclaration);
typeInfo.permittedSubtypes = getPermittedSubTypes(parsedUnit, typeDeclaration);
}
switch (kind) {
case TypeDeclaration.CLASS_DECL :
Expand Down Expand Up @@ -776,7 +813,7 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
break;
case 2 :
memberTypeIndex++;
notifySourceElementRequestor(nextMemberDeclaration, true, null, currentPackage);
notifySourceElementRequestor(parsedUnit, nextMemberDeclaration, true, null, currentPackage);
break;
}
}
Expand Down
Loading

0 comments on commit 3f5517e

Please sign in to comment.