0

I need to add this is a class or this is a method in a text/java file before class name or method name (line no is available through japa).

I have tried all possible cases I can, try to edit text/Java file with file reader/writer (but it always append at the end ,and want above class/method name), pmd, japa (can read but can't find option to edit) and random access files interface (can edit too but it don't append instead overrides character).

Nothing has helped so far, is there any way I can achieve this?

For example, the original source code:

import java.lang.*;
class test1{
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

after

import java.lang.*;
/*this is a class*/
class test1{
    /*this is a method*/
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
shrikant.sharma
  • 203
  • 1
  • 17
  • 37
  • How do you figure out where to append. If you have logic then you should read line and rewrite the file. Usually this kind of code manupluation is done using Abstract Syntax Tree (AST) – Allahbaksh Asadullah May 22 '15 at 05:12
  • 1
    It's unclear what you are asking. Are you asking what methods are available in Java to read a text file, parse it and update the file based on contents? It's not clear at this stage if the java tag is because you happen to be reading a Java file or because the solution must be using Java. Please clarify. – sprinter May 22 '15 at 05:33
  • i have used japa or by simple text reader you can find class name and its line no , then lineNo-1 is the line where i need to add /*this is method/class*/ , thats not the issue , i want to add a comment before public class abc without modifing anything else – shrikant.sharma May 22 '15 at 05:40
  • That would work for this by reading the text file till the public class XXX by using RegEx and buffers to do it and rewrite the original file. But this is not the approach which is good. Your code might not be compilable later if you don't locate the location public class XXX. This might happen because of a comment /* public class XXX { .....*/ – Allahbaksh Asadullah May 22 '15 at 05:46
  • actually i thought this approach too , read upper content in different file or string , rest in different file/string, append the required data in first part then again append rest of code, but this is not the good approach , plus its OK for small code what if code is of 1000 lines or more – shrikant.sharma May 22 '15 at 06:18
  • OK that's up-to some extent the same output i want but i want it in same file not in a new one because i am not dealing with normal text file , its a java file so after editing source code must remain compilable without human effort , if i create a new file then have to manually update reference of file every where used, – shrikant.sharma May 22 '15 at 07:14
  • and suggestion of some kind of parser or method which can do this is preferable rather then editing with normal text mode , that's not good approach in this case, – shrikant.sharma May 22 '15 at 07:16
  • @shrikant.sharma Have a look to my posted answer. – SubOptimal May 22 '15 at 07:28
  • For me this is not a duplicate. Identifying any method in a Java source file using a regexp might not be that difficult. But finding the right insert position for the comment (as requested) and keep even the right indentation might be a hard work (maybe not possible with a regexp), because of all the possible combinations of access/visibiliy qualifiers, return types, Generics, ... That's the reason I asked to reopen the questionand maybe the `duplicate` can be removed. – SubOptimal May 29 '15 at 07:14

2 Answers2

2

You can use JavaParser and implement your own ModifierVisitorAdapter. Find below a small snippet you can start with.

import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.Node;
import japa.parser.ast.body.ClassOrInterfaceDeclaration;
import japa.parser.ast.body.MethodDeclaration;
import japa.parser.ast.comments.BlockComment;
import japa.parser.ast.visitor.ModifierVisitorAdapter;
import java.io.File;
import java.io.IOException;

public class ModifierVisitorAdapterDemo {

    public static void main(String[] args) throws IOException, ParseException {
        File sourceFile = new File("Test.java");
        CompilationUnit cu = JavaParser.parse(sourceFile);
        cu.accept(new ModifierVisitor(), null);

        // instead of printing it to stdout you can write it to a file
        System.out.println("// enriched cource");
        System.out.println(cu.toString());

        // to save it into the original file
        // this will overwrite the input file
        Files.write(sourceFile.toPath(), 
                cu.toString().getBytes(Charset.defaultCharset()), 
                StandardOpenOption.TRUNCATE_EXISTING
        );
    }

    private static class ModifierVisitor extends ModifierVisitorAdapter {

        @Override
        public Node visit(ClassOrInterfaceDeclaration n, Object arg) {
            if (!n.isInterface()) {
                n.setComment(new BlockComment(" this is a class "));
            }
            return super.visit(n, arg);
        }

        @Override
        public Node visit(MethodDeclaration n, Object arg) {
            n.setComment(new BlockComment(" this is a method "));
            return super.visit(n, arg);
        }
    }
}

Assuming following input file Test.java

import java.lang.System;

class Test {

    static class Foo {
    }

    static interface IFace {
    }

    public static void main(String... args) {
    }
}

the output will be

// enriched cource
import java.lang.System;

/* this is a class */
class Test {

    /* this is a class */
    static class Foo {
    }

    static interface IFace {
    }

    /* this is a method */
    public static void main(String... args) {
    }
}
SubOptimal
  • 22,518
  • 3
  • 53
  • 69
0

You can definitely use JavaParser to do that. You can visit the tree finding all classes and methods (you can use a visitor to do that or just start from the root of the file (CompilationUnit) and call recursively node.getChildrenNodes(). When you find an instance of ClassOrInterfaceDeclaration or MethodDeclaration you just add a comment using the method node.setComment()

Now you can dump the file (going from the AST back to source code) using the DumpVisitor or just call compilationUnit.toString()

Disclaimer: I am a JavaParser contributor

Feed free to ask other questions here or open an issue on GitHub. The project is currently maintained at https://github.com/javaparser/javaparser

Federico Tomassetti
  • 2,100
  • 1
  • 19
  • 26
  • thanks guys got the solution , thanks @SubOptimal and @Federico Tomassetti ,actually it was easy , after making changes , fileWriter(cu.toString) did the job , @SubOptimal could you mail me your working project along with required jar shrikant.sharma606@gmail.com because when i am coping your code in eclipse its giving error `Files.write(sourceFile.toPath(), cu.toString().getBytes(Charset.defaultCharset()), StandardOpenOption.TRUNCATE_EXISTING );)`, would like to understand your way of doing too. – shrikant.sharma May 23 '15 at 03:29
  • @shrikant.sharma Either you have a typo `);)` or you use a Java version before 7. – SubOptimal May 26 '15 at 06:30