JDT實際上是將Java代碼構建成一個基于DOM結構的抽象語法樹AST(Abstract Syntax Tree )。代碼中的每個部分都對應一個ASTNode,許多的ASTNode就構成了這個抽象的語法樹。Java Class一般對應Compilation Unit node,該節點也是AST樹上的頂點。創建一個AST如下:
java 代碼
- ASTParser parser = ASTParser.newParser(AST.JLS3);
- parser.setSource("".toCharArray());
- CompilationUnit unit = (CompilationUnit) parser.createAST(null);
- unit.recordModifications();
- AST ast = unit.getAST();
其中createAST,當parse需要較長時間時,可以采用createAST(new NullProgressMonitor()),否則直接傳null即可。
recordModifications()用于記錄節點的變動,比如修改、刪除等,當需要對AST樹進行變動操作時,必須要預先調用這個方法。
比較重要的是:一個AST樹上的所有節點必須都屬于該AST。不允許直接將其他AST樹上的節點添加該AST樹上。否則會拋出java.lang.IllegalArgumentException異常。須使用ASTNode.copySubtree(AST target, ASTNode node)返回一個目標樹的深度拷貝,才能進行添加操作。例如:
java 代碼
- ASTParser parser = ASTParser.newParser(AST.JLS3);
- parser.setSource("".toCharArray());
- CompilationUnit targetRoot= (CompilationUnit) parser.createAST(null);
- targetRoot.recordModifications();
- parser.setSource("class T{}”".toCharArray());
- CompilationUnit srcRoot= (CompilationUnit) parser.createAST(null);
- //這是非法操作,兩者的AST源不一樣
- targetRoot.types().add(srcRoot.types().get(0));
- //這是合法操作
- targetRoot.types().add(ASTNode.copySubtree(
- targetRoot.getAST(), (ASTNode) srcRoot.types().get(0)));
- //這是合法操作
- targetRoot.types().add(targetRoot.getAST().newTypeDeclaration());
現把一些 Java代碼生成對應的ASTNode方式列出來,供參考:
List 1 生成Package
List 1 生成Package
// package astexplorer;java 代碼
- PackageDeclaration packageDeclaration = ast.newPackageDeclaration();
- unit.setPackage(packageDeclaration);
- packageDeclaration.setName(ast.newSimpleName("astexplorer"));
List 2 生成Import
// import org.eclipse.swt.SWT;
// import org.eclipse.swt.events.*;
// import org.eclipse.swt.graphics.*;
// import org.eclipse.swt.layout.*;
// import org.eclipse.swt.widgets.*;java 代碼
- for (int i = 0; i < IMPORTS.length; ++i) {
- ImportDeclaration importDeclaration = ast.newImportDeclaration();
- importDeclaration.setName(ast.newName(getSimpleNames(IMPORTS[i])));
- if (IMPORTS[i].indexOf("*") > 0)
- importDeclaration.setOnDemand(true);
- else
- importDeclaration.setOnDemand(false);
- unit.imports().add(importDeclaration);
- }
List 3 生成Class Declaration
// public class SampleComposite extends Composite
java 代碼
- TypeDeclaration classType = ast.newTypeDeclaration();
- classType.setInterface(false);
- classType.setModifiers(Modifier.PUBLIC);
- classType.setName(ast.newSimpleName("SampleComposite"));
- classType.setSuperclass(ast.newSimpleName("Composite"));
- unit.types().add(classType);
List 4 生成Constructor Declaration
// public SampleComposite(Composite parent,int style){}
java 代碼
- MethodDeclaration methodConstructor = ast.newMethodDeclaration();
- methodConstructor.setConstructor(true);
- methodConstructor.setModifiers(Modifier.PUBLIC);
- methodConstructor.setName(ast.newSimpleName("SampleComposite"));
- classType.bodyDeclarations().add(methodConstructor);
- // constructor parameters
- SingleVariableDeclaration variableDeclaration = ast.newSingleVariableDeclaration();
- variableDeclaration.setModifiers(Modifier.NONE);
- variableDeclaration.setType(ast.newSimpleType(ast.newSimpleName("Composite")));
- variableDeclaration.setName(ast.newSimpleName("parent"));
- methodConstructor.parameters().add(variableDeclaration);
- variableDeclaration = ast.newSingleVariableDeclaration();
- variableDeclaration.setModifiers(Modifier.NONE);
- variableDeclaration.setType(ast.newPrimitiveType(PrimitiveType.INT));
- variableDeclaration.setName(ast.newSimpleName("style"));
- methodConstructor.parameters().add(variableDeclaration);
- Block constructorBlock = ast.newBlock();
- methodConstructor.setBody(constructorBlock);
List 5 生成Spuer Invocation
// super(parent,style)
java 代碼
- SuperConstructorInvocation superConstructorInvocation = ast.newSuperConstructorInvocation();
- constructorBlock.statements().add(superConstructorInvocation);
- Expression exp = ast.newSimpleName("parent");
- superConstructorInvocation.arguments().add(exp);
- superConstructorInvocation.arguments().add(ast.newSimpleName("style"));
List 6 生成ClassInstanceCreation
// GridLayout gridLayout = new GridLayout();
java 代碼
- VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment();
- vdf.setName(ast.newSimpleName("gridLayout"));
- ClassInstanceCreation cc = ast.newClassInstanceCreation();
- cc.setName(ast.newSimpleName("GridLayout"));
- vdf.setInitializer(cc);
- VariableDeclarationStatement vds = ast.newVariableDeclarationStatement(vdf);
- vds.setType(ast.newSimpleType(ast.newSimpleName("GridLayout")));
- constructBlock.statements().add(vds);
// Label label = new Label(this,SWT.NONE);
java 代碼
- VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment();
- vdf.setName(ast.newSimpleName("label"));
- cc = ast.newClassInstanceCreation();
- cc.setName(ast.newSimpleName("Label"));
- cc.arguments().add(ast.newThisExpression());
- cc.arguments().add(ast.newName(getSimpleNames("SWT.NONE")));
- vdf.setInitializer(cc);
- VariableDeclarationStatement vds = ast.newVariableDeclarationStatement(vdf);
- vds.setType(ast.newSimpleType(ast.newSimpleName("Label")));
- constructBlock.statements().add(vds);
List 7生成MethodInvocation
// setLayout(gridLayout);
java 代碼
- MethodInvocation mi = ast.newMethodInvocation();
- mi.setName(ast.newSimpleName("setLayout"));
- mi.arguments().add(ast.newSimpleName("gridLayout"));
- constructorBlock.statements().add(ast.newExpressionStatement(mi));
// label.setText("Press the button to close:");
java 代碼
- mi = ast.newMethodInvocation();
- mi.setExpression(ast.newSimpleName("label"));
- mi.setName(ast.newSimpleName("setText"));
- StringLiteral sl = ast.newStringLiteral();
- sl.setLiteralValue("Press the button to close:");
- mi.arguments().add(sl);
- constructorBlock.statements().add(ast.newExpressionStatement(mi));
// label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
java 代碼
- mi = ast.newMethodInvocation();
- mi.setExpression(ast.newSimpleName("label"));
- mi.setName(ast.newSimpleName("setLayoutData"));
- cc = ast.newClassInstanceCreation();
- cc.setName(ast.newSimpleName("GridData"));
- cc.arguments().add(ast.newName(getSimpleNames("GridData.HORIZONTAL_ALIGN_CENTER")));
- mi.arguments().add(cc);
- constructorBlock.statements().add(ast.newExpressionStatement(mi));
// Button button = new Button(this,SWT.PUSH);
java 代碼
- vdf = ast.newVariableDeclarationFragment();
- vdf.setName(ast.newSimpleName("button"));
- vds = ast.newVariableDeclarationStatement(vdf);
- vds.setType(ast.newSimpleType(ast.newSimpleName("Button")));
- constructorBlock.statements().add(vds);
- cc = ast.newClassInstanceCreation();
- cc.setName(ast.newSimpleName("Button"));
- vdf.setInitializer(cc);
- cc.arguments().add(ast.newThisExpression());
- cc.arguments().add(ast.newName(getSimpleNames("SWT.PUSH")));
// button.addSelectionListener(new SelectionAdapter() {});
java 代碼
- mi = ast.newMethodInvocation();
- constructorBlock.statements().add(ast.newExpressionStatement(mi));
- mi.setExpression(ast.newSimpleName("button"));
- mi.setName(ast.newSimpleName("addSelectionListener"));
- ClassInstanceCreation ci = ast.newClassInstanceCreation();
- ci.setName(ast.newSimpleName("SelectionAdapter"));
- mi.arguments().add(ci);
- AnonymousClassDeclaration cd = ast.newAnonymousClassDeclaration();
- ci.setAnonymousClassDeclaration(cd);
// public void setup(){super.setUp()}
- MethodDeclaration methodConstructor = ast.newMethodDeclaration();
methodConstructor.modifiers().add(
ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
methodConstructor.setName(ast.newSimpleName("setUp"));- Block constructorBlock = ast.newBlock();
methodConstructor.setBody(constructorBlock);- SuperMethodInvocation smi = ast.newSuperMethodInvocation();
smi.setName(ast.newSimpleName("setUp"));
ExpressionStatement es = ast.newExpressionStatement(smi);
constructorBlock.statements().add(es);- // set exception
List targetExNames = methodConstructor.thrownExceptions();
Name targetExName = ast.newName(Exception.class.getName());
targetExNames.add(targetExName);- methodConstructor.setJavadoc(JavaDocHelper.getJavaDoc(ast,
JavaDocHelper.setUpDoc, null, null));
classType.bodyDeclarations().add(methodConstructor);