diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java index 9ceaf5eba69..22b28a02d5f 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java @@ -13,20 +13,14 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.dom; +import java.util.HashMap; import java.util.List; +import java.util.Map; import junit.framework.Test; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ImplicitTypeDeclaration; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.Javadoc; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.*; public class ASTConverter_23Test extends ConverterTestSetup { @@ -133,4 +127,406 @@ void main() { assertEquals("Not a Block", block.getNodeType(), ASTNode.BLOCK); assertEquals("Block startPosition is not correct", block.getStartPosition(), 21); } + + public void test003_a() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + sealed class A permits B, C {} + final class B extends A {} + non-sealed class C extends A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isSealed(a.getModifiers())); + + assertEquals("permitted types are not present in AST", a.permittedTypes().size(), 2); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isSealed(aBinding.getModifiers())); + } + + public void test003_b() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + sealed class A permits B, C {} + final class B extends A {} + non-sealed class C extends A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(2); + + assertTrue(Modifier.isNonSealed(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //public sealed + public void test003_c() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + public sealed class A permits B, C {} + final class B extends A {} + non-sealed class C extends A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isSealed(a.getModifiers())); + assertTrue(Modifier.isPublic(a.getModifiers())); + + assertEquals("permitted types are not present in AST", a.permittedTypes().size(), 2); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isSealed(aBinding.getModifiers())); + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + } + + //abstract final + public void test003_d() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + abstract final class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isAbstract(a.getModifiers())); + assertTrue(Modifier.isFinal(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isAbstract(aBinding.getModifiers())); + assertTrue(Modifier.isFinal(aBinding.getModifiers())); + } + + //abstract non-sealed + public void test003_e() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + abstract non-sealed class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isAbstract(a.getModifiers())); + assertTrue(Modifier.isNonSealed(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isAbstract(aBinding.getModifiers())); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //public final + public void test003_f() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + public final class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isPublic(a.getModifiers())); + assertTrue(Modifier.isFinal(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + assertTrue(Modifier.isFinal(aBinding.getModifiers())); + } + + //public non-sealed + public void test003_g() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + public non-sealed class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isPublic(a.getModifiers())); + assertTrue(Modifier.isNonSealed(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //protected non-sealed + public void test003_h() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + protected non-sealed class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isProtected(a.getModifiers())); + assertTrue(Modifier.isNonSealed(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isProtected(aBinding.getModifiers())); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //private non-sealed + public void test003_i() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + private non-sealed class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isPrivate(a.getModifiers())); + assertTrue(Modifier.isNonSealed(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isPrivate(aBinding.getModifiers())); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //protected abstract + public void test003_j() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source = """ + protected abstract class A {} + """; + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isProtected(a.getModifiers())); + assertTrue(Modifier.isAbstract(a.getModifiers())); + + ITypeBinding aBinding = a.resolveBinding(); + + assertTrue(Modifier.isProtected(aBinding.getModifiers())); + assertTrue(Modifier.isAbstract(aBinding.getModifiers())); + } + + //public sealed interface + public void test003_k() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + public sealed interface A permits X {} + public final class X implements A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isSealed(a.getModifiers())); + assertTrue(Modifier.isPublic(a.getModifiers())); + assertEquals("permitted types are not present in AST", a.permittedTypes().size(), 1); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isSealed(aBinding.getModifiers())); + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + assertFalse(Modifier.isNonSealed(aBinding.getModifiers())); + } + + //public non-sealed interface + public void test003_l() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + public non-sealed interface A permits X {} + public final class X implements A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isNonSealed(a.getModifiers())); + assertTrue(Modifier.isPublic(a.getModifiers())); + assertEquals("permitted types are not present in AST", a.permittedTypes().size(), 1); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isNonSealed(aBinding.getModifiers())); + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + assertFalse(Modifier.isSealed(aBinding.getModifiers())); + } + + //public strictfp interface + public void test003_m() throws CoreException { + ASTParser astParser = ASTParser.newParser(getAST23()); + Map options = new HashMap<>(); + options.put(JavaCore.COMPILER_COMPLIANCE, "23"); + options.put(JavaCore.COMPILER_SOURCE, "23"); + + astParser.setCompilerOptions(options); + astParser.setEnvironment(new String[] {}, new String[] {}, new String[] {}, true); + astParser.setUnitName("Example.java"); + astParser.setResolveBindings(true); + astParser.setBindingsRecovery(true); + + String source =""" + public strictfp interface A permits X {} + public final class X implements A {} + """; + + astParser.setSource(source.toCharArray()); + + CompilationUnit compilationUnit = (CompilationUnit) astParser.createAST(null); + TypeDeclaration a = (TypeDeclaration) compilationUnit.types().get(0); + + assertTrue(Modifier.isStrictfp(a.getModifiers())); + assertTrue(Modifier.isPublic(a.getModifiers())); + assertEquals("permitted types are not present in AST", a.permittedTypes().size(), 1); + + ITypeBinding aBinding = a.resolveBinding(); + assertTrue(Modifier.isStrictfp(aBinding.getModifiers())); + assertTrue(Modifier.isPublic(aBinding.getModifiers())); + } } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java index ff53e40ddde..14e23d0a271 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java @@ -45,7 +45,7 @@ class TypeBinding implements ITypeBinding { protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0]; private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | - Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP; + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP | Modifier.SEALED | Modifier.NON_SEALED; org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding; private TypeBinding prototype = null; @@ -589,6 +589,13 @@ public int getModifiers() { if (isClass()) { ReferenceBinding referenceBinding = (ReferenceBinding) this.binding; final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS; + + if (referenceBinding.isSealed()) { + return accessFlags | Modifier.SEALED; + } + if (referenceBinding.isNonSealed()) { + return accessFlags | Modifier.NON_SEALED; + } if (referenceBinding.isAnonymousType()) { return accessFlags & ~Modifier.FINAL; } @@ -600,9 +607,17 @@ public int getModifiers() { return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation); } else if (isInterface()) { ReferenceBinding referenceBinding = (ReferenceBinding) this.binding; - final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS; + int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS; // clear the AccAbstract and the AccInterface bits - return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface); + accessFlags = accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface); + + if (referenceBinding.isSealed()) { + return accessFlags | Modifier.SEALED; + } + if (referenceBinding.isNonSealed()) { + return accessFlags | Modifier.NON_SEALED; + } + return accessFlags; } else if (isEnum()) { ReferenceBinding referenceBinding = (ReferenceBinding) this.binding; final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;