| /******************************************************************************* |
| * Copyright (c) 2000, 2021 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.tests.rewrite.describing; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.PrimitiveType; |
| import org.eclipse.jdt.core.dom.RecordDeclaration; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; |
| import org.eclipse.jdt.core.tests.model.AbstractJavaModelTests; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.text.edits.TextEdit; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| /** |
| * Tests for ASTRewrite. Subclasses must have 2 constructors that forward to |
| * constructors with the same signature as this class's constructors. |
| * |
| * Test methods can end with: |
| * <ul> |
| * <li>"_since_<i>n</i>", where <i>n</i> is an AST.JLS* constant value: |
| * test will run for all AST levels >= <i>n</i> |
| * </li> |
| * <li>"_only_<i>a</i>_<i>b</i>...", where <i>a</i>, <i>b</i>, ... are AST.JLS* constant values: |
| * test will run for all specified AST levels |
| * </li> |
| * </ul> |
| */ |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| public class ASTRewritingTest extends AbstractJavaModelTests { |
| |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS2_INTERNAL = AST.JLS2; |
| |
| /** |
| * Internal synonym for deprecated constant AST.JSL3 |
| * to alleviate deprecation warnings. |
| * @deprecated |
| */ |
| private static final int JLS3_INTERNAL = AST.JLS3; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS4_INTERNAL = AST.JLS4; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS8_INTERNAL = AST.JLS8; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS9_INTERNAL = AST.JLS9; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS10_INTERNAL = AST.JLS10; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS14_INTERNAL = AST.JLS14; |
| |
| /** @deprecated using deprecated code */ |
| private final static int JLS15_INTERNAL = AST.JLS15; |
| |
| private final static int JLS16_INTERNAL = AST.JLS16; |
| |
| private final static int[] JLS_LEVELS = { JLS2_INTERNAL, JLS3_INTERNAL, JLS4_INTERNAL, JLS8_INTERNAL, JLS9_INTERNAL, JLS10_INTERNAL, JLS14_INTERNAL, JLS15_INTERNAL, JLS16_INTERNAL}; |
| |
| private static final String ONLY_AST_STRING = "_only"; |
| private static final String SINCE_AST_STRING = "_since"; |
| private static final String STRING_ = "_"; |
| |
| protected int apiLevel; |
| |
| protected IJavaProject project1; |
| protected IPackageFragmentRoot sourceFolder; |
| |
| /** @deprecated using deprecated code */ |
| public String getName() { |
| String name = super.getName() + " - JLS" + this.apiLevel; |
| return name; |
| } |
| |
| public ASTRewritingTest(String name) { |
| super(name.substring(0, name.indexOf(" - JLS"))); |
| name.indexOf(" - JLS"); |
| this.apiLevel = Integer.parseInt(name.substring(name.indexOf(" - JLS") + 6)); |
| } |
| |
| /** |
| * Creates an instance of a test at a particular AST level. All sub tests of ASTRewritingTest must have a constructor |
| * with the specified parameters. |
| * |
| * @param name name of the test method |
| * @param apiLevel The JLS level |
| */ |
| public ASTRewritingTest(String name, int apiLevel) { |
| super(name); |
| this.apiLevel = apiLevel; |
| } |
| |
| public static Test suite() { |
| TestSuite suite= new TestSuite(ASTRewritingTest.class.getName()); |
| |
| |
| suite.addTest(ASTRewritingExpressionsTest.suite()); |
| suite.addTest(ASTRewritingInsertBoundTest.suite()); |
| suite.addTest(ASTRewritingMethodDeclTest.suite()); |
| suite.addTest(ASTRewritingMoveCodeTest.suite()); |
| suite.addTest(ASTRewritingStatementsTest.suite()); |
| suite.addTest(ASTRewritingSwitchExpressionsTest.suite()); |
| |
| suite.addTest(ASTRewritingTrackingTest.suite()); |
| suite.addTest(ASTRewritingJavadocTest.suite()); |
| suite.addTest(ASTRewritingTypeAnnotationsTest.suite()); |
| suite.addTest(ASTRewritingTypeDeclTest.suite()); |
| suite.addTest(ASTRewritingGroupNodeTest.suite()); |
| suite.addTest(ASTRewritingRevertTest.suite()); |
| suite.addTest(LineCommentOffsetsTest.suite()); |
| suite.addTest(ASTRewritingWithStatementsRecoveryTest.suite()); |
| suite.addTest(ASTRewritePropertyTest.suite()); |
| suite.addTest(ASTRewritingPackageDeclTest.suite()); |
| suite.addTest(ASTRewritingLambdaExpressionTest.suite()); |
| suite.addTest(ASTRewritingReferenceExpressionTest.suite()); |
| suite.addTest(ASTRewritingRecordDeclarationTest.suite()); |
| suite.addTest(SourceModifierTest.suite()); |
| suite.addTest(ImportRewriteTest.suite()); |
| suite.addTest(ImportRewrite18Test.suite()); |
| suite.addTest(ImportRewrite_RecordTest.suite()); |
| |
| return suite; |
| } |
| |
| /** |
| * Creates a test suite according to the rules in {@link ASTRewritingTest}. |
| * |
| * @param testClass subclass of ASTRewritingTest |
| * @return test suite that runs all tests with all supported AST levels |
| */ |
| protected static TestSuite createSuite(Class testClass) { |
| return createSuite(testClass, -1); |
| } |
| |
| /** |
| * Creates a test suite according to the rules in {@link ASTRewritingTest}. |
| * |
| * @param testClass subclass of ASTRewritingTest |
| * @param classSince smallest supported AST level for this test class, or -1 to support all levels |
| * @return test suite that runs all tests with all supported AST levels |
| */ |
| protected static TestSuite createSuite(Class testClass, int classSince) { |
| TestSuite suite = new TestSuite(testClass.getName()); |
| try { |
| Method[] methods = testClass.getMethods(); |
| Constructor cons = testClass.getConstructor(new Class[]{String.class, int.class}); |
| for (int i = 0, max = methods.length; i < max; i++) { |
| String name = methods[i].getName(); |
| if (name.startsWith("test")) { //$NON-NLS-1$ |
| |
| int index = name.indexOf(ONLY_AST_STRING); |
| if (index != -1) { |
| String suffix = name.substring(index + ONLY_AST_STRING.length() + 1); |
| String[] levels = suffix.split(STRING_); |
| for (int l= 0; l < levels.length; l++) { |
| suite.addTest((Test) cons.newInstance(new Object[]{name, Integer.valueOf(levels[l])})); |
| } |
| |
| } else { |
| int since = -1; |
| index = name.indexOf(SINCE_AST_STRING); |
| if (index != -1) { |
| String suffix = name.substring(index + SINCE_AST_STRING.length() + 1); |
| since = Integer.parseInt(suffix); |
| } |
| for (int j= 0; j < JLS_LEVELS.length; j++) { |
| int level = JLS_LEVELS[j]; |
| if (level >= since && level >= classSince) { |
| suite.addTest((Test) cons.newInstance(new Object[]{name, Integer.valueOf(level)})); |
| } |
| } |
| } |
| } |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); // In the unlikely case, can't do much |
| } |
| return suite; |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| IJavaProject proj= createProject("P", JavaCore.VERSION_1_5); |
| |
| this.project1 = proj; |
| this.sourceFolder = getPackageFragmentRoot("P", "src"); |
| } |
| |
| @SuppressWarnings("deprecation") |
| protected void setUpProjectAbove14() throws Exception { |
| if (this.apiLevel == AST_INTERNAL_JLS14 ) { |
| this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_14); |
| this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_14); |
| this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_14); |
| } |
| setUpProjectAbove15(); |
| } |
| |
| @SuppressWarnings("deprecation") |
| protected void setUpProjectAbove15() throws Exception { |
| if (this.apiLevel == AST_INTERNAL_JLS15 ) { |
| this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_15); |
| this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_15); |
| this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_15); |
| } |
| setUpProjectAbove16(); |
| } |
| |
| protected void setUpProjectAbove16() throws Exception { |
| if (this.apiLevel == AST_INTERNAL_JLS16 ) { |
| this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_16); |
| this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_16); |
| this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_16); |
| } |
| } |
| |
| protected IJavaProject createProject(String projectName, String complianceVersion) throws CoreException { |
| IJavaProject proj = createJavaProject(projectName, new String[] {"src"}, "bin"); |
| proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE); |
| proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); |
| proj.setOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES, DefaultCodeFormatterConstants.TRUE); |
| proj.setOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH, DefaultCodeFormatterConstants.TRUE); |
| proj.setOption(JavaCore.COMPILER_COMPLIANCE, complianceVersion); |
| proj.setOption(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR); |
| proj.setOption(JavaCore.COMPILER_SOURCE, complianceVersion); |
| proj.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, complianceVersion); |
| return proj; |
| } |
| @Override |
| protected void tearDown() throws Exception { |
| deleteProject("P"); |
| super.tearDown(); |
| } |
| |
| protected CompilationUnit createAST(ICompilationUnit cu) { |
| return createAST(this.apiLevel, cu, false, false); |
| } |
| protected CompilationUnit createAST(ICompilationUnit cu, boolean statementsRecovery) { |
| return createAST(this.apiLevel, cu, false, statementsRecovery); |
| } |
| protected CompilationUnit createAST(ICompilationUnit cu, boolean resolveBindings, boolean statementsRecovery) { |
| return createAST(this.apiLevel, cu, resolveBindings, statementsRecovery); |
| } |
| |
| protected CompilationUnit createAST(int JLSLevel, ICompilationUnit cu, boolean resolveBindings, boolean statementsRecovery) { |
| ASTParser parser= ASTParser.newParser(JLSLevel); |
| parser.setSource(cu); |
| parser.setResolveBindings(resolveBindings); |
| parser.setStatementsRecovery(statementsRecovery); |
| return (CompilationUnit) parser.createAST(null); |
| } |
| |
| protected String evaluateRewrite(ICompilationUnit cu, ASTRewrite rewrite) throws Exception { |
| Document document1= new Document(cu.getSource()); |
| TextEdit res= rewrite.rewriteAST(document1, cu.getJavaProject().getOptions(true)); |
| res.apply(document1); |
| String content1= document1.get(); |
| |
| Document document2= new Document(cu.getSource()); |
| TextEdit res2= rewrite.rewriteAST(); |
| res2.apply(document2); |
| String content2= document2.get(); |
| |
| assertEquals(content1, content2); |
| |
| return content1; |
| } |
| |
| |
| public static void assertEqualString(String actual, String expected) { |
| StringAsserts.assertEqualString(actual, expected); |
| } |
| |
| public static TypeDeclaration findTypeDeclaration(CompilationUnit astRoot, String simpleTypeName) { |
| return (TypeDeclaration) findAbstractTypeDeclaration(astRoot, simpleTypeName); |
| } |
| |
| public static AbstractTypeDeclaration findAbstractTypeDeclaration(CompilationUnit astRoot, String simpleTypeName) { |
| List types= astRoot.types(); |
| for (int i= 0; i < types.size(); i++) { |
| AbstractTypeDeclaration elem= (AbstractTypeDeclaration) types.get(i); |
| if (simpleTypeName.equals(elem.getName().getIdentifier())) { |
| return elem; |
| } |
| } |
| return null; |
| } |
| |
| public static MethodDeclaration findMethodDeclaration(TypeDeclaration typeDecl, String methodName) { |
| MethodDeclaration[] methods= typeDecl.getMethods(); |
| for (int i= 0; i < methods.length; i++) { |
| if (methodName.equals(methods[i].getName().getIdentifier())) { |
| return methods[i]; |
| } |
| } |
| return null; |
| } |
| |
| public static MethodDeclaration findMethodDeclaration(RecordDeclaration typeDecl, String methodName) { |
| MethodDeclaration[] methods= typeDecl.getMethods(); |
| for (int i= 0; i < methods.length; i++) { |
| if (methodName.equals(methods[i].getName().getIdentifier())) { |
| return methods[i]; |
| } |
| } |
| return null; |
| } |
| |
| protected static SingleVariableDeclaration createNewParam(AST ast, String name) { |
| SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); |
| newParam.setType(ast.newPrimitiveType(PrimitiveType.FLOAT)); |
| newParam.setName(ast.newSimpleName(name)); |
| return newParam; |
| } |
| |
| /** @deprecated using deprecated code */ |
| private static void setModifiers(BodyDeclaration bodyDeclaration, int modifiers) { |
| bodyDeclaration.setModifiers(modifiers); |
| } |
| |
| /** @deprecated using deprecated code */ |
| private static void setReturnType(MethodDeclaration methodDeclaration, Type type) { |
| methodDeclaration.setReturnType(type); |
| } |
| |
| protected static FieldDeclaration createNewField(AST ast, String name) { |
| VariableDeclarationFragment frag= ast.newVariableDeclarationFragment(); |
| frag.setName(ast.newSimpleName(name)); |
| FieldDeclaration newFieldDecl= ast.newFieldDeclaration(frag); |
| if (ast.apiLevel() == JLS2_INTERNAL) { |
| setModifiers(newFieldDecl, Modifier.PRIVATE); |
| } else { |
| newFieldDecl.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD)); |
| } |
| newFieldDecl.setType(ast.newPrimitiveType(PrimitiveType.DOUBLE)); |
| return newFieldDecl; |
| } |
| |
| protected static MethodDeclaration createNewMethod(AST ast, String name, boolean isAbstract) { |
| MethodDeclaration decl= ast.newMethodDeclaration(); |
| decl.setName(ast.newSimpleName(name)); |
| if (ast.apiLevel() == JLS2_INTERNAL) { |
| setModifiers(decl, isAbstract ? (Modifier.ABSTRACT | Modifier.PRIVATE) : Modifier.PRIVATE); |
| setReturnType(decl, ast.newPrimitiveType(PrimitiveType.VOID)); |
| } else { |
| decl.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD)); |
| if (isAbstract) { |
| decl.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD)); |
| } |
| decl.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); |
| } |
| SingleVariableDeclaration param= ast.newSingleVariableDeclaration(); |
| param.setName(ast.newSimpleName("str")); |
| param.setType(ast.newSimpleType(ast.newSimpleName("String"))); |
| decl.parameters().add(param); |
| decl.setBody(isAbstract ? null : ast.newBlock()); |
| return decl; |
| } |
| |
| } |