Search code examples
javaeclipsecompilationtokenjavaparser

ClassOrInterfaceDeclaration.getTokenRange() gets all the tokens for a file even after removing nodes from the class


When I remove "ClassOrInterfaceDeclaration" nodes from a class in CompilationUnit (JavaParser) from a parsed file that contains more than one class, ClassOrInterfaceDeclaration.getTokenRange() gets all the tokens even the removed nodes tokens. For example, the code snippet at positions 1 and 2 will give the same result, although I already removed nodes from ClassOrInterfaceDeclaration n.

Does anyone know how to get the correct tokens list?

private void RemoveOtherClassesFromSameFile(ClassOrInterfaceDeclaration n) {
     n.getTokenRange() // 1
    List<ClassOrInterfaceDeclaration> internalClasses = unmodifiableList(
            n.getMembers().stream().filter(m -> m instanceof ClassOrInterfaceDeclaration)
                    .map(m -> (ClassOrInterfaceDeclaration) m).collect(toList()));
    for (ClassOrInterfaceDeclaration c : internalClasses)
        n.remove(c);
   n.getTokenRange() // 2
}

Solution

  • Ater Adjusting the file that contains the node, you must update the source root by using method saveAll, to override the AST to your file, like that

    sourceRoot.saveAll(Paths.get(parsedFilePath));
    

    Full Example:

    import com.github.javaparser.ast.CompilationUnit;
    import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
    import com.github.javaparser.ast.visitor.ModifierVisitor;
    import com.github.javaparser.ast.visitor.Visitable;
    import com.github.javaparser.utils.SourceRoot;
    
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class Main {
    
        public  static  void main(String[] args) throws IOException {
            Path dirPath =  Paths.get("C:\\JavaParserTest\\src\\main\\resources\\src\\");
            SourceRoot sourceRoot = new SourceRoot(dirPath);
            sourceRoot.tryToParse();
            CompilationUnit cu = sourceRoot.parse("", dirPath.toString()+"\\JavaFile.java");
    
            cu.accept(new ModifierVisitor<Void>() {
                @Override
                public Visitable visit(ClassOrInterfaceDeclaration n, Void arg) {
                    RemoveOtherClassesFromSameFile(n, cu);
                    return super.visit(n, arg);
                }
            }, null);
    
            sourceRoot.saveAll(Paths.get(dirPath.toString()+"\\JavaFile.java"));
        }
    
        private static ClassOrInterfaceDeclaration RemoveOtherClassesFromSameFile(ClassOrInterfaceDeclaration n, CompilationUnit cu) {
            List<ClassOrInterfaceDeclaration> internalClasses = (
                    n.getMembers().stream().filter(m -> m instanceof ClassOrInterfaceDeclaration)
                            .map(m -> (ClassOrInterfaceDeclaration) m).collect(Collectors.toList()));
            for (ClassOrInterfaceDeclaration c : internalClasses){
                n.remove(c);
            }
            return n;
        }
    
    }