diff options
author | Sarika Sinha | 2019-11-28 04:46:43 +0000 |
---|---|---|
committer | Sarika Sinha | 2019-12-07 12:17:16 +0000 |
commit | ccf6e4b85f958e25ff2d828d9211acab530a13f4 (patch) | |
tree | 5a2ac89e73292d7b6a62a15e29692e60746f3df5 | |
parent | d3c7714097800c956772f7fe7fcfc69bd1ebb975 (diff) | |
download | eclipse.jdt.core-ccf6e4b85f958e25ff2d828d9211acab530a13f4.tar.gz eclipse.jdt.core-ccf6e4b85f958e25ff2d828d9211acab530a13f4.tar.xz eclipse.jdt.core-ccf6e4b85f958e25ff2d828d9211acab530a13f4.zip |
Change-Id: I213e3fbee19f2965c7cdd6b39e8d08bce163651a
14 files changed, 946 insertions, 7 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java index 9158ad630e..5f87d7c2cf 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java @@ -8,6 +8,10 @@ * * SPDX-License-Identifier: EPL-2.0 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -356,7 +360,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit. } public void testNodeClassForType() { - Set classes = new HashSet(100); + Set classes = new HashSet(103); // make sure node types are contiguous starting at 0 int hi = 0; for (int nodeType = 1; nodeType < 110; nodeType++) { @@ -372,7 +376,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit. // oops - guess that's not valid } } - assertEquals("Wrong last known type", 102, hi); // last known one + assertEquals("Wrong last known type", 103, hi); // last known one assertEquals("Wrong number of distinct types", hi, classes.size()); // all classes are distinct } } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java index fd7bedc9eb..a63d7e2d68 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java @@ -8897,7 +8897,8 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase ASTNode.MODULE_MODIFIER, ASTNode.SWITCH_EXPRESSION, ASTNode.YIELD_STATEMENT, - ASTNode.TEXT_BLOCK + ASTNode.TEXT_BLOCK, + ASTNode.RECORD_DECLARATION }; diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index c42131b458..1723c65997 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -818,6 +818,7 @@ public final class AST { int apiLevel; private boolean previewEnabled; + /** * Tag bit value. This represents internal state of the tree. */ @@ -3638,6 +3639,17 @@ public final class AST { throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$ } } + + + /** + * + * @return If previewEnabled flag is set to <code>true</true>, return <code>true</code> else <code>false</code> + * @since 3.20 BETA_JAVA + * @noreference This method is not intended to be referenced by clients. + */ + public boolean isPreviewEnabledSet() { + return this.previewEnabled; + } /** * diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java index 65818bf183..1bdd4d5402 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java @@ -41,6 +41,7 @@ import org.eclipse.jdt.core.dom.ModuleModifier.ModuleModifierKeyword; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; +import org.eclipse.jdt.internal.compiler.ast.CompactConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference; @@ -74,6 +75,7 @@ import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.core.dom.SourceRangeVerifier; +import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil; import org.eclipse.jdt.internal.core.util.Util; /** @@ -525,6 +527,9 @@ class ASTConverter { setModifiers(methodDecl, methodDeclaration); boolean isConstructor = methodDeclaration.isConstructor(); methodDecl.setConstructor(isConstructor); + if (DOMASTUtil.isRecordDeclarationSupported(this.ast)) { + methodDecl.setCompactConstructor(methodDeclaration instanceof CompactConstructorDeclaration); + } final SimpleName methodName = new SimpleName(this.ast); methodName.internalSetIdentifier(new String(methodDeclaration.selector)); int start = methodDeclaration.sourceStart; @@ -3061,6 +3066,12 @@ class ASTConverter { } else { return convertToAnnotationDeclaration(typeDeclaration); } + case org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.RECORD_DECL : + if (!DOMASTUtil.isRecordDeclarationSupported(this.ast)) { + return null; + } else { + return convertToRecordDeclaration(typeDeclaration); + } } checkCanceled(); @@ -3375,6 +3386,38 @@ class ASTConverter { } return enumDeclaration2; } + + private RecordDeclaration convertToRecordDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) { + checkCanceled(); + // record declaration cannot be built if the source is not >= 14, since record is then seen as an identifier + final RecordDeclaration recordDeclaration = new RecordDeclaration(this.ast); + setModifiers(recordDeclaration, typeDeclaration); + final SimpleName typeName = new SimpleName(this.ast); + typeName.internalSetIdentifier(new String(typeDeclaration.name)); + typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1); + recordDeclaration.setName(typeName); + recordDeclaration.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1); + + org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces; + if (superInterfaces != null) { + for (int index = 0, length = superInterfaces.length; index < length; index++) { + recordDeclaration.superInterfaceTypes().add(convertType(superInterfaces[index])); + } + } + org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = typeDeclaration.typeParameters; + if (typeParameters != null) { + for (int index = 0, length = typeParameters.length; index < length; index++) { + recordDeclaration.typeParameters().add(convert(typeParameters[index])); + } + } + buildBodyDeclarations(typeDeclaration, recordDeclaration, false); + if (this.resolveBindings) { + recordNodes(recordDeclaration, typeDeclaration); + recordNodes(typeName, typeDeclaration); + recordDeclaration.resolveBinding(); + } + return recordDeclaration; + } public Expression convertToExpression(org.eclipse.jdt.internal.compiler.ast.Statement statement) { if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Expression && ((org.eclipse.jdt.internal.compiler.ast.Expression) statement).isTrulyExpression()) { @@ -5390,6 +5433,11 @@ class ASTConverter { this.scanner.resetTo(enumDeclaration2.declarationSourceStart, enumDeclaration2.sourceStart); this.setModifiers(enumDeclaration, enumDeclaration2.annotations, enumDeclaration2.sourceStart); } + + protected void setModifiers(RecordDeclaration recordDeclaration, org.eclipse.jdt.internal.compiler.ast.TypeDeclaration recordDeclaration2) { + this.scanner.resetTo(recordDeclaration2.declarationSourceStart, recordDeclaration2.sourceStart); + this.setModifiers(recordDeclaration, recordDeclaration2.annotations, recordDeclaration2.sourceStart); + } protected void setModifiers(EnumConstantDeclaration enumConstantDeclaration, org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) { switch(this.ast.apiLevel) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java index 476d186ec5..97286123cb 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java @@ -20,6 +20,8 @@ package org.eclipse.jdt.core.dom; import java.util.Iterator; import java.util.List; +import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil; + /** * Concrete superclass and default implementation of an AST subtree matcher. * <p> @@ -1517,7 +1519,10 @@ public class ASTMatcher { && safeSubtreeListMatch(node.thrownExceptionTypes(), o.thrownExceptionTypes()) : node.getExtraDimensions() == o.getExtraDimensions() && safeSubtreeListMatch(node.internalThrownExceptions(), o.internalThrownExceptions())) - && safeSubtreeMatch(node.getBody(), o.getBody()); + && safeSubtreeMatch(node.getBody(), o.getBody()) + && (DOMASTUtil.isRecordDeclarationSupported(node.getAST()) + ? node.isCompactConstructor() == o.isCompactConstructor() + : true); } /** @@ -1976,6 +1981,37 @@ public class ASTMatcher { * @return <code>true</code> if the subtree matches, or * <code>false</code> if they do not match or the other object has a * different node type or is <code>null</code> + * @since 3.20 BETA_JAVA + */ + public boolean match(RecordDeclaration node, Object other) { + if (!(other instanceof RecordDeclaration)) { + return false; + } + RecordDeclaration o = (RecordDeclaration) other; + return ( + safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) + && safeSubtreeListMatch(node.modifiers(), o.modifiers()) + && safeSubtreeMatch(node.getName(), o.getName()) + && safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes()) + && safeSubtreeMatch(node.typeParameters(), o.typeParameters()) + && safeSubtreeListMatch( + node.bodyDeclarations(), + o.bodyDeclarations())); + } + + /** + * Returns whether the given node and the other object match. + * <p> + * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + * </p> + * + * @param node the node + * @param other the other object, or <code>null</code> + * @return <code>true</code> if the subtree matches, or + * <code>false</code> if they do not match or the other object has a + * different node type or is <code>null</code> * * @since 3.14 */ diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java index ab815d29a5..d98eac8b9a 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java @@ -981,6 +981,15 @@ public abstract class ASTNode { * @since 3.20 */ public static final int TEXT_BLOCK = 102; + + /** + * Node type constant indicating a node of type + * <code>RecordDeclaration</code>. + * @see RecordDeclaration + * @since 3.20 BETA_JAVA + */ + public static final int RECORD_DECLARATION = 103; + /** * Returns the node class for the corresponding node type. @@ -1130,6 +1139,8 @@ public abstract class ASTNode { return QualifiedName.class; case QUALIFIED_TYPE : return QualifiedType.class; + case RECORD_DECLARATION : + return RecordDeclaration.class; case REQUIRES_DIRECTIVE : return RequiresDirective.class; case RETURN_STATEMENT : diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java index bb5494e294..57e9eda62c 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java @@ -8,6 +8,10 @@ * * SPDX-License-Identifier: EPL-2.0 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -1346,6 +1350,24 @@ public abstract class ASTVisitor { * Visits the given type-specific AST node. * <p> * The default implementation does nothing and return true. + * Subclasses may re-implement. + * </p> + * + * @param node the node to visit + * @return <code>true</code> if the children of this node should be + * visited, and <code>false</code> if the children of this node should + * be skipped + * @since 3.20 BETA_JAVA + * @noreference This method is not intended to be referenced by clients. + */ + public boolean visit(RecordDeclaration node) { + return true; + } + + /** + * Visits the given type-specific AST node. + * <p> + * The default implementation does nothing and return true. * Subclasses may reimplement. * </p> * @@ -2749,6 +2771,21 @@ public abstract class ASTVisitor { /** * End of visit the given type-specific AST node. * <p> + * The default implementation does nothing. Subclasses may re implement. + * </p> + * + * @param node the node to visit + * @since 3.20 BETA_JAVA + * @noreference This method is not intended to be referenced by clients. + */ + public void endVisit(RecordDeclaration node) { + // default implementation: do nothing + } + + + /** + * End of visit the given type-specific AST node. + * <p> * The default implementation does nothing. Subclasses may reimplement. * </p> * diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java index ef2783f72a..bd2aa8ceb7 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -8,6 +8,10 @@ * * SPDX-License-Identifier: EPL-2.0 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -871,6 +875,29 @@ class BindingResolver { ITypeBinding resolveType(EnumDeclaration type) { return null; } + + /** + * Resolves the given record declaration and returns the binding + * for it. + * <p> + * The implementation of <code>RecordDeclaration.resolveBinding</code> + * forwards to this method. How the record declaration resolves is often + * a function of the context in which the declaration node is embedded + * as well as the record declaration subtree itself. + * </p> + * <p> + * The default implementation of this method returns <code>null</code>. + * Subclasses may re implement. + * </p> + * + * @param type the record declaration of interest + * @return the binding for the given record declaration, or <code>null</code> + * if no binding is available + * @since 3.20 BETA_JAVA + */ + ITypeBinding resolveType(RecordDeclaration type) { + return null; + } /** * Resolves the given type and returns the type binding for it. diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java index ee36dc5527..abb11eec6c 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java @@ -8,6 +8,10 @@ * * SPDX-License-Identifier: EPL-2.0 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for @@ -1676,6 +1680,27 @@ class DefaultBindingResolver extends BindingResolver { } return null; } + + @Override + ITypeBinding resolveType(RecordDeclaration type) { + final Object node = this.newAstToOldAst.get(type); + if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) { + org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node; + ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding); + if (typeBinding == null) { + return null; + } + this.bindingsToAstNodes.put(typeBinding, type); + String key = typeBinding.getKey(); + if (key != null) { + this.bindingTables.bindingKeysToBindings.put(key, typeBinding); + } + return typeBinding; + } + return null; + } + + @Override synchronized ITypeBinding resolveType(Type type) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java index 158c19f26e..dc8a9498c9 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -8,6 +8,10 @@ * * SPDX-License-Identifier: EPL-2.0 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -17,6 +21,8 @@ package org.eclipse.jdt.core.dom; import java.util.ArrayList; import java.util.List; +import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil; + /** * Method declaration AST node type. A method declaration * is the union of a method declaration and a constructor declaration. @@ -87,6 +93,13 @@ public class MethodDeclaration extends BodyDeclaration { */ public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY = new SimplePropertyDescriptor(MethodDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$ + + /** + * The "compact constructor" structural property of record node type (type: {@link Boolean}). + * @since 3.20 BETA_JAVA + */ + public static final SimplePropertyDescriptor COMPACT_CONSTRUCTOR_PROPERTY = + new SimplePropertyDescriptor(MethodDeclaration.class, "compactConstructor", boolean.class, OPTIONAL); //$NON-NLS-1$ /** * The "name" structural property of this node type (child type: {@link SimpleName}). @@ -199,6 +212,14 @@ public class MethodDeclaration extends BodyDeclaration { * @since 3.10 */ private static final List PROPERTY_DESCRIPTORS_8_0; + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + * @since 3.20 BETA_JAVA + */ + private static final List PROPERTY_DESCRIPTORS_9_0; static { List propertyList = new ArrayList(10); @@ -242,7 +263,24 @@ public class MethodDeclaration extends BodyDeclaration { addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList); addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList); addProperty(BODY_PROPERTY, propertyList); - PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + + propertyList = new ArrayList(14); + createPropertyList(MethodDeclaration.class, propertyList); + addProperty(JAVADOC_PROPERTY, propertyList); + addProperty(MODIFIERS2_PROPERTY, propertyList); + addProperty(CONSTRUCTOR_PROPERTY, propertyList); + addProperty(TYPE_PARAMETERS_PROPERTY, propertyList); + addProperty(RETURN_TYPE2_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + addProperty(RECEIVER_TYPE_PROPERTY, propertyList); + addProperty(RECEIVER_QUALIFIER_PROPERTY, propertyList); + addProperty(PARAMETERS_PROPERTY, propertyList); + addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList); + addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList); + addProperty(BODY_PROPERTY, propertyList); + addProperty(COMPACT_CONSTRUCTOR_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList); } /** @@ -255,10 +293,28 @@ public class MethodDeclaration extends BodyDeclaration { * @since 3.0 */ public static List propertyDescriptors(int apiLevel) { + return propertyDescriptors(apiLevel, false); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * <code>AST.JLS*</code> constants + * @param previewEnabled the previewEnabled flag + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + * @noreference This method is not intended to be referenced by clients. + * @since 3.20 BETA_JAVA + */ + public static List propertyDescriptors(int apiLevel, boolean previewEnabled) { if (apiLevel == AST.JLS2_INTERNAL) { return PROPERTY_DESCRIPTORS_2_0; } else if (apiLevel < AST.JLS8_INTERNAL) { return PROPERTY_DESCRIPTORS_3_0; + } else if (DOMASTUtil.isRecordDeclarationSupported(apiLevel, previewEnabled)) { + return PROPERTY_DESCRIPTORS_9_0; } else { return PROPERTY_DESCRIPTORS_8_0; } @@ -269,6 +325,13 @@ public class MethodDeclaration extends BodyDeclaration { * Defaults to method. */ private boolean isConstructor = false; + + + /** + * <code>true</code> for a compact constructor in a record, <code>false</code> for a method. + * Defaults to method. + */ + private boolean isCompactConstructor = false; /** * The method name; lazily initialized; defaults to an unspecified, @@ -400,6 +463,11 @@ public class MethodDeclaration extends BodyDeclaration { } @Override + final List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) { + return propertyDescriptors(apiLevel, previewEnabled); + } + + @Override final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) { if (property == MODIFIERS_PROPERTY) { if (get) { @@ -430,10 +498,19 @@ public class MethodDeclaration extends BodyDeclaration { setConstructor(value); return false; } + } else if (property == COMPACT_CONSTRUCTOR_PROPERTY) { + if (get) { + return isCompactConstructor(); + } else { + setCompactConstructor(value); + return false; + } } // allow default implementation to flag the error return super.internalGetSetBooleanProperty(property, get, value); } + + @Override final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { @@ -577,6 +654,9 @@ public class MethodDeclaration extends BodyDeclaration { } else { result.thrownExceptions().addAll(ASTNode.copySubtrees(target, thrownExceptions())); } + if (DOMASTUtil.isRecordDeclarationSupported(this.ast)) { + result.setCompactConstructor(isCompactConstructor()); + } result.setBody( (Block) ASTNode.copySubtree(target, getBody())); return result; @@ -642,6 +722,40 @@ public class MethodDeclaration extends BodyDeclaration { } /** + * Returns whether this declaration declares a constructor or a method. + * + * @return <code>true</code> if this is a compact constructor declaration in a record, + * and <code>false</code> if this is a method declaration + * @since 3.20 BETA_JAVA + * @noreference This method is not intended to be referenced by clients. + * @exception UnsupportedOperationException if this operation is not used in JLS14 + * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false + */ + + public boolean isCompactConstructor() { + supportedOnlyIn14(); + unsupportedWithoutPreviewError(); + return this.isCompactConstructor; + } + + /** + * Sets whether this declaration declares a compact constructor in a record or a method. + * + * @param isCompactConstructor <code>true</code> for a constructor declaration, + * and <code>false</code> for a method declaration + * @since 3.20 BETA_JAVA + * @noreference This method is not intended to be referenced by clients. + * @exception UnsupportedOperationException if this operation is not used in JLS14 + * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false + */ + + public void setCompactConstructor(boolean isCompactConstructor) { + preValueChange(COMPACT_CONSTRUCTOR_PROPERTY); + this.isCompactConstructor = isCompactConstructor; + postValueChange(COMPACT_CONSTRUCTOR_PROPERTY); + } + + /** * Returns the live ordered list of type parameters of this method * declaration (added in JLS3 API). This list is non-empty for parameterized methods. * diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java new file mode 100644 index 0000000000..68a5969b99 --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java @@ -0,0 +1,464 @@ +/******************************************************************************* + * Copyright (c) 2019 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 + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Record declaration AST node type (added in JLS14 API). + * + * <pre> + * RecordDeclaration: + * [ Javadoc ] { ExtendedModifier } <b>record</b> Identifier + * [ <b><</b> TypeParameter <b>></b> ] + * [ Type { <b>,</b> Type } ] + * [ <b>;</b> { RecordBodyDeclaration | <b>;</b> } ] + * <b>}</b> + * </pre> + * The {@link #bodyDeclarations()} list holds the class body declarations + * that appear after the semicolon. + * <p> + * When a Javadoc comment is present, the source + * range begins with the first character of the "/**" comment delimiter. + * When there is no Javadoc comment, the source range begins with the first + * character of the first modifier or annotation (if present), or the + * first character of the "record" keyword (if no + * modifiers or annotations). The source range extends through the last + * character of the "}" token following the body declarations. + * </p> + * + * @since 3.20 BETA_JAVA + * @noinstantiate This class is not intended to be instantiated by clients. + * @noreference This class is not intended to be referenced by clients as it is a part of Java preview feature. + */ +@SuppressWarnings({ "rawtypes", "unchecked" }) +public class RecordDeclaration extends AbstractTypeDeclaration { + + /** + * The "javadoc" structural property of this node type (child type: {@link Javadoc}). + * @since 3.20 BETA_JAVA + */ + public static final ChildPropertyDescriptor JAVADOC_PROPERTY = + internalJavadocPropertyFactory(RecordDeclaration.class); + + /** + * The "modifiers" structural property of this node type (element type: {@link IExtendedModifier}) (added in JLS3 API). + * @since 3.20 BETA_JAVA + */ + public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = + internalModifiers2PropertyFactory(RecordDeclaration.class); + + /** + * The "interface" structural property of this node type (type: {@link Boolean}). + * @since 3.20 BETA_JAVA + */ + public static final SimplePropertyDescriptor INTERFACE_PROPERTY = + new SimplePropertyDescriptor(RecordDeclaration.class, "interface", boolean.class, MANDATORY); //$NON-NLS-1$ + + /** + * The "name" structural property of this node type (child type: {@link SimpleName}). + * @since 3.20 BETA_JAVA + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + internalNamePropertyFactory(RecordDeclaration.class); + + + /** + * The "superInterfaceTypes" structural property of this node type (element type: {@link Type}) (added in JLS3 API). + * @since 3.20 BETA_JAVA + */ + public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY = + new ChildListPropertyDescriptor(RecordDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "typeParameters" structural property of this node type (element type: {@link TypeParameter}) (added in JLS3 API). + * @since 3.20 BETA_JAVA + */ + public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY = + new ChildListPropertyDescriptor(RecordDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "bodyDeclarations" structural property of this node type (element type: {@link BodyDeclaration}) (added in JLS3 API). + * @since 3.20 BETA_JAVA + */ + public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = + internalBodyDeclarationPropertyFactory(RecordDeclaration.class); + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + * @since 3.20 BETA_JAVA + */ + private static final List PROPERTY_DESCRIPTORS; + + static { + + ArrayList propertyList = new ArrayList(8); + createPropertyList(RecordDeclaration.class, propertyList); + addProperty(JAVADOC_PROPERTY, propertyList); + addProperty(MODIFIERS2_PROPERTY, propertyList); + addProperty(INTERFACE_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + addProperty(TYPE_PARAMETERS_PROPERTY, propertyList); + addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList); + addProperty(BODY_DECLARATIONS_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * <code>AST.JLS*</code> constants + + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + * @noreference This method is not intended to be referenced by clients. + * @since 3.20 BETA_JAVA + */ + public static List propertyDescriptors(int apiLevel) { + return propertyDescriptors(apiLevel, false); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * <code>AST.JLS*</code> constants + * @param previewEnabled the previewEnabled flag + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + * @noreference This method is not intended to be referenced by clients. + * @since 3.20 BETA_JAVA + */ + public static List propertyDescriptors(int apiLevel, boolean previewEnabled) { + if (apiLevel == AST.JLS14_INTERNAL && previewEnabled) { + return PROPERTY_DESCRIPTORS; + } + return null; + } + + /** + * The type parameters (element type: {@link TypeParameter}). + * Null in JLS2. Added in JLS3; defaults to an empty list + * (see constructor). + * @since 3.20 BETA_JAVA + */ + private ASTNode.NodeList typeParameters = null; + + + /** + * The superinterface types (element type: {@link Type}). + * Null in JLS2. Added in JLS3; defaults to an empty list + * (see constructor). + * @since 3.20 BETA_JAVA + */ + private ASTNode.NodeList superInterfaceTypes = null; + + /** + * Creates a new AST node for a type declaration owned by the given + * AST. By default, the type declaration is for a class of an + * unspecified, but legal, name; no modifiers; no javadoc; + * no type parameters; no superinterfaces; and an empty list + * of body declarations. + * <p> + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + * </p> + * + * @param ast the AST that is to own this node + * @exception UnsupportedOperationException if this operation is used other than JLS14 + * @exception UnsupportedOperationException if this expression is used with previewEnabled flag as false + */ + RecordDeclaration(AST ast) { + super(ast); + supportedOnlyIn14(); + unsupportedWithoutPreviewError(); + this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY); + this.superInterfaceTypes = new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + @Override + final List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) { + return propertyDescriptors(apiLevel, previewEnabled); + } + + @Override + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == JAVADOC_PROPERTY) { + if (get) { + return getJavadoc(); + } else { + setJavadoc((Javadoc) child); + return null; + } + } + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((SimpleName) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + @Override + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == MODIFIERS2_PROPERTY) { + return modifiers(); + } + if (property == TYPE_PARAMETERS_PROPERTY) { + return typeParameters(); + } + if (property == SUPER_INTERFACE_TYPES_PROPERTY) { + return superInterfaceTypes(); + } + if (property == BODY_DECLARATIONS_PROPERTY) { + return bodyDeclarations(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + @Override + final ChildPropertyDescriptor internalJavadocProperty() { + return JAVADOC_PROPERTY; + } + + @Override + final ChildListPropertyDescriptor internalModifiers2Property() { + return MODIFIERS2_PROPERTY; + } + + @Override + final ChildPropertyDescriptor internalNameProperty() { + return NAME_PROPERTY; + } + + @Override + final ChildListPropertyDescriptor internalBodyDeclarationsProperty() { + return BODY_DECLARATIONS_PROPERTY; + } + + @Override + final int getNodeType0() { + return TYPE_DECLARATION; + } + + @Override + ASTNode clone0(AST target) { + RecordDeclaration result = new RecordDeclaration(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setJavadoc( + (Javadoc) ASTNode.copySubtree(target, getJavadoc())); + result.setName((SimpleName) getName().clone(target)); + result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); + result.typeParameters().addAll( + ASTNode.copySubtrees(target, typeParameters())); + result.superInterfaceTypes().addAll( + ASTNode.copySubtrees(target, superInterfaceTypes())); + result.bodyDeclarations().addAll( + ASTNode.copySubtrees(target, bodyDeclarations())); + return result; + } + + @Override + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + @Override + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getJavadoc()); + acceptChildren(visitor, this.modifiers); + acceptChild(visitor, getName()); + acceptChildren(visitor, this.typeParameters); + acceptChildren(visitor, this.superInterfaceTypes); + acceptChildren(visitor, this.bodyDeclarations); + } + visitor.endVisit(this); + } + + /** + * Returns the live ordered list of type parameters of this type + * declaration (added in JLS3 API). This list is non-empty for parameterized types. + * + * @return the live list of type parameters + * (element type: {@link TypeParameter}) + * @since 3.20 BETA_JAVA + */ + public List typeParameters() { + return this.typeParameters; + } + + + /** + * Returns the live ordered list of superinterfaces of this type + * declaration (added in JLS3 API). For a class declaration, these are the interfaces + * that this class implements; for an interface declaration, + * these are the interfaces that this interface extends. + * + * @return the live list of interface types + * (element type: {@link Type}) + * @since 3.20 BETA_JAVA + */ + public List superInterfaceTypes() { + return this.superInterfaceTypes; + } + + /** + * Returns the ordered list of field declarations of this type + * declaration. For a class declaration, these are the + * field declarations; for an interface declaration, these are + * the constant declarations. + * <p> + * This convenience method returns this node's body declarations + * with non-fields filtered out. Unlike <code>bodyDeclarations</code>, + * this method does not return a live result. + * </p> + * + * @return the (possibly empty) list of field declarations + */ + public FieldDeclaration[] getFields() { + List bd = bodyDeclarations(); + int fieldCount = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + if (it.next() instanceof FieldDeclaration) { + fieldCount++; + } + } + FieldDeclaration[] fields = new FieldDeclaration[fieldCount]; + int next = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + Object decl = it.next(); + if (decl instanceof FieldDeclaration) { + fields[next++] = (FieldDeclaration) decl; + } + } + return fields; + } + + /** + * Returns the ordered list of method declarations of this type + * declaration. + * <p> + * This convenience method returns this node's body declarations + * with non-methods filtered out. Unlike <code>bodyDeclarations</code>, + * this method does not return a live result. + * </p> + * + * @return the (possibly empty) list of method (and constructor) + * declarations + */ + public MethodDeclaration[] getMethods() { + List bd = bodyDeclarations(); + int methodCount = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + if (it.next() instanceof MethodDeclaration) { + methodCount++; + } + } + MethodDeclaration[] methods = new MethodDeclaration[methodCount]; + int next = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + Object decl = it.next(); + if (decl instanceof MethodDeclaration) { + methods[next++] = (MethodDeclaration) decl; + } + } + return methods; + } + + /** + * Returns the ordered list of member type declarations of this type + * declaration. + * <p> + * This convenience method returns this node's body declarations + * with non-types filtered out. Unlike <code>bodyDeclarations</code>, + * this method does not return a live result. + * </p> + * + * @return the (possibly empty) list of member type declarations + */ + public RecordDeclaration[] getTypes() { + List bd = bodyDeclarations(); + int typeCount = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + if (it.next() instanceof RecordDeclaration) { + typeCount++; + } + } + RecordDeclaration[] memberTypes = new RecordDeclaration[typeCount]; + int next = 0; + for (Iterator it = bd.listIterator(); it.hasNext(); ) { + Object decl = it.next(); + if (decl instanceof RecordDeclaration) { + memberTypes[next++] = (RecordDeclaration) decl; + } + } + return memberTypes; + } + + @Override + ITypeBinding internalResolveBinding() { + return this.ast.getBindingResolver().resolveType(this); + } + + @Override + int memSize() { + return super.memSize() + 6 * 4; + } + + @Override + int treeSize() { + return memSize() + + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize()) + + (this.modifiers == null ? 0 : this.modifiers.listSize()) + + (this.typeName == null ? 0 : getName().treeSize()) + + (this.typeParameters == null ? 0 : this.typeParameters.listSize()) + + (this.superInterfaceTypes == null ? 0 : this.superInterfaceTypes.listSize()) + + this.bodyDeclarations.listSize(); + } + + @Override + SimplePropertyDescriptor internalModifiersProperty() { + // node type does not exist before JLS 14 + return null; + } + +} + diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java index c8bdbb7cc5..68d4661722 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java @@ -1303,6 +1303,51 @@ public class NaiveASTFlattener extends ASTVisitor { } @Override + public boolean visit(RecordDeclaration node) { + if (node.getJavadoc() != null) { + node.getJavadoc().accept(this); + } + printIndent(); + printModifiers(node.modifiers()); + this.buffer.append("record ");//$NON-NLS-1$ + node.getName().accept(this); + this.buffer.append(" ");//$NON-NLS-1$ + if (!node.superInterfaceTypes().isEmpty()) { + this.buffer.append("implements ");//$NON-NLS-1$ + for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) { + Type t = (Type) it.next(); + t.accept(this); + if (it.hasNext()) { + this.buffer.append(", ");//$NON-NLS-1$ + } + } + this.buffer.append(" ");//$NON-NLS-1$ + } + if (!node.typeParameters().isEmpty()) { + this.buffer.append("<");//$NON-NLS-1$ + for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) { + TypeParameter t = (TypeParameter) it.next(); + t.accept(this); + if (it.hasNext()) { + this.buffer.append(",");//$NON-NLS-1$ + } + } + this.buffer.append(">");//$NON-NLS-1$ + } + this.buffer.append("{");//$NON-NLS-1$ + if (!node.bodyDeclarations().isEmpty()) { + this.buffer.append("; ");//$NON-NLS-1$ + for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { + BodyDeclaration d = (BodyDeclaration) it.next(); + d.accept(this); + // other body declarations include trailing punctuation + } + } + this.buffer.append("}\n");//$NON-NLS-1$ + return false; + } + + @Override public boolean visit(RequiresDirective node) { printIndent(); this.buffer.append("requires");//$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java index cc0ed65731..e4ce272e3f 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java @@ -850,6 +850,26 @@ public class ASTRewriteFlattener extends ASTVisitor { } @Override + public boolean visit(RecordDeclaration node) { + ASTNode javadoc= getChildNode(node, RecordDeclaration.JAVADOC_PROPERTY); + if (javadoc != null) { + javadoc.accept(this); + } + visitList(node, RecordDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); + this.result.append("enum ");//$NON-NLS-1$ + getChildNode(node, RecordDeclaration.NAME_PROPERTY).accept(this); + this.result.append(' '); + visitList(node, RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, String.valueOf(','), "implements ", Util.EMPTY_STRING); //$NON-NLS-1$ + this.result.append(' '); + visitList(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, String.valueOf(','), String.valueOf('<'), String.valueOf('>')); + + this.result.append('{'); + visitList(node, RecordDeclaration.BODY_DECLARATIONS_PROPERTY, Util.EMPTY_STRING, String.valueOf(';'), Util.EMPTY_STRING); + this.result.append('}'); + return false; + } + + @Override public boolean visit(RequiresDirective node) { this.result.append("requires "); //$NON-NLS-1$ visitList(node, RequiresDirective.MODIFIERS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' ')); diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java new file mode 100644 index 0000000000..9071686042 --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2019 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 + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.internal.core.dom.util; + +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTNode; + +public class DOMASTUtil { + + /** + * Validates if the given <code>AST</code> supports the provided <code>nodeType</code>. This API checks for node + * types supported from JLS 14 onwards and will return <code>true></code> for nodes added before JLS14. + * + * @param ast + * the AST to be evaluated + * @param nodeType + * the node type constant indicating a node of type to be evaluated + * @return <code>true</code> if the given <code>AST</code> supports the provided <code>nodeType</code> else + * <code>false</code> + * @see ASTNode#getNodeType() + * @since 3.20 BETA_JAVA + */ + private static boolean isNodeTypeSupportedinAST(AST ast, int nodeType) { + return isNodeTypeSupportedinAST(ast.apiLevel(), ast.isPreviewEnabledSet(), nodeType); + } + + /** + * Validates if the given <code>apiLevel</code> and <code>previewEnabled</code> supports the provided + * <code>nodeType</code>. This API checks for node types supported from JLS 14 onwards and will return + * <code>true></code> for nodes added before JLS14. + * + * @param apiLevel + * the level to be checked + * @param previewEnabled + * the preview feature to be considered + * @param nodeType + * the node type constant indicating a node of type to be evaluated + * @return <code>true</code> if the given <code>AST</code> supports the provided <code>nodeType</code> else + * <code>false</code> + * @see ASTNode#getNodeType() + * @since 3.20 BETA_JAVA + */ + private static boolean isNodeTypeSupportedinAST(int apiLevel, boolean previewEnabled, int nodeType) { + switch (nodeType) { + case ASTNode.SWITCH_EXPRESSION: + case ASTNode.YIELD_STATEMENT: + return apiLevel >= AST.JLS14; + case ASTNode.TEXT_BLOCK: + case ASTNode.RECORD_DECLARATION: + return isPreviewEnabled(apiLevel, previewEnabled); + } + return false; + } + + private static boolean isPreviewEnabled(int apiLevel, boolean previewEnabled) { + return (apiLevel == AST.JLS14 && previewEnabled); + } + + public static boolean isSwitchExpressionSupported(AST ast) { + return isNodeTypeSupportedinAST(ast, ASTNode.SWITCH_EXPRESSION); + } + + public static boolean isYieldStatementSupported(AST ast) { + return isNodeTypeSupportedinAST(ast, ASTNode.YIELD_STATEMENT); + } + + public static boolean isTextBlockSupported(AST ast) { + return isNodeTypeSupportedinAST(ast, ASTNode.TEXT_BLOCK); + } + + public static boolean isRecordDeclarationSupported(AST ast) { + return isNodeTypeSupportedinAST(ast, ASTNode.RECORD_DECLARATION); + } + + public static boolean isRecordDeclarationSupported(int apiLevel, boolean previewEnabled) { + return isNodeTypeSupportedinAST(apiLevel, previewEnabled, ASTNode.RECORD_DECLARATION); + } + +} |