【Eclipse AST】AST的创建
来源:互联网 发布:淘宝左氏燕窝真假 编辑:程序博客网 时间:2024/04/30 03:11
对于源代码优化过程而言,借助前文所介绍的AST访问与解析,可以自动查找出哪些地方需要优化,或者说能够发现优化或重构“时机”。接下来要做的就是采取相应的优化措施,在AST中创建节点(包括创建新的AST)或修改原有节点。本文将介绍如何创建一棵AST,以及通过AST来生成Java源代码。
在创建节点时,需要开发人员对AST中的节点有较为深入的了解。Eclipse AST中的AST类采用了工厂方法模式,针对所有类型的节点都提供了new***()方法来创建新的节点,如newTypeDeclaration()、newMethodInvocation()等等。“创建规则”是从叶子节点开始创建,先创建子节点后创建父节点,再将它们关联起来。这也意味着我们需要为创建一小段Java代码而编写一大段AST操作代码。
例如创建如下单行变量声明语句:
int i = 1;
在创建代码对应的AST之前,可以先通过ASTView观察一下此代码由哪些节点组成,如图1所示。
图1 示例代码AST
根据创建规则需要从“int”、“i”和“1”开始创建。完整的创建代码如下,其中VariableDeclarationStatement即为所需创建的节点:
SimpleName name = ast.newSimpleName("i");NumberLiteral number = ast.newNumberLiteral("1");PrimitiveType type = ast.newPrimitiveType(PrimitiveType.INT);//创建语句“i = 1”VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment();fragment.setName(name);fragment.setInitializer(number);//创建“int i = 1;”VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(fragment);statement.setType(type);
但是,根据创建顺序进行编码加大了代码的阅读难度,因此建议采用局部按照创建顺序,整体按照编码顺序进行编写。
下面我们来创建一个完整的如下HelloWorld类:
public class HelloWorld { public HelloWorld(){ System.out.println("Hello World!"); }}
由于是从无到有创建一个新的类,这意味着需要构建一个新的AST,而且创建新节点的任务需要通过该AST对象调用相应的new***()方法来完成,因此首先可以通过解析空的代码来创建一个空的AST。
ASTParser parser = ASTParser.newParser(AST.JLS3);parser.setSource("".toCharArray());CompilationUnit comp = (CompilationUnit) parser.createAST(null); comp.recordModifications();AST ast = comp.getAST();
根据编码顺序,我们需要先创建一个公共类,类名为HelloWorld,并把类节点作为编译单元comp的子节点。
/**public class HelloWorld {**}*/TypeDeclaration classDec = ast.newTypeDeclaration();classDec.setInterface(false);//设置为非接口SimpleName className = ast.newSimpleName("HelloWorld");Modifier classModifier = ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);//设置类节点classDec.setName(className);//类名classDec.modifiers().add(classModifier);//类可见性//将类节点连接为编译单元的子节点comp.types().add(classDec);
然后创建构造函数HelloWorld,并作为类节点classDec的子节点。
/**public class HelloWorld {* public HelloWorld(){* * }*}*/MethodDeclaration methodDec = ast.newMethodDeclaration();methodDec.setConstructor(true);//设置为构造函数SimpleName methodName = ast.newSimpleName("HelloWorld");Modifier methodModifier = ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);Block methodBody = ast.newBlock();//设置方法节点methodDec.setName(methodName);// 方法名methodDec.modifiers().add(methodModifier);//方法可见性methodDec.setBody(methodBody); //方法体//将方法节点连接为类节点的子节点classDec.bodyDeclarations().add(methodDec);
创建方法体中的输出语句,并作为方法节点methodDec的子节点。
/**public class HelloWorld {* public HelloWorld(){* System.out.println("Hello World!");* }*}*/MethodInvocation methodInv = ast.newMethodInvocation();SimpleName nameSystem = ast.newSimpleName("System");SimpleName nameOut = ast.newSimpleName("out");SimpleName namePrintln = ast.newSimpleName("println");//连接‘System’和‘out’//System.outQualifiedName nameSystemOut = ast.newQualifiedName(nameSystem, nameOut);//连接‘System.out’和‘println’到MethodInvocation节点//System.out.println()methodInv.setExpression(nameSystemOut);methodInv.setName(namePrintln);//”Hello World!”StringLiteral sHelloworld = ast.newStringLiteral();sHelloworld.setEscapedValue("\"Hello World!\"");//System.out.println(“Hello World!”)methodInv.arguments().add(sHelloworld);//将方法调用节点MethodInvocation连接为表达式语句ExpressionStatement的子节点//System.out.println(“Hello World!”);ExpressionStatement es = ast.newExpressionStatement(methodInv);//将表达式语句ExpressionStatement连接为方法节点的点methodBody.statements().add(es);
完整的创建代码如下:
import org.eclipse.jdt.core.dom.AST;import org.eclipse.jdt.core.dom.ASTParser;import org.eclipse.jdt.core.dom.Block;import org.eclipse.jdt.core.dom.CompilationUnit;import org.eclipse.jdt.core.dom.ExpressionStatement;import org.eclipse.jdt.core.dom.MethodDeclaration;import org.eclipse.jdt.core.dom.MethodInvocation;import org.eclipse.jdt.core.dom.Modifier;import org.eclipse.jdt.core.dom.QualifiedName;import org.eclipse.jdt.core.dom.SimpleName;import org.eclipse.jdt.core.dom.StringLiteral;import org.eclipse.jdt.core.dom.TypeDeclaration;public class HelloWorldBuilder {public HelloWorldBuilder() {build();}private void build() {ASTParser parser = ASTParser.newParser(AST.JLS3);parser.setSource("".toCharArray());CompilationUnit comp = (CompilationUnit) parser.createAST(null); comp.recordModifications();AST ast = comp.getAST();/**public class HelloWorld {**}*/TypeDeclaration classDec = ast.newTypeDeclaration();classDec.setInterface(false);//设置为非接口SimpleName className = ast.newSimpleName("HelloWorld");Modifier classModifier = ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);//设置类节点classDec.setName(className);//类名classDec.modifiers().add(classModifier);//类可见性//将类节点连接为编译单元的子节点comp.types().add(classDec);/**public class HelloWorld {* public HelloWorld(){* * }*}*/MethodDeclaration methodDec = ast.newMethodDeclaration();methodDec.setConstructor(true);//设置为构造函数SimpleName methodName = ast.newSimpleName("HelloWorld");Modifier methodModifier = ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);Block methodBody = ast.newBlock();//设置方法节点methodDec.setName(methodName);// 方法名methodDec.modifiers().add(methodModifier);//方法可见性methodDec.setBody(methodBody); //方法体//将方法节点连接为类节点的子节点classDec.bodyDeclarations().add(methodDec);/**public class HelloWorld {* public HelloWorld(){* System.out.println("Hello World!");* }*}*/MethodInvocation methodInv = ast.newMethodInvocation();SimpleName nameSystem = ast.newSimpleName("System");SimpleName nameOut = ast.newSimpleName("out");SimpleName namePrintln = ast.newSimpleName("println");//连接‘System’和‘out’//System.outQualifiedName nameSystemOut = ast.newQualifiedName(nameSystem, nameOut);//连接‘System.out’和‘println’到MethodInvocation节点//System.out.println()methodInv.setExpression(nameSystemOut);methodInv.setName(namePrintln);//”Hello World!”StringLiteral sHelloworld = ast.newStringLiteral();sHelloworld.setEscapedValue("\"Hello World!\"");//System.out.println(“Hello World!”)methodInv.arguments().add(sHelloworld);//将方法调用节点MethodInvocation连接为表达式语句ExpressionStatement的子节点//System.out.println(“Hello World!”);ExpressionStatement es = ast.newExpressionStatement(methodInv);//将表达式语句ExpressionStatement连接为方法节点的点methodBody.statements().add(es);//EndSystem.out.println(comp.toString());}}
一个简单的通过AST来生成代码的完整实例至此结束,虽说生成的代码很简单,实际上该生成过程对于新手来说还是略有点复杂,需要好好理解和掌握!
与其临渊羡鱼,不如退而结网,大家不妨动手一试!
【本文作者:刘伟,刘宏韬 http://blog.csdn.net/lovelion】
- 【Eclipse AST】AST的创建
- 【Eclipse AST】AST的修改
- 【Eclipse AST】AST的获取与访问
- AST
- ast
- AST
- 【Eclipse AST】AST与ASTView简介
- 【Eclipse AST】AST与ASTView简介 .
- Eclipse JDT--AST入门
- Eclipse JDT--AST入门
- Eclipse JDT--AST入门
- ast 好的网址
- 使用Eclipse JDT 构建AST
- 解决eclipse下的Requesting JavaScript AST from selection
- 【eclipse高效开发】——AST的获取与访问
- AST的一些概念(待续)
- 【eclipse高效开发】——AST View
- 利用Eclipse JDT抽取Java AST
- Surface研究报告
- powerdesigner的使用
- tomcat conf目录下web.xml、tomcat-users.xml、server.xml以及context.xml四个文件的作用
- 1--4同学成绩
- 秦九韶算法解多项式
- 【Eclipse AST】AST的创建
- php对文件操作
- HTML5 Geolocation(地理定位)用于定位用户的位置
- C语言经典算法100例-012-求素数
- 笔记1
- Linux 进程
- SystemServer研究报告
- KVC OC中键值编码的概念和使用方法
- 乒乓启示录一 - 把简单的动作做到极致就是成功