Search code examples
javapythonpython-3.xpython-2.7code-editor

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


I have a lot of java files wherein I have to search for a method, if present I have to add a line inside this method "If this line does not already exist". This line has to be added before the closing brace of the method.

So far I have the following code:

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 }

But I am not sure where to go from here, Python not being my first language. Could I request to be guided in the right direction.

Example: I am looking for a method with the following signature:

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

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

Solution

  • This is actually quite difficult. First of all, your if "onPause" in sourcecode approach currently doesn't distinguish between defining onPause() and calling it. And second of all, finding the correct closing } isn't trivial. Naively, you might just count opening and closing curlies ({ increments the blocklevel, } decrements it), and assume that the } that makes the blocklevel zero is the closing curly of the method. However, this might be wrong! Because the method might contain some string literal containing (possibly unbalanced) curlies. Or comments with curlies. This would mess up the blocklevel count.

    To do this properly, you would have to build an actual Java parser. That's a lot of work, even when using libraries such as tatsu.

    If you're fine with a rather volatile kludge, you can try and use the blocklevel count mentioned above together with the indentation as a clue (assuming your source code is decently indented). Here's something I've hacked up as a starting point:

    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\")"))
    

    Note that this is vulnerable to all sorts of edge cases (such as { in a string or in a comment, or tab indent instead of space, or possibly a thousand other things). This is just a starting point for you.