package de.dhbwstuttgart.parser.SyntaxTreeGenerator; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.InvalidClassNameException; import de.dhbwstuttgart.parser.PackageCrawler; import de.dhbwstuttgart.parser.antlr.Java8Parser; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typecheck.*; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.TerminalNode; public class SyntaxTreeGenerator{ private JavaClassRegistry reg; private String pkgName = ""; List imports = new ArrayList(); public SyntaxTreeGenerator(JavaClassRegistry reg){ this.reg = reg; } public void setPackageName(Java8Parser.CompilationUnitContext ctx){ if(ctx.packageDeclaration() != null){ for(TerminalNode t : ctx.packageDeclaration().Identifier()){ this.pkgName = this.pkgName + "." + t.toString(); } this.pkgName = this.pkgName.substring(1); } } public void getNames(Java8Parser.CompilationUnitContext ctx){ if(this.pkgName == "") this.setPackageName(ctx); String nameString = ""; for (Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ if(typeDecl.interfaceDeclaration() != null){ if(typeDecl.interfaceDeclaration().normalInterfaceDeclaration() != null){ if(this.pkgName != ""){ nameString = this.pkgName + "." + typeDecl.interfaceDeclaration().normalInterfaceDeclaration().Identifier().toString(); } else{ nameString = typeDecl.interfaceDeclaration().normalInterfaceDeclaration().Identifier().toString(); } //Die Generic TypeParameter Definitionen ebenfalls an die JavaClassName-Registry anfügen: if(typeDecl.classDeclaration().normalClassDeclaration().typeParameters() != null){ for(Java8Parser.TypeParameterContext tp : typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter()){ this.reg.add(tp.Identifier().toString()); } } this.reg.add(nameString); } } else{ if(typeDecl.classDeclaration().normalClassDeclaration() != null){ if(this.pkgName != ""){ nameString = this.pkgName + "." + typeDecl.classDeclaration().normalClassDeclaration().Identifier().toString(); } else{ nameString = typeDecl.classDeclaration().normalClassDeclaration().Identifier().toString(); } //Die Generic TypeParameter Definitionen ebenfalls an die JavaClassName-Registry anfügen: if(typeDecl.classDeclaration().normalClassDeclaration().typeParameters() != null){ for(Java8Parser.TypeParameterContext tp : typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter()){ this.reg.add(tp.Identifier().toString()); } } this.reg.add(nameString); } } } } public JavaClassRegistry getReg(){ return this.reg; } // Converts type name to String. public String convertTypeName(Java8Parser.TypeNameContext ctx){ String ret; if(ctx.packageOrTypeName() == null){ ret = ctx.Identifier().toString(); } else{ ret = convertPackageOrTypeName(ctx.packageOrTypeName()) + "." + ctx.Identifier().toString(); } return ret; } // Converts PackageOrTypeName to String. public String convertPackageOrTypeName(Java8Parser.PackageOrTypeNameContext ctx){ String ret; if(ctx.packageOrTypeName() == null){ ret = ctx.Identifier().toString(); } else{ ret = convertPackageOrTypeName(ctx.packageOrTypeName()) + "." + ctx.Identifier().toString(); } return ret; } public void setImports(Java8Parser.CompilationUnitContext ctx) throws InvalidClassNameException { List newImports = new ArrayList(); for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ if(importDeclCtx.singleTypeImportDeclaration() != null){ newImports.add(convertSingleTypeImportDeclaration(importDeclCtx.singleTypeImportDeclaration())); } else if(importDeclCtx.typeImportOnDemandDeclaration() != null){ newImports.add(convertTypeImportOnDemandDeclaration(importDeclCtx.typeImportOnDemandDeclaration())); } else if(importDeclCtx.singleStaticImportDeclaration() != null){ newImports.add(convertSingleStaticImportDeclaration(importDeclCtx.singleStaticImportDeclaration())); } else{ newImports.add(convertStaticImportOnDemandDeclaration(importDeclCtx.staticImportOnDemandDeclaration())); } } this.imports.addAll(newImports); } private JavaClassName convertSingleTypeImportDeclaration(Java8Parser.SingleTypeImportDeclarationContext ctx) throws InvalidClassNameException{ String typeName = convertTypeName(ctx.typeName()); String packageName = getPackageFromClass(typeName); List classes = PackageCrawler.getClassNames(packageName); reg.add(typeName); JavaClassName ret = reg.getName(typeName); if(classes.contains(ret)){ return ret; } else{ throw new InvalidClassNameException(); } } private JavaClassName convertTypeImportOnDemandDeclaration(Java8Parser.TypeImportOnDemandDeclarationContext ctx){ return null; } private JavaClassName convertSingleStaticImportDeclaration(Java8Parser.SingleStaticImportDeclarationContext ctx){ return null; } private JavaClassName convertStaticImportOnDemandDeclaration(Java8Parser.StaticImportOnDemandDeclarationContext ctx){ return null; } private String getPackageFromClass(String cls){ String ret = ""; String[] parts = cls.split("\\."); for(int i = 0; i < parts.length - 1; i++){ ret = ret + "." + parts[i]; } ret = ret.substring(1); return ret; } public SourceFile convert(Java8Parser.CompilationUnitContext ctx){ List classes = new ArrayList<>(); this.getNames(ctx); for(Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ ClassOrInterface newClass; if(typeDecl.classDeclaration() != null){ newClass = convertClass(typeDecl.classDeclaration()); } else{ newClass = convertInterface(typeDecl.interfaceDeclaration()); } classes.add(newClass); } return new SourceFile(this.pkgName, classes, this.imports); } private ClassOrInterface convertClass(Java8Parser.ClassDeclarationContext ctx) { ClassOrInterface newClass; if(ctx.normalClassDeclaration() != null){ newClass = convertNormal(ctx.normalClassDeclaration()); } else{ newClass = convertEnum(ctx.enumDeclaration()); } return newClass; } private ClassOrInterface convertNormal(Java8Parser.NormalClassDeclarationContext ctx){ int modifiers = 0; if(ctx.classModifier() != null){ for(Java8Parser.ClassModifierContext mod : ctx.classModifier()){ int newModifier = convert(mod); modifiers += newModifier; } } JavaClassName name = convert(ctx.Identifier()); Block class_block = null; List fielddecl = convertFields(ctx.classBody()); List methods = convertMethods(ctx.classBody()); GenericDeclarationList genericClassParameters = null; Token offset = ctx.getStart(); RefType superClass ; if(ctx.superclass() != null){ superClass = convert(ctx.superclass()); }else{ superClass = new ASTFactory(reg).createObjectClass().getType(); } Boolean isInterface = false; List implementedInterfaces = null; return new ClassOrInterface(modifiers, name, fielddecl, methods, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); } private RefType convert(Java8Parser.SuperclassContext superclass) { throw new NotImplementedException(); } private List convertMethods(Java8Parser.ClassBodyContext classBodyContext) { List ret = new ArrayList<>(); for(Java8Parser.ClassBodyDeclarationContext classMember : classBodyContext.classBodyDeclaration()){ if(classMember.classMemberDeclaration() != null){ Java8Parser.ClassMemberDeclarationContext classMemberDeclarationContext = classMember.classMemberDeclaration(); if(classMemberDeclarationContext.fieldDeclaration() != null){ //Do nothing! }else if(classMemberDeclarationContext.methodDeclaration()!= null){ StatementGenerator stmtGen = new StatementGenerator(reg); ret.add(stmtGen.convert(classMemberDeclarationContext.methodDeclaration())); } } } return ret; } private List convertFields(Java8Parser.ClassBodyContext classBodyContext) { List ret = new ArrayList<>(); for(Java8Parser.ClassBodyDeclarationContext classMember : classBodyContext.classBodyDeclaration()){ if(classMember.classMemberDeclaration() != null){ Java8Parser.ClassMemberDeclarationContext classMemberDeclarationContext = classMember.classMemberDeclaration(); if(classMemberDeclarationContext.fieldDeclaration() != null){ ret.addAll(convert(classMember.classMemberDeclaration().fieldDeclaration())); }else if(classMemberDeclarationContext.methodDeclaration()!= null){ //Do nothing! } } } return ret; } public static int convert(List methodModifierContexts) { int ret = 0; for(Java8Parser.MethodModifierContext mod : methodModifierContexts){ if(mod.annotation() == null)convertModifier(mod.getText()); } return ret; } private List convert(Java8Parser.FieldDeclarationContext fieldDeclarationContext) { List ret = new ArrayList<>(); int modifiers = 0; for(Java8Parser.FieldModifierContext fieldModifierContext : fieldDeclarationContext.fieldModifier()){ modifiers+=(convert(fieldModifierContext)); } RefTypeOrTPHOrWildcardOrGeneric fieldType = TypeGenerator.convert(fieldDeclarationContext.unannType(), reg); for(Java8Parser.VariableDeclaratorContext varCtx : fieldDeclarationContext.variableDeclaratorList().variableDeclarator()){ String fieldName = convert(varCtx.variableDeclaratorId()); if(varCtx.variableInitializer() != null){ initializeField(fieldDeclarationContext); } else{ ret.add(new Field(fieldName,fieldType,modifiers,varCtx.getStart())); } } return ret; } public static String convert(Java8Parser.VariableDeclaratorIdContext variableDeclaratorIdContext) { return variableDeclaratorIdContext.getText(); } // Initialize a field by creating implicit constructor. private void initializeField(Java8Parser.FieldDeclarationContext ctx){ //TODO } public static int convertModifier(String modifier){ HashMap modifiers = new HashMap<>(); modifiers.put(Modifier.toString(Modifier.PUBLIC), Modifier.PUBLIC); modifiers.put(Modifier.toString(Modifier.PRIVATE), Modifier.PRIVATE); modifiers.put(Modifier.toString(Modifier.PROTECTED), Modifier.PROTECTED); modifiers.put(Modifier.toString(Modifier.ABSTRACT), Modifier.ABSTRACT); modifiers.put(Modifier.toString(Modifier.STATIC), Modifier.STATIC); modifiers.put(Modifier.toString(Modifier.STRICT), Modifier.STRICT); modifiers.put(Modifier.toString(Modifier.FINAL), Modifier.FINAL); modifiers.put(Modifier.toString(Modifier.TRANSIENT), Modifier.TRANSIENT); modifiers.put(Modifier.toString(Modifier.VOLATILE), Modifier.VOLATILE); modifiers.put(Modifier.toString(Modifier.SYNCHRONIZED), Modifier.SYNCHRONIZED); modifiers.put(Modifier.toString(Modifier.NATIVE), Modifier.NATIVE); modifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE); int ret = 0; for(String m : modifiers.keySet()){ if(modifier.startsWith(m))ret+=modifiers.get(m); } return ret; } private int convert(Java8Parser.ClassModifierContext ctx){ if(ctx.annotation() != null)return 0; return convertModifier(ctx.getText()); } private int convert(Java8Parser.FieldModifierContext ctx){ if(ctx.annotation() != null)return 0; return convertModifier(ctx.getText()); } /** Converts a TerminalNode to JavaClassName. If pkgName is set, it will be included like expected. **/ private JavaClassName convert(TerminalNode t){ String name = ""; if(this.pkgName != null){ name = this.pkgName + "." + t.toString(); } else{ name = t.toString(); } return this.reg.getName(name); } private ClassOrInterface convertEnum(Java8Parser.EnumDeclarationContext ctx){ return null; } private ClassOrInterface convertInterface(Java8Parser.InterfaceDeclarationContext ctx){ return null; } }