diff options
Diffstat (limited to 'org.eclipse.jdt.core/model')
37 files changed, 787 insertions, 164 deletions
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java index 4950c1bfd1..8fe20ea15b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java @@ -193,6 +193,26 @@ public final class Flags { * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature. */ public static final int AccRecord = ExtraCompilerModifiers.AccRecord; + /** + * Sealed property flag. + * <p> + * Note that this flag's value is internal and is not defined in the + * Virtual Machine specification. + * </p> + * @since 3.23 + * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature. + */ + public static final int AccSealed = ExtraCompilerModifiers.AccSealed; + /** + * Non-sealed property flag. + * <p> + * Note that this flag's value is internal and is not defined in the + * Virtual Machine specification. + * </p> + * @since 3.23 + * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature. + */ + public static final int AccNonSealed = ExtraCompilerModifiers.AccNonSealed; /** * Not instantiable. @@ -402,6 +422,30 @@ public final class Flags { public static boolean isRecord(int flags) { return (flags & AccRecord) != 0; } + /** + * Returns whether the given integer has the <code>AccSealed</code> + * bit set. + * + * @param flags the flags + * @return <code>true</code> if the <code>AccSealed</code> flag is included + * @see #AccSealed + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ + public static boolean isSealed(int flags) { + return (flags & AccSealed) != 0; + } + /** + * Returns whether the given integer has the <code>AccNonSealed</code> + * bit set. + * + * @param flags the flags + * @return <code>true</code> if the <code>AccNonSealed</code> flag is included + * @see #AccNonSealed + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ + public static boolean isNonSealed(int flags) { + return (flags & AccNonSealed) != 0; + } /** * Returns whether the given integer has the <code>AccAnnotation</code> diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java index 0d16aaf890..3550361b88 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java @@ -759,6 +759,22 @@ public interface IType extends IMember, IAnnotatable { String[] getSuperInterfaceNames() throws JavaModelException; /** + * Returns the names of types that this sealed type permits to be its sub types. + * For a non sealed type, an empty array is returned. + * If type declares an explicit permits clause, then the permitted sub-types + * are returned in the declared order. If a sealed type does not explicitly + * declare permitted sub types, then the implicit permitted types, that is, + * the types in the same compilation unit that are sub types of this sealed type + * are returned in the order they appear within the compilation unit. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return names of types that this type permits to be its sub types + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ + String[] getPermittedSubtypeNames() throws JavaModelException; + + /** * Returns the formal type parameter signatures for this type. * Returns an empty array if this type has no formal type parameters. * <p> @@ -915,6 +931,16 @@ public interface IType extends IMember, IAnnotatable { */ boolean isRecord() throws JavaModelException; /** + * Returns whether this type is a sealed type. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if this type this type is a sealed type, false otherwise + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ + boolean isSealed() throws JavaModelException; + + /** * Returns the record components declared by this record class, or an empty * array if this is not a record. * @@ -924,7 +950,7 @@ public interface IType extends IMember, IAnnotatable { * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. */ default IField[] getRecordComponents() throws JavaModelException { - return null; + return new IField[0]; } /** * Returns the record component with the specified name diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java index b2a9d2b068..733c9b90a5 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java @@ -3120,12 +3120,18 @@ public final class JavaCore extends Plugin { public static final String VERSION_14 = "14"; //$NON-NLS-1$ /** * Configurable option value: {@value}. + * @since 3.23 + * @category OptionValue + */ + public static final String VERSION_15 = "15"; //$NON-NLS-1$ + /** + * Configurable option value: {@value}. * @since 3.4 * @category OptionValue */ public static final String VERSION_CLDC_1_1 = "cldc1.1"; //$NON-NLS-1$ private static List<String> allVersions = Collections.unmodifiableList(Arrays.asList(VERSION_CLDC_1_1, VERSION_1_1, VERSION_1_2, VERSION_1_3, VERSION_1_4, VERSION_1_5, - VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14)); + VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15)); /** * Returns all {@link JavaCore}{@code #VERSION_*} levels in the order of their diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java index c3f2ddabab..297f1f5364 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -207,6 +207,11 @@ public interface IAttributeNamesConstants { * @since 3.22 */ char[] RECORD = "Record".toCharArray(); //$NON-NLS-1$ + /** + * "PermittedSubclasses" attribute (JVMS 15). + * @since 3.23 + */ + char[] PERMITTED_SUBCLASSES = "PermittedSubclasses".toCharArray(); //$NON-NLS-1$ } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java index f72dafb9ea..22b21f38b6 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -137,6 +137,16 @@ public interface IClassFileReader { } /** + * Answer back the permitted subclasses attribute of this .class file, null if none. + * + * @return the permitted subclasses attribute of this .class file, null if none + * @since 3.23 + */ + default IPermittedSubclassesAttribute getPermittedSubclassesAttribute() { + return null; + } + + /** * Answer back the array of method infos of this .class file, * an empty array if none. * diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java new file mode 100644 index 0000000000..467bb00f69 --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2000, 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of permitted subclasses attribute as described in the JVM + * specifications. + * + * @since 3.23 + */ +public interface IPermittedSubclassesAttribute extends IClassFileAttribute { + + /** + * Answer back the number of permitted subclasses as specified in + * the JVM specifications. + * + * @return the number of permitted subclasses as specified in + * the JVM specifications + */ + int getNumberOfPermittedSubclasses(); + + /** + * Answer back the array of permitted subclass attribute entries as specified in + * the JVM specifications, or an empty array if none. + * + * @return the array of permitted subclass attribute entries as specified in + * the JVM specifications, or an empty array if none + */ + IPermittedSubclassesAttributeEntry[] getPermittedSubclassAttributesEntries(); +} diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java new file mode 100644 index 0000000000..3c3dc95677 --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2000, 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.util; + +/** + * Description of permitted subclasses attribute as described in the JVM + * specifications. + * + * @since 3.23 + */ +public interface IPermittedSubclassesAttributeEntry { + + /** + * Answer back the permitted subclass name as specified + * in the JVM specifications. + * + * @return the permitted subclass name as specified + * in the JVM specifications + */ + char[] getPermittedSubclassName(); + + /** + * Answer back the permitted subclass name index. + * + * @return the permitted class name index + */ + int gePermittedSubclassIndex(); +} diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java index 0ba46a2b3d..72d0758e13 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java @@ -17,12 +17,11 @@ import java.util.HashMap; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; -import org.eclipse.jdt.internal.compiler.ast.RecordComponent; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; /* @@ -89,6 +88,7 @@ public interface ISourceElementRequestor { public int nameSourceEnd; public char[] superclass; public char[][] superinterfaces; + public char[][] permittedSubtypes; public TypeParameterInfo[] typeParameters; public char[][] categories; public boolean secondary; @@ -111,6 +111,7 @@ public interface ISourceElementRequestor { public static class MethodInfo { public boolean typeAnnotated; + public boolean isCanonicalConstr; public boolean isConstructor; public boolean isAnnotation; public int declarationStart; @@ -142,6 +143,7 @@ public interface ISourceElementRequestor { public char[] name; } public static class FieldInfo { + public boolean isRecordComponent; public boolean typeAnnotated; public int declarationStart; public int modifiers; @@ -151,21 +153,9 @@ public interface ISourceElementRequestor { public int nameSourceEnd; public char[][] categories; public Annotation[] annotations; - public FieldDeclaration node; + public AbstractVariableDeclaration node; } - public static class RecordComponentInfo { - public boolean typeAnnotated; - public int declarationStart; - public int modifiers; - public char[] type; - public char[] name; - public int nameSourceStart; - public int nameSourceEnd; - public char[][] categories; - public Annotation[] annotations; - public RecordComponent node; - } void acceptAnnotationTypeReference(char[][] annotation, int sourceStart, int sourceEnd); void acceptAnnotationTypeReference(char[] annotation, int sourcePosition); @@ -229,8 +219,6 @@ public interface ISourceElementRequestor { void enterMethod(MethodInfo methodInfo); - void enterRecordComponent(RecordComponentInfo recordComponentInfo); - void enterType(TypeInfo typeInfo); void exitCompilationUnit(int declarationEnd); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java index b4a6370182..e530a64726 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java @@ -44,7 +44,6 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; import org.eclipse.jdt.internal.compiler.ast.OpensStatement; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; -import org.eclipse.jdt.internal.compiler.ast.RecordComponent; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; @@ -166,18 +165,23 @@ 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); +} protected char[][] getThrownExceptions(AbstractMethodDeclaration methodDeclaration) { - char[][] thrownExceptionTypes = null; - TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions; + return extractTypeReferences(methodDeclaration.thrownExceptions); +} +private char[][] extractTypeReferences(TypeReference[] thrownExceptions) { + char[][] names = null; if (thrownExceptions != null) { int thrownExceptionLength = thrownExceptions.length; - thrownExceptionTypes = new char[thrownExceptionLength][]; + names = new char[thrownExceptionLength][]; for (int i = 0; i < thrownExceptionLength; i++) { - thrownExceptionTypes[i] = + names[i] = CharOperation.concatWith(thrownExceptions[i].getParameterizedTypeName(), '.'); } } - return thrownExceptionTypes; + return names; } protected char[][] getTypeParameterBounds(TypeParameter typeParameter) { TypeReference firstBound = typeParameter.type; @@ -307,6 +311,7 @@ protected void notifySourceElementRequestor(AbstractMethodDeclaration methodDecl currentModifiers |= ClassFileConstants.AccDeprecated; methodInfo.isConstructor = true; + methodInfo.isCanonicalConstr = methodDeclaration.isCanonicalConstructor(); methodInfo.declarationStart = methodDeclaration.declarationSourceStart; methodInfo.modifiers = currentModifiers; methodInfo.name = methodDeclaration.selector; @@ -536,8 +541,10 @@ protected void notifySourceElementRequestor(FieldDeclaration fieldDeclaration, T fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart; fieldInfo.name = fieldDeclaration.name; fieldInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; - if (fieldDeclaration.isARecordComponent) + if (fieldDeclaration.isARecordComponent) { fieldInfo.modifiers |= ExtraCompilerModifiers.AccRecord; + fieldInfo.isRecordComponent = true; + } fieldInfo.type = typeName; fieldInfo.nameSourceStart = fieldDeclaration.sourceStart; fieldInfo.nameSourceEnd = fieldDeclaration.sourceEnd; @@ -621,40 +628,40 @@ protected void notifySourceElementRequestor(ModuleDeclaration moduleDeclaration) this.requestor.exitModule(moduleDeclaration.declarationSourceEnd); } } -protected void notifySourceElementRequestor(RecordComponent recordComponent, TypeDeclaration declaringType) { - assert declaringType.isRecord(); - - // range check - boolean isInRange = - this.initialPosition <= recordComponent.declarationSourceStart - && this.eofPosition >= recordComponent.declarationSourceEnd; - int recordComponentEndPosition = this.sourceEnds.get(recordComponent); - if (recordComponentEndPosition == -1) { - // use the declaration source end by default - recordComponentEndPosition = recordComponent.declarationSourceEnd; - } - if (isInRange) { - char[] typeName = CharOperation.concatWith(recordComponent.type.getParameterizedTypeName(), '.'); - ISourceElementRequestor.RecordComponentInfo recordComponentInfo = new ISourceElementRequestor.RecordComponentInfo(); - recordComponentInfo.typeAnnotated = ((recordComponent.bits & ASTNode.HasTypeAnnotations) != 0); - recordComponentInfo.declarationStart = recordComponent.declarationSourceStart; - recordComponentInfo.name = recordComponent.name; - recordComponentInfo.type = typeName; - recordComponentInfo.nameSourceStart = recordComponent.sourceStart; - recordComponentInfo.nameSourceEnd = recordComponent.sourceEnd; - recordComponentInfo.categories = this.nodesToCategories.get(recordComponent); - recordComponentInfo.annotations = recordComponent.annotations; - recordComponentInfo.node = recordComponent; - this.requestor.enterRecordComponent(recordComponentInfo); - } - this.visitIfNeeded(recordComponent, declaringType); - if (isInRange){ - this.requestor.exitRecordComponent( - recordComponentEndPosition, - recordComponent.declarationSourceEnd); - } - -} +//protected void notifySourceElementRequestor(RecordComponent recordComponent, TypeDeclaration declaringType) { +// assert declaringType.isRecord(); +// +// // range check +// boolean isInRange = +// this.initialPosition <= recordComponent.declarationSourceStart +// && this.eofPosition >= recordComponent.declarationSourceEnd; +// int recordComponentEndPosition = this.sourceEnds.get(recordComponent); +// if (recordComponentEndPosition == -1) { +// // use the declaration source end by default +// recordComponentEndPosition = recordComponent.declarationSourceEnd; +// } +// if (isInRange) { +// char[] typeName = CharOperation.concatWith(recordComponent.type.getParameterizedTypeName(), '.'); +// ISourceElementRequestor.RecordComponentInfo recordComponentInfo = new ISourceElementRequestor.RecordComponentInfo(); +// recordComponentInfo.typeAnnotated = ((recordComponent.bits & ASTNode.HasTypeAnnotations) != 0); +// recordComponentInfo.declarationStart = recordComponent.declarationSourceStart; +// recordComponentInfo.name = recordComponent.name; +// recordComponentInfo.type = typeName; +// recordComponentInfo.nameSourceStart = recordComponent.sourceStart; +// recordComponentInfo.nameSourceEnd = recordComponent.sourceEnd; +// recordComponentInfo.categories = this.nodesToCategories.get(recordComponent); +// recordComponentInfo.annotations = recordComponent.annotations; +// recordComponentInfo.node = recordComponent; +// this.requestor.enterRecordComponent(recordComponentInfo); +// } +// this.visitIfNeeded(recordComponent, declaringType); +// if (isInRange){ +// this.requestor.exitRecordComponent( +// recordComponentEndPosition, +// recordComponent.declarationSourceEnd); +// } +// +//} protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) { if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return; @@ -667,15 +674,12 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo FieldDeclaration[] fields = typeDeclaration.fields; AbstractMethodDeclaration[] methods = typeDeclaration.methods; TypeDeclaration[] memberTypes = typeDeclaration.memberTypes; - RecordComponent[] recordComponents = typeDeclaration.recordComponents; int fieldCounter = fields == null ? 0 : fields.length; int methodCounter = methods == null ? 0 : methods.length; int memberTypeCounter = memberTypes == null ? 0 : memberTypes.length; - int recordComponentCounter = recordComponents == null ? 0 : recordComponents.length; int fieldIndex = 0; int methodIndex = 0; int memberTypeIndex = 0; - int recordComponentIndex = 0; if (notifyTypePresence){ char[][] interfaceNames = getInterfaceNames(typeDeclaration); @@ -704,7 +708,10 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo } else { typeInfo.declarationStart = typeDeclaration.allocation.sourceStart; } - typeInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; + typeInfo.modifiers = deprecated + ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated + : currentModifiers & ExtraCompilerModifiers.AccJustFlag; + typeInfo.modifiers |= currentModifiers & (ExtraCompilerModifiers.AccSealed | ExtraCompilerModifiers.AccNonSealed); typeInfo.name = typeDeclaration.name; typeInfo.nameSourceStart = isEnumInit ? typeDeclaration.allocation.enumConstant.sourceStart : typeDeclaration.sourceStart; typeInfo.nameSourceEnd = sourceEnd(typeDeclaration); @@ -717,6 +724,9 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo typeInfo.annotations = typeDeclaration.annotations; typeInfo.extraFlags = ExtraFlags.getExtraFlags(typeDeclaration); typeInfo.node = typeDeclaration; + if ((currentModifiers & ExtraCompilerModifiers.AccSealed) != 0) { + typeInfo.permittedSubtypes = getPermittedSubTypes(typeDeclaration); + } switch (kind) { case TypeDeclaration.CLASS_DECL : if (superclassName != null) @@ -748,12 +758,10 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo } while ((fieldIndex < fieldCounter) || (memberTypeIndex < memberTypeCounter) - || (methodIndex < methodCounter) - || (recordComponentIndex < recordComponentCounter)) { + || (methodIndex < methodCounter)) { FieldDeclaration nextFieldDeclaration = null; AbstractMethodDeclaration nextMethodDeclaration = null; TypeDeclaration nextMemberDeclaration = null; - RecordComponent nextRecordComponent = null; int position = Integer.MAX_VALUE; int nextDeclarationType = -1; @@ -778,18 +786,9 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo nextDeclarationType = 2; // MEMBER } } - if (recordComponentIndex < recordComponentCounter) { - nextRecordComponent = recordComponents[recordComponentIndex]; - if (nextRecordComponent.declarationSourceStart < position) { - position = nextRecordComponent.declarationSourceStart; - nextDeclarationType = 3; // RECORD_COMPONENT - } - } switch (nextDeclarationType) { case 0 : fieldIndex++; -// if (typeDeclaration.isRecord() && nextFieldDeclaration.isARecordComponent) -// break; notifySourceElementRequestor(nextFieldDeclaration, typeDeclaration); break; case 1 : @@ -800,10 +799,6 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo memberTypeIndex++; notifySourceElementRequestor(nextMemberDeclaration, true, null, currentPackage); break; - case 3 : - recordComponentIndex++; - notifySourceElementRequestor(nextRecordComponent, typeDeclaration); - break; } } if (notifyTypePresence){ @@ -957,19 +952,6 @@ private void visitIfNeeded(FieldDeclaration field, TypeDeclaration declaringType } } } -private void visitIfNeeded(RecordComponent component, TypeDeclaration declaringType) { - if (this.localDeclarationVisitor != null - && (component.bits & ASTNode.HasLocalType) != 0) { - if (component.initialization != null) { - try { - this.localDeclarationVisitor.pushDeclaringType(declaringType); - component.initialization.traverse(this.localDeclarationVisitor, (MethodScope) null); - } finally { - this.localDeclarationVisitor.popDeclaringType(); - } - } - } -} private void visitIfNeeded(Initializer initializer) { if (this.localDeclarationVisitor != null diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java index 17ec28efde..54449400ef 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,7 +13,9 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; @@ -114,6 +116,11 @@ private void acceptJavadocTypeReference(Expression expression) { } else if (expression instanceof JavadocQualifiedTypeReference) { JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression; this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd); + } else if (expression instanceof JavadocModuleReference) { + Expression exp = ((JavadocModuleReference) expression).getTypeReference(); + if (exp != null) { + acceptJavadocTypeReference(exp); + } } } public void addUnknownRef(NameReference nameRef) { @@ -1032,6 +1039,73 @@ protected QualifiedNameReference newQualifiedNameReference(char[][] tokens, long protected SingleNameReference newSingleNameReference(char[] source, long positions) { return new SingleNameReference(source, positions); } +private class DummyTypeReference extends TypeReference { + char[] token; + DummyTypeReference(char[] name) { + this.token = name; + } + @Override + public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, + Annotation[][] additionalAnnotations, boolean isVarargs) { + // TODO Auto-generated method stub + return null; + } + @Override + public char[] getLastToken() { + return this.token; + } + @Override + protected TypeBinding getTypeBinding(Scope scope) { + return null; + } + @Override + public char[][] getTypeName() { + return new char[][] {this.token}; + } + @Override + public void traverse(ASTVisitor visitor, BlockScope scope) { + // TODO Auto-generated method stub + } + + @Override + public void traverse(ASTVisitor visitor, ClassScope scope) { + // TODO Auto-generated method stub + } + + @Override + public StringBuffer printExpression(int indent, StringBuffer output) { + return output.append(this.token); + } + @Override + public String toString() { + return new String(this.token); + } +} +private void processImplicitPermittedTypes(TypeDeclaration typeDecl, TypeDeclaration[] allTypes) { + if (typeDecl.permittedTypes == null && + (typeDecl.modifiers & ExtraCompilerModifiers.AccSealed) != 0) { + List<TypeReference> list = new ArrayList(); + for (TypeDeclaration type : allTypes) { + if (type != typeDecl) { + char[][] qName = type.superclass == null ? null : type.superclass.getTypeName(); + if (qName != null && + CharOperation.equals(qName[qName.length -1], typeDecl.name)) { + list.add(new DummyTypeReference(type.name)); + } + if (type.superInterfaces != null) { + for (TypeReference ref : type.superInterfaces) { + qName = ref.getTypeName(); + if (CharOperation.equals(qName[qName.length -1], typeDecl.name)) { + list.add(new DummyTypeReference(type.name)); + break; + } + } + } + } + } + typeDecl.permittedTypes = list.toArray(new TypeReference[list.size()]); + } +} public CompilationUnitDeclaration parseCompilationUnit( ICompilationUnit unit, boolean fullParse, @@ -1046,6 +1120,12 @@ public CompilationUnitDeclaration parseCompilationUnit( this.reportReferenceInfo = fullParse; CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit); parsedUnit = parse(unit, compilationUnitResult); + TypeDeclaration[] types = parsedUnit.types; + if (types != null) { + for (TypeDeclaration typeDecl : types) { + processImplicitPermittedTypes(typeDecl, types); + } + } if (pm != null && pm.isCanceled()) throw new OperationCanceledException(Messages.operation_cancelled); if (this.scanner.recordLineSeparator) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java index 8b17f04707..05d54686fe 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java @@ -180,10 +180,6 @@ public class SourceElementRequestorAdapter implements ISourceElementRequestor { } @Override - public void enterRecordComponent(RecordComponentInfo recordComponentInfo) { - // default implementation: do nothing - } - @Override public void enterType(TypeInfo typeInfo) { // default implementation: do nothing } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java index 29b31b1349..33967f8407 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java @@ -570,6 +570,14 @@ public class SourceTypeConverter extends TypeConverter { type.superInterfaces[i].bits |= ASTNode.IsSuperType; } } + char[][] permittedSubtypeNames = typeInfo.getPermittedSubtypeNames(); + int permittedSubtypeCount = permittedSubtypeNames == null ? 0 : permittedSubtypeNames.length; + if (permittedSubtypeCount > 0) { + type.permittedTypes = new TypeReference[permittedSubtypeCount]; + for (int i = 0; i < permittedSubtypeCount; i++) { + type.permittedTypes[i] = createTypeReference(permittedSubtypeNames[i], start, end, true /* include generics */); + } + } /* convert member types */ if ((this.flags & MEMBER_TYPE) != 0) { SourceType[] sourceMemberTypes = typeInfo.getMemberTypeHandles(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryRecordComponent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryRecordComponent.java new file mode 100644 index 0000000000..678dfe0931 --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryRecordComponent.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2000, 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.Signature; +import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; +import org.eclipse.jdt.internal.compiler.env.IBinaryField; +import org.eclipse.jdt.internal.compiler.lookup.Binding; + +/** + * @see IField + */ + +/* package */ class BinaryRecordComponent extends BinaryMember implements IField { + +/* + * Constructs a handle to the field with the given name in the specified type. + */ +protected BinaryRecordComponent(JavaElement parent, String name) { + super(parent, name); +} +@Override +public boolean equals(Object o) { + if (!(o instanceof BinaryRecordComponent)) return false; + return super.equals(o); +} +@Override +public IAnnotation[] getAnnotations() throws JavaModelException { + IBinaryField info = (IBinaryField) getElementInfo(); + IBinaryAnnotation[] binaryAnnotations = info.getAnnotations(); + return getAnnotations(binaryAnnotations, info.getTagBits()); +} +/* + * @see IField + */ +@Override +public Object getConstant() throws JavaModelException { + IBinaryField info = (IBinaryField) getElementInfo(); + return convertConstant(info.getConstant()); +} +/* + * @see IMember + */ +@Override +public int getFlags() throws JavaModelException { + IBinaryField info = (IBinaryField) getElementInfo(); + return info.getModifiers(); +} +/* + * @see IJavaElement + */ +@Override +public int getElementType() { + return FIELD; +} +/* + * @see JavaElement#getHandleMemento() + */ +@Override +protected char getHandleMementoDelimiter() { + return JavaElement.JEM_FIELD; +} +@Override +public String getKey(boolean forceOpen) throws JavaModelException { + return getKey(this, forceOpen); +} +/* + * @see IField + */ +@Override +public String getTypeSignature() throws JavaModelException { + IBinaryField info = (IBinaryField) getElementInfo(); + char[] genericSignature = info.getGenericSignature(); + if (genericSignature != null) { + return new String(ClassFile.translatedName(genericSignature)); + } + return new String(ClassFile.translatedName(info.getTypeName())); +} +/* (non-Javadoc) + * @see org.eclipse.jdt.core.IField#isEnumConstant() + */@Override +public boolean isEnumConstant() throws JavaModelException { + return Flags.isEnum(getFlags()); +} + +@Override +public boolean isResolved() { + return false; +} +@Override +public JavaElement resolved(Binding binding) { + SourceRefElement resolvedHandle = new ResolvedBinaryField(this.parent, this.name, new String(binding.computeUniqueKey())); + resolvedHandle.occurrenceCount = this.occurrenceCount; + return resolvedHandle; +} +/* + * @private Debugging purposes + */ +@Override +protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) { + buffer.append(tabString(tab)); + if (info == null) { + toStringName(buffer); + buffer.append(" (not open)"); //$NON-NLS-1$ + } else if (info == NO_INFO) { + toStringName(buffer); + } else { + try { + buffer.append(Signature.toString(getTypeSignature())); + buffer.append(" "); //$NON-NLS-1$ + toStringName(buffer); + } catch (JavaModelException e) { + buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$ + } + } +} +@Override +public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException { + JavadocContents javadocContents = ((BinaryType) this.getDeclaringType()).getJavadocContents(monitor); + if (javadocContents == null) return null; + return javadocContents.getFieldDoc(this); +} +@Override +public boolean isRecordComponent() throws JavaModelException { + return false; +} +} diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java index 95f7640af8..f7ccbe0f40 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java @@ -589,6 +589,21 @@ public String[] getSuperInterfaceNames() throws JavaModelException { } return strings; } +@Override +public String[] getPermittedSubtypeNames() throws JavaModelException { + IBinaryType info = (IBinaryType) getElementInfo(); + char[][] names= info.getPermittedSubtypeNames(); + int length; + if (names == null || (length = names.length) == 0) { + return CharOperation.NO_STRINGS; + } + names= ClassFile.translatedNames(names); + String[] strings= new String[length]; + for (int i= 0; i < length; i++) { + strings[i]= new String(names[i]); + } + return strings; +} /** * @see IType#getSuperInterfaceTypeSignatures() @@ -743,6 +758,16 @@ public boolean isRecord() throws JavaModelException { IBinaryType info = (IBinaryType) getElementInfo(); return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.RECORD_DECL; } +/** + * @see IType#isSealed() + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ +@Override +public boolean isSealed() throws JavaModelException { + IBinaryType info = (IBinaryType) getElementInfo(); + char[][] names = info.getPermittedSubtypeNames(); + return (names != null && names.length > 0); +} @Override public boolean isInterface() throws JavaModelException { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java index d7f86001a5..47a5ba2426 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java @@ -18,12 +18,14 @@ import java.util.HashMap; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; import org.eclipse.jdt.internal.compiler.env.IBinaryType; +import org.eclipse.jdt.internal.compiler.env.IRecordComponent; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; @@ -235,6 +237,10 @@ private void generateFieldInfos(IType type, IBinaryType typeInfo, HashMap newEle JavaModelManager manager = JavaModelManager.getJavaModelManager(); for (int i = 0, fieldCount = fields.length; i < fieldCount; i++) { IBinaryField fieldInfo = fields[i]; + // If the type is a record and this is an instance field, it can only be a record component + // Filter out + if (typeInfo.isRecord() && (fieldInfo.getModifiers() & ClassFileConstants.AccStatic) == 0) + continue; BinaryField field = new BinaryField((JavaElement)type, manager.intern(new String(fieldInfo.getName()))); newElements.put(field, fieldInfo); childrenHandles.add(field); @@ -242,6 +248,30 @@ private void generateFieldInfos(IType type, IBinaryType typeInfo, HashMap newEle } } /** + * Creates the handles and infos for the fields of the given binary type. + * Adds new handles to the given vector. + */ +private void generateRecordComponentInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList childrenHandles) { + // Make the fields + IRecordComponent[] components = typeInfo.getRecordComponents(); + if (components == null) { + return; + } + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + for (int i = 0, fieldCount = components.length; i < fieldCount; i++) { + IRecordComponent componentInfo = components[i]; + BinaryField component = new BinaryField((JavaElement)type, manager.intern(new String(componentInfo.getName()))) { + @Override + public boolean isRecordComponent() throws JavaModelException { + return true; + } + }; + newElements.put(component, componentInfo); + childrenHandles.add(component); + generateAnnotationsInfos(component, componentInfo.getAnnotations(), componentInfo.getTagBits(), newElements); + } +} +/** * Creates the handles for the inner types of the given binary type. * Adds new handles to the given vector. */ @@ -428,6 +458,7 @@ protected void readBinaryChildren(ClassFile classFile, HashMap newElements, IBin generateAnnotationsInfos(type, typeInfo.getAnnotations(), typeInfo.getTagBits(), newElements); generateTypeParameterInfos(type, typeInfo.getGenericSignature(), newElements, typeParameterHandles); generateFieldInfos(type, typeInfo, newElements, childrenHandles); + generateRecordComponentInfos(type, typeInfo, newElements, childrenHandles); generateMethodInfos(type, typeInfo, newElements, childrenHandles, typeParameterHandles); generateInnerClassHandles(type, typeInfo, childrenHandles); // Note inner class are separate openables that are not opened here: no need to pass in newElements } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java index 4ae54d9987..79dc7be0e3 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java @@ -239,7 +239,7 @@ protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) { String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name)); return new SourceField(parent, fieldName); } -protected SourceField createRecordComponent(JavaElement parent, RecordComponentInfo compInfo) { +protected SourceField createRecordComponent(JavaElement parent, FieldInfo compInfo) { String name = JavaModelManager.getJavaModelManager().intern(new String(compInfo.name)); SourceField field = new SourceField(parent, name) { @Override @@ -355,7 +355,11 @@ public void enterField(FieldInfo fieldInfo) { JavaElement parentHandle= (JavaElement) this.handleStack.peek(); SourceField handle = null; if (parentHandle.getElementType() == IJavaElement.TYPE) { - handle = createField(parentHandle, fieldInfo); + if (fieldInfo.isRecordComponent) { + handle = createRecordComponent(parentHandle, fieldInfo); + } else { + handle = createField(parentHandle, fieldInfo); + } } else { Assert.isTrue(false); // Should not happen @@ -436,6 +440,7 @@ private SourceMethodElementInfo createMethodInfo(MethodInfo methodInfo, SourceMe } else { info = elements.length == 0 ? new SourceMethodInfo() : new SourceMethodWithChildrenInfo(elements); } + info.isCanonicalConstructor = methodInfo.isCanonicalConstr; info.setSourceRangeStart(methodInfo.declarationStart); int flags = methodInfo.modifiers; info.setNameSourceStart(methodInfo.nameSourceStart); @@ -584,10 +589,14 @@ private SourceTypeElementInfo createTypeInfo(TypeInfo typeInfo, SourceType handl JavaModelManager manager = JavaModelManager.getJavaModelManager(); char[] superclass = typeInfo.superclass; info.setSuperclassName(superclass == null ? null : manager.intern(superclass)); - char[][] superinterfaces = typeInfo.superinterfaces; - for (int i = 0, length = superinterfaces == null ? 0 : superinterfaces.length; i < length; i++) - superinterfaces[i] = manager.intern(superinterfaces[i]); - info.setSuperInterfaceNames(superinterfaces); + char[][] typeNames = typeInfo.superinterfaces; + for (int i = 0, length = typeNames == null ? 0 : typeNames.length; i < length; i++) + typeNames[i] = manager.intern(typeNames[i]); + info.setSuperInterfaceNames(typeNames); + typeNames = typeInfo.permittedSubtypes; + for (int i = 0, length = typeNames == null ? 0 : typeNames.length; i < length; i++) + typeNames[i] = manager.intern(typeNames[i]); + info.setPermittedSubtypeNames(typeNames); info.addCategories(handle, typeInfo.categories); this.newElements.put(handle, info); @@ -727,7 +736,7 @@ public void exitField(int initializationStart, int declarationEnd, int declarati @Override public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) { JavaElement handle = (JavaElement) this.handleStack.peek(); - RecordComponentInfo compInfo = (RecordComponentInfo) this.infoStack.peek(); + FieldInfo compInfo = (FieldInfo) this.infoStack.peek(); IJavaElement[] elements = getChildren(compInfo); SourceFieldElementInfo info = elements.length == 0 ? new SourceFieldElementInfo() : new SourceFieldWithChildrenInfo(elements); info.isRecordComponent = true; @@ -944,23 +953,4 @@ protected Object getMemberValue(org.eclipse.jdt.internal.core.MemberValuePair me return null; } } -@Override -public void enterRecordComponent(RecordComponentInfo recordComponentInfo) { - TypeInfo parentInfo = (TypeInfo) this.infoStack.peek(); - JavaElement parentHandle= (JavaElement) this.handleStack.peek(); - SourceField handle = null; - if (parentHandle.getElementType() == IJavaElement.TYPE) { - handle = createRecordComponent(parentHandle, recordComponentInfo); - } - else { - Assert.isTrue(false); // Should not happen - } - resolveDuplicates(handle); - - addToChildren(parentInfo, handle); - parentInfo.childrenCategories.put(handle, recordComponentInfo.categories); - - this.infoStack.push(recordComponentInfo); - this.handleStack.push(handle); -} } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java index 5cea5b616f..2583c18bfd 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java @@ -90,7 +90,7 @@ public class CopyResourceElementsOperation extends MultiOperation implements Suf initializeASTParser(); } private void initializeASTParser() { - this.parser = ASTParser.newParser(AST.JLS14); + this.parser = ASTParser.newParser(getLatestASTLevel()); } /** * Returns the children of <code>source</code> which are affected by this operation. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java index d1635908a7..d4d092cb1b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -267,7 +267,7 @@ public abstract class CreateElementInCUOperation extends JavaModelOperation { // ensure cu is consistent (noop if already consistent) cu.makeConsistent(this.progressMonitor); // create an AST for the compilation unit - ASTParser parser = ASTParser.newParser(AST.JLS14); + ASTParser parser = ASTParser.newParser(getLatestASTLevel()); parser.setSource(cu); return (CompilationUnit) parser.createAST(this.progressMonitor); } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java index 65a1e92ae5..99bd3977d0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java @@ -23,7 +23,6 @@ import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; @@ -86,7 +85,7 @@ protected StructuralPropertyDescriptor getChildPropertyDescriptor(ASTNode parent protected ASTNode generateElementAST(ASTRewrite rewriter, ICompilationUnit cu) throws JavaModelException { if (this.createdNode == null) { this.source = removeIndentAndNewLines(this.source, cu); - ASTParser parser = ASTParser.newParser(AST.JLS14); + ASTParser parser = ASTParser.newParser(getLatestASTLevel()); parser.setSource(this.source.toCharArray()); parser.setProject(getCompilationUnit().getJavaProject()); parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS); @@ -173,7 +172,7 @@ protected String generateSyntaxIncorrectAST() { buff.append(lineSeparator + " public class A {" + lineSeparator); //$NON-NLS-1$ buff.append(this.source); buff.append(lineSeparator).append('}'); - ASTParser parser = ASTParser.newParser(AST.JLS14); + ASTParser parser = ASTParser.newParser(getLatestASTLevel()); parser.setSource(buff.toString().toCharArray()); CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); TypeDeclaration typeDeclaration = (TypeDeclaration) compilationUnit.types().iterator().next(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java index c119a55d24..380132d662 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -84,7 +84,7 @@ public class DeleteElementsOperation extends MultiOperation { } private void initASTParser() { - this.parser = ASTParser.newParser(AST.JLS14); + this.parser = ASTParser.newParser(getLatestASTLevel()); } /** diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java index 0b53db6ed4..3b664d4b3b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java @@ -446,7 +446,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement for (int i = children.length-1; i >= 0; i--) { IJavaElement aChild = children[i]; if (aChild instanceof SourceRefElement) { - SourceRefElement child = (SourceRefElement) children[i]; + SourceRefElement child = (SourceRefElement) aChild; ISourceRange range = child.getSourceRange(); int start = range.getOffset(); int end = start + range.getLength(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java index 2fee564093..8dd3ad41d9 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -22,6 +22,7 @@ import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -153,6 +154,9 @@ public abstract class JavaModelOperation implements IWorkspaceRunnable, IProgres this.elementsToProcess = new IJavaElement[]{element}; } + protected int getLatestASTLevel() { + return AST.JLS15; + } /* * Registers the given action at the end of the list of actions to run. */ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java index 8ee095c0ca..51f82007f0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java @@ -14,6 +14,7 @@ package org.eclipse.jdt.internal.core; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -271,6 +272,14 @@ public void acceptField(char[] declaringTypePackageName, char[] declaringTypeNam if(type != null) { try { IField[] fields = type.getFields(); + if (type.isRecord()) { + IField[] comps = type.getRecordComponents(); + if(comps.length > 0) { + IField[] f = fields; + fields = Arrays.copyOf(f, f.length + comps.length); + System.arraycopy(comps, 0, fields, f.length, comps.length); + } + } for (int i = 0; i < fields.length; i++) { IField field = fields[i]; ISourceRange range = field.getNameRange(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java index 44a3a65505..fc595f9a8f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java @@ -915,24 +915,6 @@ public class SourceMapper addCategories(field, fieldInfo.categories); } } - /** - * @see ISourceElementRequestor - */ - @Override - public void enterRecordComponent(RecordComponentInfo compInfo) { - if (this.typeDepth >= 0) { - this.memberDeclarationStart[this.typeDepth] = compInfo.declarationStart; - this.memberNameRange[this.typeDepth] = - new SourceRange(compInfo.nameSourceStart, compInfo.nameSourceEnd - compInfo.nameSourceStart + 1); - String fieldName = new String(compInfo.name); - this.memberName[this.typeDepth] = fieldName; - - // categories - IType currentType = this.types[this.typeDepth]; - IField field = currentType.getRecordComponent(fieldName); - addCategories(field, compInfo.categories); - } - } /** * @see ISourceElementRequestor diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java index 3d31be1c69..f99005feb4 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java @@ -49,6 +49,8 @@ public abstract class SourceMethodElementInfo extends AnnotatableInfo implements */ protected ITypeParameter[] typeParameters = TypeParameter.NO_TYPE_PARAMETERS; + protected boolean isCanonicalConstructor; + @Override public char[][] getArgumentNames() { return this.argumentNames; @@ -86,6 +88,9 @@ public char[][] getTypeParameterNames() { } @Override public abstract boolean isConstructor(); +public boolean isCanonicalConstructor() { + return this.isCanonicalConstructor; +} public abstract boolean isAnnotationMethod(); protected void setArgumentNames(char[][] names) { this.argumentNames = names; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java index 504a131128..a2bbf9c9c2 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java @@ -300,6 +300,12 @@ public IField[] getRecordComponents() throws JavaModelException { return NO_FIELDS; return getFieldsOrComponents(true); } +@Override +public String[] getPermittedSubtypeNames() throws JavaModelException { + SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo(); + char[][] names= info.getPermittedSubtypeNames(); + return CharOperation.toStrings(names); +} private IField[] getFieldsOrComponents(boolean component) throws JavaModelException { ArrayList list = getChildrenOfType(FIELD); if (list.size() == 0) { @@ -694,6 +700,15 @@ public boolean isRecord() throws JavaModelException { SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo(); return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.RECORD_DECL; } +/** + * @see IType#isSealed() + * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature. + */ +@Override +public boolean isSealed() throws JavaModelException { + SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo(); + return Flags.isSealed(info.getModifiers()); +} /** * @see IType @@ -967,6 +982,9 @@ protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean s } } else { try { + if (isSealed()) { + buffer.append("sealed "); //$NON-NLS-1$ + } if (isRecord()) { buffer.append("record "); //$NON-NLS-1$ } else if (isEnum()) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java index de6bb33d80..69934eabce 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -50,6 +50,8 @@ public class SourceTypeElementInfo extends AnnotatableInfo implements ISourceTyp */ protected char[][] superInterfaceNames; + protected char[][] permittedTypeNames; + /** * Backpointer to my type handle - useful for translation * from info to handle. @@ -182,7 +184,16 @@ public char[][] getInterfaceNames() { } return this.superInterfaceNames; } - +/** + * @see ISourceType + */ +@Override +public char[][] getPermittedSubtypeNames() { + if (isAnonymous()) { // if anonymous type + return null; + } + return this.permittedTypeNames; +} /** * @see ISourceType */ @@ -334,6 +345,9 @@ protected void setSuperclassName(char[] superclassName) { protected void setSuperInterfaceNames(char[][] superInterfaceNames) { this.superInterfaceNames = superInterfaceNames; } +protected void setPermittedSubtypeNames(char[][] permittedTypeNames) { + this.permittedTypeNames = permittedTypeNames; +} @Override public String toString() { return "Info for " + this.handle.toString(); //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java index 58adc80954..e1f16f002b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java @@ -57,7 +57,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { protected Path releasePath; protected Path modulePath; private String modPathString; - private CtSym ctSym; + CtSym ctSym; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java index a92f2fc9ed..ff0aef001d 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -27,6 +27,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; +import org.eclipse.jdt.internal.compiler.env.IRecordComponent; import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; @@ -233,6 +234,10 @@ public boolean isLocal() { return false; // index did not record this information (since unused for hierarchies) } @Override +public boolean isRecord() { + return false; // index did not record this information (since unused for hierarchies) +} +@Override public boolean isMember() { return false; // index did not record this information (since unused for hierarchies) } @@ -337,4 +342,9 @@ public char[] getModule() { public ExternalAnnotationStatus getExternalAnnotationStatus() { return ExternalAnnotationStatus.NOT_EEA_CONFIGURED; } + +@Override +public IRecordComponent[] getRecordComponents() { + return null; +} } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java index be4e2edac1..5568fc98f0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java @@ -209,11 +209,6 @@ protected SourceElementParser getParser(Map<String, String> settings) { } @Override -public void enterRecordComponent(RecordComponentInfo recordComponentInfo) { - // TODO Auto-generated method stub -} - -@Override public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) { // TODO Auto-generated method stub } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java index 3203fceddd..1e4092af0e 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.core.util.IInnerClassesAttribute; import org.eclipse.jdt.core.util.IMethodInfo; import org.eclipse.jdt.core.util.IModifierConstants; import org.eclipse.jdt.core.util.INestMembersAttribute; +import org.eclipse.jdt.core.util.IPermittedSubclassesAttribute; import org.eclipse.jdt.core.util.IRecordAttribute; import org.eclipse.jdt.core.util.ISourceAttribute; import org.eclipse.jdt.internal.compiler.util.Util; @@ -49,6 +50,7 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader private int fieldsCount; private IInnerClassesAttribute innerClassesAttribute; private INestMembersAttribute nestMembersAttribute; + private IPermittedSubclassesAttribute permittedSubclassesAttribute; private int[] interfaceIndexes; private char[][] interfaceNames; private int interfacesCount; @@ -314,6 +316,9 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader } else if (equals(attributeName, IAttributeNamesConstants.RECORD)) { this.recordAttribute = new RecordAttribute(classFileBytes, this.constantPool, readOffset); this.attributes[attributesIndex++] = this.recordAttribute; + } else if (equals(attributeName, IAttributeNamesConstants.PERMITTED_SUBCLASSES)) { + this.permittedSubclassesAttribute = new PermittedSubclassesAttribute(classFileBytes, this.constantPool, readOffset); + this.attributes[attributesIndex++] = this.permittedSubclassesAttribute; } else { this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset); } @@ -395,6 +400,9 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader public IFieldInfo[] getFieldInfos() { return this.fields; } + /* + * @see IClassFileReader#getFieldInfos() + */ /** * @see IClassFileReader#getFieldsCount() @@ -417,6 +425,11 @@ public class ClassFileReader extends ClassFileStruct implements IClassFileReader return this.nestMembersAttribute; } + @Override + public IPermittedSubclassesAttribute getPermittedSubclassesAttribute() { + return this.permittedSubclassesAttribute; + } + /** * @see IClassFileReader#getInterfaceIndexes() */ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java index 8bb273a84e..2899853fd6 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java @@ -1023,6 +1023,7 @@ public class Disassembler extends ClassFileBytesDisassembler { } INestMembersAttribute nestMembersAttribute = classFileReader.getNestMembersAttribute(); + IPermittedSubclassesAttribute permittedSubclassesAttribute = classFileReader.getPermittedSubclassesAttribute(); IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute(); IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); @@ -1184,6 +1185,9 @@ public class Disassembler extends ClassFileBytesDisassembler { if (nestMembersAttribute != null) { remainingAttributesLength--; } + if (permittedSubclassesAttribute != null) { + remainingAttributesLength--; + } if (innerClassesAttribute != null || enclosingMethodAttribute != null || nestHostAttribute != null @@ -1191,6 +1195,7 @@ public class Disassembler extends ClassFileBytesDisassembler { || bootstrapMethods != null || moduleAttribute != null || recordAttribute != null + || permittedSubclassesAttribute != null || remainingAttributesLength != 0) { // this test is to ensure we don't insert more than one line separator if (buffer.lastIndexOf(lineSeparator) != buffer.length() - lineSeparator.length()) { @@ -1215,6 +1220,9 @@ public class Disassembler extends ClassFileBytesDisassembler { if (bootstrapMethods != null) { disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0, classFileReader.getConstantPool()); } + if (permittedSubclassesAttribute != null) { + disassemble(permittedSubclassesAttribute, buffer, lineSeparator, 0); + } if (checkMode(mode, SYSTEM)) { if (runtimeVisibleAnnotationsAttribute != null) { disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); @@ -1235,6 +1243,7 @@ public class Disassembler extends ClassFileBytesDisassembler { && attribute != nestHostAttribute && attribute != nestMembersAttribute && attribute != recordAttribute + && attribute != permittedSubclassesAttribute && attribute != sourceAttribute && attribute != signatureAttribute && attribute != enclosingMethodAttribute @@ -1478,6 +1487,32 @@ public class Disassembler extends ClassFileBytesDisassembler { } } } + private void disassemble(IPermittedSubclassesAttribute permittedSubclassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { + writeNewLine(buffer, lineSeparator, tabNumber); + writeNewLine(buffer, lineSeparator, tabNumber); // additional line + buffer.append(Messages.disassembler_permittedsubclasses); + writeNewLine(buffer, lineSeparator, tabNumber + 1); + IPermittedSubclassesAttributeEntry[] entries = permittedSubclassesAttribute.getPermittedSubclassAttributesEntries(); + int length = entries.length; + int permittedSubclassesIndex; + IPermittedSubclassesAttributeEntry entry; + for (int i = 0; i < length; i++) { + if (i != 0) { + buffer.append(Messages.disassembler_comma); + writeNewLine(buffer, lineSeparator, tabNumber + 1); + } + entry = entries[i]; + permittedSubclassesIndex = entry.gePermittedSubclassIndex(); + buffer + .append(Messages.disassembler_constantpoolindex) + .append(permittedSubclassesIndex); + if (permittedSubclassesIndex != 0) { + buffer + .append(Messages.disassembler_space) + .append(entry.getPermittedSubclassName()); + } + } + } private void disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator, int tabNumber, boolean isExports) { buffer.append(isExports ? "exports" : "opens"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java index 989b64b8b4..91cbd74f6f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java @@ -282,6 +282,7 @@ public final class Messages extends NLS { public static String disassembler_nesthost; public static String disassembler_nestmembers; public static String disassembler_record; + public static String disassembler_permittedsubclasses; public static String disassembler_components; public static String disassembler_endofcomponent; public static String disassembler_genericattributeheader; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttribute.java new file mode 100644 index 0000000000..7b19f861cd --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttribute.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IPermittedSubclassesAttributeEntry; +import org.eclipse.jdt.core.util.IPermittedSubclassesAttribute; + +/** + * Default implementation of IPermittedSubclassesAttribute. + */ +public class PermittedSubclassesAttribute extends ClassFileAttribute implements IPermittedSubclassesAttribute { + private static final IPermittedSubclassesAttributeEntry[] NO_ENTRIES = new IPermittedSubclassesAttributeEntry[0]; + + private int permittedSubclasses; + private IPermittedSubclassesAttributeEntry[] entries; + + /** + * Constructor for PermittedSubclassesAttribute. + * @param classFileBytes + * @param constantPool + * @param offset + * @throws ClassFormatException + */ + public PermittedSubclassesAttribute( + byte[] classFileBytes, + IConstantPool constantPool, + int offset) + throws ClassFormatException { + super(classFileBytes, constantPool, offset); + this.permittedSubclasses = u2At(classFileBytes, 6, offset); + final int length = this.permittedSubclasses; + if (length != 0) { + int readOffset = 8; + this.entries = new IPermittedSubclassesAttributeEntry[length]; + for (int i = 0; i < length; i++) { + this.entries[i] = new PermittedSubclassesAttributeEntry(classFileBytes, constantPool, offset + readOffset); + readOffset += 2; + } + } else { + this.entries = NO_ENTRIES; + } + } + + @Override + public int getNumberOfPermittedSubclasses() { + return this.permittedSubclasses; + } + + @Override + public IPermittedSubclassesAttributeEntry[] getPermittedSubclassAttributesEntries() { + return this.entries; + } + +} diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttributeEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttributeEntry.java new file mode 100644 index 0000000000..bb33b4b2ae --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PermittedSubclassesAttributeEntry.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.core.util; + +import org.eclipse.jdt.core.util.ClassFormatException; +import org.eclipse.jdt.core.util.IConstantPool; +import org.eclipse.jdt.core.util.IConstantPoolConstant; +import org.eclipse.jdt.core.util.IConstantPoolEntry; +import org.eclipse.jdt.core.util.IPermittedSubclassesAttributeEntry; + +public class PermittedSubclassesAttributeEntry extends ClassFileStruct implements IPermittedSubclassesAttributeEntry { + + private int permittedClassNameIndex; + private char[] permittedClassName; + + public PermittedSubclassesAttributeEntry(byte[] classFileBytes, IConstantPool constantPool, int offset) + throws ClassFormatException { + this.permittedClassNameIndex = u2At(classFileBytes, 0, offset); + if (this.permittedClassNameIndex != 0) { + IConstantPoolEntry constantPoolEntry; + constantPoolEntry = constantPool.decodeEntry(this.permittedClassNameIndex); + if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) { + throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); + } + this.permittedClassName = constantPoolEntry.getClassInfoName(); + } + } + + @Override + public String toString() { + return new String(this.permittedClassName); + } + + @Override + public char[] getPermittedSubclassName() { + return this.permittedClassName; + } + + @Override + public int gePermittedSubclassIndex() { + return this.permittedClassNameIndex; + } +} + diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java index d7d6bc39c0..f2b81783c4 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java @@ -4263,6 +4263,7 @@ public static boolean isKeyword(int token) { case TerminalTokens.TokenNameinstanceof: case TerminalTokens.TokenNamelong: case TerminalTokens.TokenNamenew: + case TerminalTokens.TokenNamenon_sealed: case TerminalTokens.TokenNamenull: case TerminalTokens.TokenNamenative: case TerminalTokens.TokenNamepublic: diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties index cb269da38b..cd39d61412 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2018 IBM Corporation and others. +# Copyright (c) 2000, 2020 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -302,6 +302,7 @@ disassembler_arraydimensions = [] disassembler_nesthost = Nest Host: disassembler_nestmembers = Nest Members: disassembler_record = Record: +disassembler_permittedsubclasses = PermittedSubclasses: disassembler_components = Components: disassembler_endofcomponent = ; disassembler_innerattributesheader = Inner classes: |