Home | History | Annotate | Download | only in generator
      1 package com.github.javaparser.generator;
      2 
      3 import com.github.javaparser.ast.CompilationUnit;
      4 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
      5 import com.github.javaparser.ast.body.MethodDeclaration;
      6 import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
      7 import com.github.javaparser.ast.expr.Name;
      8 import com.github.javaparser.metamodel.BaseNodeMetaModel;
      9 import com.github.javaparser.metamodel.JavaParserMetaModel;
     10 import com.github.javaparser.utils.Log;
     11 import com.github.javaparser.utils.SourceRoot;
     12 
     13 import java.util.Optional;
     14 
     15 import static com.github.javaparser.ast.Modifier.PUBLIC;
     16 
     17 /**
     18  * Makes it easier to generate visitor classes.
     19  * It will create missing visit methods on the fly,
     20  * and will ask you to fill in the bodies of the visit methods.
     21  */
     22 public abstract class VisitorGenerator extends Generator {
     23     private final String pkg;
     24     private final String visitorClassName;
     25     private final String returnType;
     26     private final String argumentType;
     27     private final boolean createMissingVisitMethods;
     28 
     29     protected VisitorGenerator(SourceRoot sourceRoot, String pkg, String visitorClassName, String returnType, String argumentType, boolean createMissingVisitMethods) {
     30         super(sourceRoot);
     31         this.pkg = pkg;
     32         this.visitorClassName = visitorClassName;
     33         this.returnType = returnType;
     34         this.argumentType = argumentType;
     35         this.createMissingVisitMethods = createMissingVisitMethods;
     36     }
     37 
     38     public final void generate() throws Exception {
     39         Log.info("Running %s", getClass().getSimpleName());
     40 
     41         final CompilationUnit compilationUnit = sourceRoot.tryToParse(pkg, visitorClassName + ".java").getResult().get();
     42 
     43         Optional<ClassOrInterfaceDeclaration> visitorClassOptional = compilationUnit.getClassByName(visitorClassName);
     44         if (!visitorClassOptional.isPresent()) {
     45             visitorClassOptional = compilationUnit.getInterfaceByName(visitorClassName);
     46         }
     47         final ClassOrInterfaceDeclaration visitorClass = visitorClassOptional.get();
     48 
     49         JavaParserMetaModel.getNodeMetaModels().stream()
     50                 .filter((baseNodeMetaModel) -> !baseNodeMetaModel.isAbstract())
     51                 .forEach(node -> generateVisitMethodForNode(node, visitorClass, compilationUnit));
     52         after();
     53     }
     54 
     55     protected void after() throws Exception {
     56 
     57     }
     58 
     59     private void generateVisitMethodForNode(BaseNodeMetaModel node, ClassOrInterfaceDeclaration visitorClass, CompilationUnit compilationUnit) {
     60         final Optional<MethodDeclaration> existingVisitMethod = visitorClass.getMethods().stream()
     61                 .filter(m -> m.getNameAsString().equals("visit"))
     62                 .filter(m -> m.getParameter(0).getType().toString().equals(node.getTypeName()))
     63                 .findFirst();
     64 
     65         if (existingVisitMethod.isPresent()) {
     66             generateVisitMethodBody(node, existingVisitMethod.get(), compilationUnit);
     67         } else if (createMissingVisitMethods) {
     68             MethodDeclaration newVisitMethod = visitorClass.addMethod("visit")
     69                     .addParameter(node.getTypeNameGenerified(), "n")
     70                     .addParameter(argumentType, "arg")
     71                     .setType(returnType);
     72             if (!visitorClass.isInterface()) {
     73                 newVisitMethod
     74                         .addAnnotation(new MarkerAnnotationExpr(new Name("Override")))
     75                         .addModifier(PUBLIC);
     76             }
     77             generateVisitMethodBody(node, newVisitMethod, compilationUnit);
     78         }
     79     }
     80 
     81     protected abstract void generateVisitMethodBody(BaseNodeMetaModel node, MethodDeclaration visitMethod, CompilationUnit compilationUnit);
     82 }
     83