使用 python 在 java 代码的方法块中添加一行

Adding a line in a method block of java code using python

我有很多 java 文件,我必须在其中搜索一种方法,如果存在,我必须在该方法中添加一行 "If this line does not already exist"。此行必须添加到方法的右大括号之前。

到目前为止我有以下代码:

import os
import ntpath
extensions = set(['.java','.kt'])
for subdir, dirs, files in os.walk("/src/main"):
        for file in files:
            filepath = subdir + os.sep + file
            extension = os.path.splitext(filepath)[1]
            if extension in extensions:
                if 'onCreate(' in open(filepath).read():
                        print (ntpath.basename(filepath))
                        if 'onPause' in open (filepath).read():
                            print ("is Activity and contains onPause\n")
                            #Check if Config.pauseCollectingLifecycleData(); is in this code bloack, if exists do nothing, if does not exist add to the end of code block before }
                        if 'onResume' in open (filepath).read():
                            print ("is Activity and contains onResume\n")
                            #Check if Config.resumeCollectingLifecycleData(); is in this code bloack, if exists do nothing, if does not exist add to the end of code block before }

但我不确定从这里到哪里去,Python 不是我的母语。我可以要求在正确的方向上得到指导吗?

示例: 我正在寻找具有以下签名的方法:

public void onPause(){
   super.onPause();
   // Add my line here
}

public void onPause(){
   super.onPause();
   Config.pauseCollectingLifecycleData(); // Line exists do nothing 
}

这个其实挺难的。首先,您的 if "onPause" in sourcecode 方法目前不区分 定义 onPause() 调用 它。其次,找到正确的结尾 } 并非易事。天真地,您可能只计算打开和关闭卷曲({ 增加块级别,} 减少它),并假设使块级别为零的 } 是方法的关闭卷曲.然而,这可能是错误的!因为该方法可能包含一些 string literal 包含(可能不平衡)卷曲。或者 comments with curlies。这会弄乱块级计数。

要正确执行此操作,您必须构建一个实际的 Java 解析器。这是很多工作,即使使用 tatsu.

等库也是如此

如果您可以接受相当不稳定的 kludge,您可以尝试使用上面提到的块级别计数和缩进作为线索(假设您的源代码缩进得当)。这是我作为起点的一些东西:

def augment_function(sourcecode, function, line_to_insert):
    in_function = False
    blocklevel = 0
    insert_before = None
    source = sourcecode.split("\n")
    for line_no, line in enumerate(source):
        if in_function:
            if "{" in line:
                blocklevel += 1
            if "}" in line:
                blocklevel -= 1
                if blocklevel == 0:
                    insert_before = line_no
                    indent = len(line) - len(line.lstrip(" ")) + 4  #4=your indent level
                    break
        elif function in line and "public " in line:
            in_function = True
            if "{" in line:
                blocklevel += 1
    if insert_before:
        source.insert(insert_before, " "*indent + line_to_insert)
    return "\n".join(source)

# test code:
java_code = """class Foo {
    private int foo;
    public void main(String[] args) {
        foo = 1;
    }
    public void setFoo(int f)
    {
        foo = f;
    }
    public int getFoo(int f) {
        return foo;
    }
}
"""
print(augment_function(java_code, "setFoo", "log.debug(\"setFoo\")"))

请注意,这很容易受到各种边缘情况的影响(例如字符串或注释中的 {,或者制表符缩进而不是 space,或者可能还有一千种其他情况) .这只是您的一个起点。