1 package com.github.javaparser.generator.metamodel; 2 3 import com.github.javaparser.ast.*; 4 import com.github.javaparser.ast.body.*; 5 import com.github.javaparser.ast.comments.BlockComment; 6 import com.github.javaparser.ast.comments.Comment; 7 import com.github.javaparser.ast.comments.JavadocComment; 8 import com.github.javaparser.ast.comments.LineComment; 9 import com.github.javaparser.ast.expr.*; 10 import com.github.javaparser.ast.modules.*; 11 import com.github.javaparser.ast.stmt.*; 12 import com.github.javaparser.ast.type.*; 13 import com.github.javaparser.printer.PrettyPrinter; 14 import com.github.javaparser.printer.PrettyPrinterConfiguration; 15 import com.github.javaparser.utils.SourceRoot; 16 17 import java.io.IOException; 18 import java.lang.reflect.Field; 19 import java.nio.file.Path; 20 import java.nio.file.Paths; 21 import java.util.ArrayList; 22 import java.util.Comparator; 23 import java.util.List; 24 25 import static com.github.javaparser.utils.Utils.decapitalize; 26 27 public class MetaModelGenerator { 28 static final String BASE_NODE_META_MODEL = "BaseNodeMetaModel"; 29 private static List<Class<? extends Node>> ALL_NODE_CLASSES = new ArrayList<Class<? extends Node>>() {{ 30 /* Base classes go first, so we don't have to do any sorting to make sure 31 generated classes can refer to their base generated classes without 32 being afraid those are not initialized yet. */ 33 add(Node.class); 34 35 add(BodyDeclaration.class); 36 add(CallableDeclaration.class); 37 add(Statement.class); 38 add(Expression.class); 39 add(Type.class); 40 41 add(AnnotationExpr.class); 42 add(TypeDeclaration.class); 43 add(ReferenceType.class); 44 45 add(LiteralExpr.class); 46 add(LiteralStringValueExpr.class); 47 add(StringLiteralExpr.class); 48 49 add(ModuleDeclaration.class); 50 add(ModuleStmt.class); 51 52 // 53 add(ArrayCreationLevel.class); 54 add(CompilationUnit.class); 55 add(PackageDeclaration.class); 56 57 add(AnnotationDeclaration.class); 58 add(AnnotationMemberDeclaration.class); 59 add(ClassOrInterfaceDeclaration.class); 60 add(ConstructorDeclaration.class); 61 add(EnumConstantDeclaration.class); 62 add(EnumDeclaration.class); 63 add(FieldDeclaration.class); 64 add(InitializerDeclaration.class); 65 add(MethodDeclaration.class); 66 add(Parameter.class); 67 add(ReceiverParameter.class); 68 add(VariableDeclarator.class); 69 70 add(Comment.class); 71 add(BlockComment.class); 72 add(JavadocComment.class); 73 add(LineComment.class); 74 75 add(ArrayAccessExpr.class); 76 add(ArrayCreationExpr.class); 77 add(ArrayInitializerExpr.class); 78 add(AssignExpr.class); 79 add(BinaryExpr.class); 80 add(BooleanLiteralExpr.class); 81 add(CastExpr.class); 82 add(CharLiteralExpr.class); 83 add(ClassExpr.class); 84 add(ConditionalExpr.class); 85 add(DoubleLiteralExpr.class); 86 add(EnclosedExpr.class); 87 add(FieldAccessExpr.class); 88 add(InstanceOfExpr.class); 89 add(IntegerLiteralExpr.class); 90 add(LambdaExpr.class); 91 add(LongLiteralExpr.class); 92 add(MarkerAnnotationExpr.class); 93 add(MemberValuePair.class); 94 add(MethodCallExpr.class); 95 add(MethodReferenceExpr.class); 96 add(NameExpr.class); 97 add(Name.class); 98 add(NormalAnnotationExpr.class); 99 add(NullLiteralExpr.class); 100 add(ObjectCreationExpr.class); 101 add(SimpleName.class); 102 add(SingleMemberAnnotationExpr.class); 103 add(SuperExpr.class); 104 add(ThisExpr.class); 105 add(TypeExpr.class); 106 add(UnaryExpr.class); 107 add(VariableDeclarationExpr.class); 108 109 add(ImportDeclaration.class); 110 111 add(AssertStmt.class); 112 add(BlockStmt.class); 113 add(BreakStmt.class); 114 add(CatchClause.class); 115 add(ContinueStmt.class); 116 add(DoStmt.class); 117 add(EmptyStmt.class); 118 add(ExplicitConstructorInvocationStmt.class); 119 add(ExpressionStmt.class); 120 add(ForeachStmt.class); 121 add(ForStmt.class); 122 add(IfStmt.class); 123 add(LabeledStmt.class); 124 add(ReturnStmt.class); 125 add(SwitchEntryStmt.class); 126 add(SwitchStmt.class); 127 add(SynchronizedStmt.class); 128 add(ThrowStmt.class); 129 add(TryStmt.class); 130 add(LocalClassDeclarationStmt.class); 131 add(WhileStmt.class); 132 add(UnparsableStmt.class); 133 134 add(ArrayType.class); 135 add(ClassOrInterfaceType.class); 136 add(IntersectionType.class); 137 add(PrimitiveType.class); 138 add(TypeParameter.class); 139 add(UnionType.class); 140 add(UnknownType.class); 141 add(VoidType.class); 142 add(WildcardType.class); 143 add(VarType.class); 144 145 add(ModuleRequiresStmt.class); 146 add(ModuleExportsStmt.class); 147 add(ModuleProvidesStmt.class); 148 add(ModuleUsesStmt.class); 149 add(ModuleOpensStmt.class); 150 }}; 151 152 static String METAMODEL_PACKAGE = "com.github.javaparser.metamodel"; 153 main(String[] args)154 public static void main(String[] args) throws IOException, NoSuchMethodException { 155 if (args.length != 1) { 156 throw new RuntimeException("Need 1 parameter: the JavaParser source checkout root directory."); 157 } 158 final Path root = Paths.get(args[0], "..", "javaparser-core", "src", "main", "java"); 159 final SourceRoot sourceRoot = new SourceRoot(root); 160 sourceRoot.setPrinter(new PrettyPrinter(new PrettyPrinterConfiguration().setEndOfLineCharacter("\n"))::print); 161 162 new MetaModelGenerator().run(sourceRoot); 163 164 sourceRoot.saveAll(); 165 } 166 run(SourceRoot sourceRoot)167 private void run(SourceRoot sourceRoot) throws IOException, NoSuchMethodException { 168 final CompilationUnit javaParserMetaModel = sourceRoot.parse(METAMODEL_PACKAGE, "JavaParserMetaModel.java"); 169 170 generateNodeMetaModels(javaParserMetaModel, sourceRoot); 171 } 172 generateNodeMetaModels(CompilationUnit javaParserMetaModelCu, SourceRoot sourceRoot)173 private void generateNodeMetaModels(CompilationUnit javaParserMetaModelCu, SourceRoot sourceRoot) throws NoSuchMethodException { 174 final ClassOrInterfaceDeclaration metaModelCoid = javaParserMetaModelCu.getClassByName("JavaParserMetaModel").get(); 175 final NodeList<Statement> initializeNodeMetaModelsStatements = metaModelCoid.getMethodsByName("initializeNodeMetaModels").get(0).getBody().get().getStatements(); 176 final NodeList<Statement> initializePropertyMetaModelsStatements = metaModelCoid.getMethodsByName("initializePropertyMetaModels").get(0).getBody().get().getStatements(); 177 final NodeList<Statement> initializeConstructorParametersStatements = metaModelCoid.getMethodsByName("initializeConstructorParameters").get(0).getBody().get().getStatements(); 178 initializeNodeMetaModelsStatements.clear(); 179 initializePropertyMetaModelsStatements.clear(); 180 initializeConstructorParametersStatements.clear(); 181 182 metaModelCoid.getFields().stream().filter(f -> f.getVariable(0).getNameAsString().endsWith("MetaModel")).forEach(Node::remove); 183 final NodeMetaModelGenerator nodeMetaModelGenerator = new NodeMetaModelGenerator(); 184 for (Class<? extends Node> nodeClass : ALL_NODE_CLASSES) { 185 nodeMetaModelGenerator.generate(nodeClass, metaModelCoid, initializeNodeMetaModelsStatements, initializePropertyMetaModelsStatements, initializeConstructorParametersStatements, sourceRoot); 186 } 187 188 initializeNodeMetaModelsStatements.sort(Comparator.comparing(Node::toString)); 189 } 190 isNode(Class<?> c)191 static boolean isNode(Class<?> c) { 192 return Node.class.isAssignableFrom(c); 193 } 194 nodeMetaModelName(Class<?> c)195 static String nodeMetaModelName(Class<?> c) { 196 return c.getSimpleName() + "MetaModel"; 197 } 198 propertyMetaModelFieldName(Field field)199 static String propertyMetaModelFieldName(Field field) { 200 return field.getName() + "PropertyMetaModel"; 201 } 202 nodeMetaModelFieldName(Class<?> nodeClass)203 static String nodeMetaModelFieldName(Class<?> nodeClass) { 204 return decapitalize(nodeMetaModelName(nodeClass)); 205 } 206 207 } 208