使用 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,或者可能还有一千种其他情况) .这只是您的一个起点。
我有很多 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,或者可能还有一千种其他情况) .这只是您的一个起点。