java 语义分析_Java代码分析器(五): 语义分析简介

本系列临近尾声,科技树到此点满。

语法分析主要用库解决了,代码变成了一棵树,但是变量类型,方法签名之类的东东都不清楚。

如果做IDE插件,可以享受IDE的语义分析能力。为了让程序独立运行,我自己按需实现了语义分析。

比较复杂,就分享一种最典型的吧。贴代码为主,有问题请告诉我,我再改文章。

解析某个变量的声明类型,会上溯当前方法和类,以及祖先类。为了提速(分析大型代码库),可以手动限制范围。

直接贴代码了,已在Exia项目提供。

public class VariableTypeResolver {

private final String symbol;

private final ASTNode minScope;

private boolean methodLevel = true;

private boolean typeLevel = true;

/**

* The found result

*/

private SimpleName declSN;

private final ASTVisitor visitor = new ASTVisitor() {

@Override

public boolean visit(SimpleName sn) {

if (found()) {

return false;

}

if (sn.getIdentifier().equals(symbol) && sn.getParent() instanceof VariableDeclaration) {

declSN = sn;

return false;

}

return true;

}

};

/**

* Starts resolving with the requested symbol

* @param varSymbolNode the variable symbol node to resolve (node must be in the AST)

*/

public VariableTypeResolver(SimpleName varSymbolNode) {

this.symbol = varSymbolNode.getIdentifier();

this.minScope = varSymbolNode;

}

public VariableTypeResolver(String varSymbol, ASTNode minScope) {

this.symbol = varSymbol;

this.minScope = minScope;

}

public VariableTypeResolver disableMethodLevel() {

methodLevel = false;

return this;

}

public VariableTypeResolver disableTypeLevel() {

typeLevel = false;

return this;

}

/**

* Node's parent is instance of {@link VariableDeclarationFragment} or {@link SingleVariableDeclaration}

* @return the SimpleName node of declaration

*/

public SimpleName resolveDeclSimpleName() {

if (!found()) {

resolve();

}

return declSN;

}

private void resolve() {

if(found()) {return;}

if (methodLevel) {

apply(FindUpper.methodScope(minScope));

}

if(found()) {return;}

if (typeLevel) {

AbstractTypeDeclaration typeScope = FindUpper.abstractTypeScope(minScope);

applyInFields(typeScope);

if(found()) {return;}

for (TypeDeclaration superClass : superClasses(typeScope)) {

if(found()) {return;}

applyInFields(superClass);

}

}

}

private boolean found() {

return declSN != null;

}

private void apply(ASTNode scope) {

if (scope == null) {

throw new NullPointerException();

}

scope.accept(visitor);

}

private void applyInFields(AbstractTypeDeclaration typeScope) {

for (Object bd : typeScope.bodyDeclarations()) {

if (bd instanceof FieldDeclaration) {

apply((ASTNode) bd);

}

}

}

private List superClasses(AbstractTypeDeclaration atd) {

if (atd instanceof TypeDeclaration) {

return AstUtils.superClasses((TypeDeclaration) atd);

}

else {

return Collections.EMPTY_LIST;

}

}

}

它依赖的AstUtils, FindUpper, SourcePathCollector设施都在Exia里面,配合使用即可。https://github.com/sorra/exia

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值