资讯专栏INFORMATION COLUMN

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

宋华 / 3582人阅读

摘要:另载于本系列临近尾声,科技树到此点满。如果做插件,可以享受的语义分析能力。为了让程序独立运行,我自己按需实现了语义分析。为了提速分析大型代码库,可以手动限制范围。直接贴代码了,已在项目提供。

另载于 http://www.qingjingjie.com/blogs/6

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

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

如果做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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64351.html

相关文章

  • 深入理解Java内存模型()——锁

    摘要:前情提要深入理解内存模型四锁的释放获取建立的关系锁是并发编程中最重要的同步机制。锁内存语义的实现本文将借助的源代码,来分析锁内存语义的具体实现机制。请看下篇深入理解内存模型六 前情提要 深入理解Java内存模型(四)—— volatile 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还可以让释放锁的线程向...

    caige 评论0 收藏0
  • 论文简介-1

    摘要:论文一本体论在自动问答系统中的应用骆正华基于本体来组织问句的方法,并探讨在基础上分析问句的方法,并利用本体向量来联系问句实例和领域知识,达到问题和答案的连接。领域具体事实知识的表示采用标记规范,主题操作事件或业务实体描述或属性。 论文 一、本体论在自动问答系统中的应用_骆正华 基于本体来组织问句的方法,并探讨在基础上分析问句的方法,并利用本体向量来联系问句实例和领域知识,达到问题和答...

    lyning 评论0 收藏0
  • JavaWEB开发01——HTML

    摘要:网站信息页面需求分析我们公司的需要一个对外宣传的网站介绍介绍公司的主要业务公司的发展历史公司的口号等等信息技术分析概述超文本标记语言超文本比普通文本功能更加强大可以添加各种样式标记语言通过一组标签来对内容进行描述关键字是由浏览器来解释执行静 1.网站信息页面 1.1需求分析: 我们公司的需要一个对外宣传的网站介绍,介绍公司的主要业务,公司的发展历史,公司的口号等等信息 1.2技术分析:...

    IntMain 评论0 收藏0
  • Java并发编程,3分分钟深入分析volatile的实现原理

    摘要:一言以蔽之,被修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。为了实现内存语义时,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。volatile原理volatile简介Java内存模型告诉我们,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存中的数据进行操作处理。 线程在工作内存进行操作后何时会写到主内存中...

    番茄西红柿 评论0 收藏0
  • Java并发编程,3分分钟深入分析volatile的实现原理

    摘要:一言以蔽之,被修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。为了实现内存语义时,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。volatile原理volatile简介Java内存模型告诉我们,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存中的数据进行操作处理。 线程在工作内存进行操作后何时会写到主内存中...

    番茄西红柿 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<