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