Skip to content

Commit

Permalink
[23] DOM Support for implicitly declared classes (#2996)
Browse files Browse the repository at this point in the history
* Added ASTRewrite support(Unit test & Rewrite) and ASTConverter unit test

* Incorporated the code review changes
  • Loading branch information
subyssurendran666 authored Oct 15, 2024
1 parent 74d062b commit 26e33c7
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<MethodDeclaration> 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<ASTNode> 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());

}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
13 changes: 13 additions & 0 deletions org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 26e33c7

Please sign in to comment.