如何使用Perl识别对Java类的引用?

pol*_*ear 3 java perl parsing

我正在写一个Perl脚本,我已经到了一个点,我需要逐行解析Java源文件,检查对完全限定的Java类名的引用.我知道我正在寻找的课程; 也是正在搜索的源文件的完全限定名称(基于其路径).

例如,在com/bob/is/YourUncle.java文件中找到对foo.bar.Baz的所有有效引用.

此时我能想到的需要考虑的案例是:

  1. 正在解析的文件与搜索类位于同一个包中.

    在foo/bar/Boing.java中找到foo.bar.Baz引用

  2. 它应该忽略评论.

    // this is a comment saying this method returns a foo.bar.Baz or Baz instance 
    // it shouldn't count
    
    /*   a multiline comment as well
     this shouldn't count
     if I put foo.bar.Baz or Baz in here either */
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在线完全限定参考.

    foo.bar.Baz fb = new foo.bar.Baz();
    
    Run Code Online (Sandbox Code Playgroud)
  4. 引用基于import语句.

    import foo.bar.Baz;
    ...
    Baz b = new Baz();
    
    Run Code Online (Sandbox Code Playgroud)

在Perl 5.8中最有效的方法是什么?有些花哨的正则表达式可能吗?

open F, $File::Find::name or die;
# these three things are already known
# $classToFind    looking for references of this class
# $pkgToFind      the package of the class you're finding references of
# $currentPkg     package name of the file being parsed
while(<F>){
  # ... do work here   
}
close F;
# the results are availble here in some form
Run Code Online (Sandbox Code Playgroud)

Pau*_*cks 5

正则表达式可能是最好的解决方案,尽管我确实在CPAN中找到了您可以使用的以下模块

  • Java :: JVM :: Classfile - 解析已编译的类文件并返回有关它们的信息.您必须先编译文件才能使用它.

此外,请记住,使用正则表达式捕获多行注释的所有可能变体可能很棘手.


tye*_*tye 5

您还需要跳过引用的字符串(如果您不处理引用的字符串,则甚至无法正确跳过注释).

我可能会编写一个相当简单,高效且不完整的标记化器,与我在节点566467中编写的标记器非常相似.

基于该代码,我可能只是挖掘非注释/非字符串块寻找\bimport\b\b\Q$toFind\E\b匹配.也许类似于:

if( m[
        \G
        (?:
            [^'"/]+
          | /(?![/*])
        )+
    ]xgc
) {
    my $code = substr( $_, $-[0], $+[0] - $-[0] );
    my $imported = 0;
    while( $code =~ /\b(import\s+)?\Q$package\E\b/g ) {
        if( $1 ) {
            ... # Found importing of package
            while( $code =~ /\b\Q$class\E\b/g ) {
                ... # Found mention of imported class
            }
            last;
        }
        ... # Found a package reference
    }
} elsif( m[ \G ' (?: [^'\\]+ | \\. )* ' ]xgc
    ||   m[ \G " (?: [^"\\]+ | \\. )* " ]xgc
) {
    # skip quoted strings
} elsif(  m[\G//.*]g­c  ) {
    # skip C++ comments
Run Code Online (Sandbox Code Playgroud)