从Java代码中提取方法调用

3

我想从Java代码中提取所有的方法调用。我编写了以下两个正则表达式,但它们无法提取所有的方法调用。

Reg1 : Pattern.compile("([a-zA-Z][0-9_a-zA-Z]*\\([a-zA-Z0-9_\\s,\\[\\]\\(\\)\\.]+\\))");

Reg2 : Pattern.compile("([a-zA-Z][0-9_a-zA-Z]*\\([\\s]*\\))")

输入:

"{
     if ((war == null) && (config != null)) {
    sb.append( &config= );
    sb.append(URLEncoder.encode(config,getCharset()));
    }
    if ((war == null) && (localWar != null)) {
    sb.append( &war= );
    sb.append(URLEncoder.encode(localWar,getCharset()));
    }
    if (update) {
    sb.append( &update=true );
    }
    if (tag != null) {
      sb.append( &tag= );
      sb.append(URLEncoder.encode(tag,getCharset()));
     }
     }"

输出:

getCharset getCharset getCharset append append append

我无法提取"encode"。

有没有人有任何想法,应该添加什么正则表达式?


5
根据语言理论的成熟原则,使用正则表达式进行此操作是不可能的,主要是因为每个调用可能包含其他调用,这些调用可能又包含其他调用... - laune
请给我一些它的替代方案建议。 - Sangeeta
2
也许这篇帖子会有所帮助 https://dev59.com/LHE95IYBdhLWcg3wrP4o - Mariano
谢谢!但我想提取程序中所调用的方法。 - Sangeeta
1
同样适用于Java:https://dev59.com/questions/rGw15IYBdhLWcg3wO5IH - Nir Alfasi
1个回答

9
您需要一个Java代码解析器来完成此任务。以下是一个使用Java Parser的示例:
public class MethodCallPrinter
{
    public static void main(String[] args) throws Exception
    {
        FileInputStream in = new FileInputStream("MethodCallPrinter.java");

        CompilationUnit cu;
        try
        {
            cu = JavaParser.parse(in);
        }
        finally
        {
            in.close();
        }
        new MethodVisitor().visit(cu, null);
    }

    private static class MethodVisitor extends VoidVisitorAdapter
    {
        @Override
        public void visit(MethodCallExpr methodCall, Object arg)
        {
            System.out.print("Method call: " + methodCall.getName() + "\n");
            List<Expression> args = methodCall.getArgs();
            if (args != null)
                handleExpressions(args);
        }

        private void handleExpressions(List<Expression> expressions)
        {
            for (Expression expr : expressions)
            {
                if (expr instanceof MethodCallExpr)
                    visit((MethodCallExpr) expr, null);
                else if (expr instanceof BinaryExpr)
                {
                    BinaryExpr binExpr = (BinaryExpr)expr;
                    handleExpressions(Arrays.asList(binExpr.getLeft(), binExpr.getRight()));
                }
            }
        }
    }
}

输出:

Method call: parse
Method call: close
Method call: visit
Method call: print
Method call: getName
Method call: getArgs
Method call: handleExpressions
Method call: visit
Method call: handleExpressions
Method call: asList
Method call: getLeft
Method call: getRight

@laune,你说的“句子中的递归”是什么意思? - splash
1
Java语法定义了如何构建该语言的“句子”。在“方法调用”的定义中,通过一些NTs之间,“方法调用”再次出现:递归。因此,必须有一个迭代for(Expression e:methodCall.getArgs()){...}等等。 - laune
1
@Sangeeta,你可以使用methodCall.getBeginLine()来检查方法调用是否在源代码的所需部分内。 - splash
@splash,当我使用代码的一部分创建解析器时,它会出现错误。因为有时候缺少;、)、}或do-while循环中的while。有什么想法如何处理不完整的代码? - Sangeeta
@Sangeeta,你应该始终解析有效的Java代码。如果你只有部分代码,那么你必须完成代码使其有效,并忽略“MethodVisitor”中添加的代码行。 - splash
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接