From 26e33c7915827b9f67aeafe20b578a78811480c4 Mon Sep 17 00:00:00 2001 From: Suby S Surendran Date: Tue, 15 Oct 2024 16:24:12 +0530 Subject: [PATCH] [23] DOM Support for implicitly declared classes (#2996) * Added ASTRewrite support(Unit test & Rewrite) and ASTConverter unit test * Incorporated the code review changes --- .../core/tests/dom/ASTConverter_23Test.java | 30 ++ ...TRewritingImplicitTypeDeclarationTest.java | 288 ++++++++++++++++++ .../rewrite/describing/ASTRewritingTest.java | 11 + .../dom/org/eclipse/jdt/core/dom/AST.java | 13 + .../internal/core/dom/NaiveASTFlattener.java | 19 ++ .../core/dom/rewrite/ASTRewriteAnalyzer.java | 14 + .../core/dom/rewrite/ASTRewriteFlattener.java | 11 + 7 files changed, 386 insertions(+) create mode 100644 org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingImplicitTypeDeclarationTest.java diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java index 67d879e4bd9..9ceaf5eba69 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_23Test.java @@ -20,8 +20,12 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ImplicitTypeDeclaration; import org.eclipse.jdt.core.dom.ImportDeclaration; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Modifier; public class ASTConverter_23Test extends ConverterTestSetup { @@ -103,4 +107,30 @@ void m() { assertEquals("Incorrect name", "java.lang.System.out", imp.getName().toString()); } } + + public void test002() throws CoreException { + String contents = """ + /** */ + void main() { + System.out.println("Eclipse"); + } + """; + this.workingCopy = getWorkingCopy("/Converter_23/src/X.java", true/*resolve*/); + ASTNode node = buildAST(contents, this.workingCopy); + assertEquals("Wrong type of statement", ASTNode.COMPILATION_UNIT, node.getNodeType()); + CompilationUnit compilationUnit = (CompilationUnit) node; + ImplicitTypeDeclaration implicitTypeDeclaration = (ImplicitTypeDeclaration) compilationUnit.types().get(0); + assertEquals("Not an ImplicitTypeDeclaration Type", implicitTypeDeclaration.getNodeType(), ASTNode.UNNAMED_CLASS); + assertEquals("Not an ImplicitTypeDeclaration Name Type", implicitTypeDeclaration.getName().getNodeType(), ASTNode.SIMPLE_NAME); + assertEquals("Identifier is not empty String", implicitTypeDeclaration.getName().getIdentifier(), ""); + MethodDeclaration bodyDeclaration = (MethodDeclaration) implicitTypeDeclaration.bodyDeclarations().get(0); + assertEquals("Not a Method Declaration", bodyDeclaration.getNodeType(), ASTNode.METHOD_DECLARATION); + assertEquals("Method Declaration start is not one", bodyDeclaration.getStartPosition(), 1); + Javadoc javaDoc = bodyDeclaration.getJavadoc(); + assertEquals("Not a JavaDoc", javaDoc.getNodeType(), ASTNode.JAVADOC); + assertEquals("JavaDoc startPosition is not One", javaDoc.getStartPosition(), 1); + Block block = bodyDeclaration.getBody(); + assertEquals("Not a Block", block.getNodeType(), ASTNode.BLOCK); + assertEquals("Block startPosition is not correct", block.getStartPosition(), 21); + } } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingImplicitTypeDeclarationTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingImplicitTypeDeclarationTest.java new file mode 100644 index 00000000000..7c8a6170115 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingImplicitTypeDeclarationTest.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2024 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.util.List; +import junit.framework.Test; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; + +public class ASTRewritingImplicitTypeDeclarationTest extends ASTRewritingTest{ + + public ASTRewritingImplicitTypeDeclarationTest(String name, int apiLevel) { + super(name, apiLevel); + } + + public static Test suite() { + return createSuite(ASTRewritingImplicitTypeDeclarationTest.class, 23); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (this.apiLevel == AST.JLS23 ) { + this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_23); + this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_23); + this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_23); + this.project1.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED); + } + } + + public void test001() throws Exception { + AST ast = AST.newAST(AST.JLS23, true); + // Create CompilationUnit + CompilationUnit compilationUnit = ast.newCompilationUnit(); + + ImplicitTypeDeclaration implicitTypeDeclaration = ast.newImplicitTypeDeclaration(); + + Javadoc javaDoc= ast.newJavadoc(); + TextElement textElem= ast.newTextElement(); + textElem.setText("Hello"); + TagElement tagElement= ast.newTagElement(); + tagElement.fragments().add(textElem); + javaDoc.tags().add(tagElement); + implicitTypeDeclaration.setJavadoc(javaDoc); + + QualifiedName qualifiedName = ast.newQualifiedName(ast.newName("System"), ast.newSimpleName("out")); + MethodInvocation methodInvocation = ast.newMethodInvocation(); + methodInvocation.setExpression(qualifiedName); + methodInvocation.setName(ast.newSimpleName("println")); + + StringLiteral literal = ast.newStringLiteral(); + literal.setLiteralValue("Eclipse"); + methodInvocation.arguments().add(literal); + ExpressionStatement expressionStatement = ast.newExpressionStatement(methodInvocation); + + Block block= ast.newBlock(); + block.statements().add(expressionStatement); + MethodDeclaration methodDeclaration = ast.newMethodDeclaration(); + methodDeclaration.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); + methodDeclaration.setName(ast.newSimpleName("main")); + methodDeclaration.setBody(block); + implicitTypeDeclaration.bodyDeclarations().add(methodDeclaration); + // Add Implicity Type class to compilation unit + compilationUnit.types().add(implicitTypeDeclaration); + + StringBuilder buf = new StringBuilder(); + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append(" void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append(" }\n"); + + assertEqualString(compilationUnit.toString(), buf.toString()); + } + + //javaDoc + public void test002() throws Exception { + AST ast = AST.newAST(AST.JLS23, true); + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuilder buf = new StringBuilder(); + buf= new StringBuilder(); + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append("}\n"); + + ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null); + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + + ImplicitTypeDeclaration implicitTypeDeclaration= findImplicitDeclaration(astRoot, ""); + List methodDeclarationsList = implicitTypeDeclaration.bodyDeclarations(); + MethodDeclaration methodDeclaration = methodDeclarationsList.get(0); + { + + Javadoc javaDoc = methodDeclaration.getJavadoc(); + + Javadoc newJavaDoc= ast.newJavadoc(); + TextElement textElem= ast.newTextElement(); + textElem.setText("Eclipse"); + TagElement tagElement= ast.newTagElement(); + tagElement.fragments().add(textElem); + newJavaDoc.tags().add(tagElement); + + rewrite.replace(javaDoc, newJavaDoc, null); + } + + String preview = evaluateRewrite(cu, rewrite); + buf= new StringBuilder(); + + buf.append("/**\n"); + buf.append(" * Eclipse\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + { + Javadoc javaDoc = methodDeclaration.getJavadoc(); + Javadoc newJavaDoc = null; + + rewrite.replace(javaDoc, newJavaDoc, null); + } + + preview = evaluateRewrite(cu, rewrite); + buf= new StringBuilder(); + + buf.append("void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + } + + //adding more MEthodDeclaration + public void test003() throws Exception { + AST ast = AST.newAST(AST.JLS23, true); + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuilder buf = new StringBuilder(); + buf= new StringBuilder(); + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append("}\n"); + + ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null); + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + ImplicitTypeDeclaration implicitTypeDeclaration= findImplicitDeclaration(astRoot, ""); + { + MethodInvocation methodInvocation = ast.newMethodInvocation(); + methodInvocation.setName(ast.newSimpleName("println")); + + StringLiteral literal = ast.newStringLiteral(); + literal.setLiteralValue("abc"); + + QualifiedName qualifiedName = ast.newQualifiedName(ast.newName("System"), ast.newSimpleName("out")); + + methodInvocation.setExpression(qualifiedName); + methodInvocation.arguments().add(literal); + + ExpressionStatement expressionStatement = ast.newExpressionStatement(methodInvocation); + + Block block = ast.newBlock(); + block.statements().add(expressionStatement); + + MethodDeclaration methodDeclaration = ast.newMethodDeclaration(); + methodDeclaration.setBody(block); + methodDeclaration.setName(ast.newSimpleName("abc")); + methodDeclaration.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); + + ListRewrite listRewrite= rewrite.getListRewrite(implicitTypeDeclaration, ImplicitTypeDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.insertAt(methodDeclaration, 1, null); + } + + String preview = evaluateRewrite(cu, rewrite); + buf= new StringBuilder(); + + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"Eclipse\");\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("void abc() {\n"); + buf.append(" System.out.println(\"abc\");\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + } + public void test004() throws Exception { + AST ast = AST.newAST(AST.JLS23, true); + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuilder buf = new StringBuilder(); + buf= new StringBuilder(); + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"main\");\n"); + buf.append("}\n"); + buf.append("void abc(){\n"); + buf.append(" System.out.println(\"abc\");\n"); + buf.append("}\n"); + + ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null); + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + ImplicitTypeDeclaration implicitTypeDeclaration= findImplicitDeclaration(astRoot, ""); + List bodyDeclaration = implicitTypeDeclaration.bodyDeclarations(); + System.out.println("sasi"); + { + + rewrite.remove(bodyDeclaration.get(1), null);//remove one method + + MethodInvocation methodInvocation = ast.newMethodInvocation(); + methodInvocation.setName(ast.newSimpleName("println")); + + StringLiteral literal = ast.newStringLiteral(); + literal.setLiteralValue("xyz"); + + QualifiedName qualifiedName = ast.newQualifiedName(ast.newName("System"), ast.newSimpleName("out")); + + methodInvocation.setExpression(qualifiedName); + methodInvocation.arguments().add(literal); + + ExpressionStatement expressionStatement = ast.newExpressionStatement(methodInvocation); + + Block block = ast.newBlock(); + block.statements().add(expressionStatement); + + MethodDeclaration methodDeclaration = ast.newMethodDeclaration(); + methodDeclaration.setBody(block); + methodDeclaration.setName(ast.newSimpleName("xyz")); + methodDeclaration.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); + + ListRewrite listRewrite= rewrite.getListRewrite(implicitTypeDeclaration, ImplicitTypeDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.insertAt(methodDeclaration, 1, null); + + String preview = evaluateRewrite(cu, rewrite); + buf= new StringBuilder(); + + buf.append("/** \n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("void main(){\n"); + buf.append(" System.out.println(\"main\");\n"); + buf.append("}\n"); + buf.append("void xyz() {\n"); + buf.append(" System.out.println(\"xyz\");\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + } + +} \ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java index dcfc5187067..728508b8534 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java @@ -446,4 +446,15 @@ protected static MethodDeclaration createNewMethod(AST ast, String name, boolean return decl; } + public static ImplicitTypeDeclaration findImplicitDeclaration(CompilationUnit astRoot, String simpleTypeName) { + List types= astRoot.types(); + for (int i= 0; i < types.size(); i++) { + ImplicitTypeDeclaration elem= (ImplicitTypeDeclaration) types.get(i); + if (simpleTypeName.equals(elem.getName().getIdentifier())) { + return elem; + } + } + return null; + } + } 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 54c4790a500..fddc84e74f8 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 @@ -3189,6 +3189,19 @@ public TryStatement newTryStatement() { return new TryStatement(this); } + /** + * Creates an unparented class declaration node owned by this AST. + * The name of the class is an unspecified, but legal, name; + * no modifiers; no doc comment; no superclass or superinterfaces; + * and an empty class body. + * + * @return a new unparented type declaration node + * @since 3.40 + */ + public ImplicitTypeDeclaration newImplicitTypeDeclaration() { + return new ImplicitTypeDeclaration(this); + } + /** * Creates an unparented class declaration node owned by this AST. * The name of the class is an unspecified, but legal, name; 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 2b65c3a90d6..ffc404a2c9d 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 @@ -1912,6 +1912,25 @@ public boolean visit(TryStatement node) { return false; } + @Override + public boolean visit(ImplicitTypeDeclaration node) { + //javaDoc + if (node.getJavadoc() != null) { + node.getJavadoc().accept(this); + } + + //bodyDeclaration + this.indent++; + for (Object element : node.bodyDeclarations()) { + BodyDeclaration d = (BodyDeclaration) element; + d.accept(this); + } + this.indent--; + printIndent(); + + return false; + } + @Override public boolean visit(TypeDeclaration node) { if (node.getJavadoc() != null) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java index 76c09181b52..94d00d72b08 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java @@ -1849,6 +1849,20 @@ public boolean visit(CompilationUnit node) { return false; } + @Override + public boolean visit(ImplicitTypeDeclaration node) { + if (!hasChildrenChanges(node)) { + return doVisitUnchangedChildren(node); + } + //javaDoc + rewriteJavadoc(node, ImplicitTypeDeclaration.JAVADOC_PROPERTY); + + int startIndent= getIndent(node.getStartPosition()) + 1; + int startPos= node.getStartPosition(); + rewriteParagraphList(node, ImplicitTypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2); + return false; + } + @Override public boolean visit(TypeDeclaration node) { if (!hasChildrenChanges(node)) { 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 3326d9fd4c0..d53c75bc0cf 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 @@ -1209,6 +1209,17 @@ public boolean visit(TryStatement node) { return false; } + @Override + public boolean visit(ImplicitTypeDeclaration node) { + ASTNode javadoc= getChildNode(node, TypeDeclaration.JAVADOC_PROPERTY); + if (javadoc != null) { + javadoc.accept(this); + } + + visitList(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY, null); + return false; + } + @Override public boolean visit(TypeDeclaration node) { int apiLevel= node.getAST().apiLevel();