package de.dhbwstuttgart.parser.SyntaxTreeGenerator; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.parser.NullToken; 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.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typecheck.*; import java.io.File; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; //import jdk.internal.dynalink.support.TypeConverterFactory; import org.antlr.v4.runtime.CommonToken; 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 Nicht! an die JavaClassName-Registry anfügen: /* //Diese gelängen dadurch in den globalen Scope, was sie schließlich nicht sind 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 Nicht! an die JavaClassName-Registry anfügen: /* //Diese gelängen dadurch in den globalen Scope, was sie schließlich nicht sind 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 ClassNotFoundException { 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 ClassNotFoundException{ 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 ClassNotFoundException(); } } 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) throws ClassNotFoundException{ List classes = new ArrayList<>(); this.getNames(ctx); this.setImports(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); } public Method convert(Java8Parser.MethodDeclarationContext methodDeclarationContext, JavaClassName parentClass, GenericsRegistry generics) { Java8Parser.MethodHeaderContext header = methodDeclarationContext.methodHeader(); int modifiers = SyntaxTreeGenerator.convert(methodDeclarationContext.methodModifier()); GenericsRegistry localGenerics = createGenerics(methodDeclarationContext.methodHeader().typeParameters(), parentClass, header.methodDeclarator().Identifier().getText()); localGenerics.putAll(generics); return convert(modifiers, header, methodDeclarationContext.methodBody(),parentClass, localGenerics); } public Method convert(Java8Parser.InterfaceMethodDeclarationContext ctx, JavaClassName parentClass, GenericsRegistry generics) { Java8Parser.MethodHeaderContext header = ctx.methodHeader(); int modifiers = SyntaxTreeGenerator.convertInterfaceModifier(ctx.interfaceMethodModifier()); GenericsRegistry localGenerics = createGenerics(header.typeParameters(), parentClass, header.methodDeclarator().Identifier().getText()); localGenerics.putAll(generics); return convert(modifiers, header, ctx.methodBody(),parentClass, localGenerics); } private Method convert(int modifiers, Java8Parser.MethodHeaderContext header, Java8Parser.MethodBodyContext body, JavaClassName parentClass, GenericsRegistry localGenerics) { StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, new HashMap<>()); String name = header.methodDeclarator().Identifier().getText(); GenericDeclarationList gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); if(header.typeParameters() != null){ gtvDeclarations = TypeGenerator.convert(header.typeParameters(), parentClass, name,reg, localGenerics); }else{ gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); } RefTypeOrTPHOrWildcardOrGeneric retType; if(header.result() != null){ if(header.result().unannType() != null){ retType = TypeGenerator.convert(header.result().unannType(), reg, localGenerics); } else retType = new de.dhbwstuttgart.syntaxtree.type.Void(header.result().getStart()); }else{ retType = TypePlaceholder.fresh(header.getStart()); } ParameterList parameterList = stmtGen.convert(header.methodDeclarator().formalParameterList()); Block block = null; if(body.block() == null){ if(! Modifier.isAbstract(modifiers)){ //TODO: Error! Abstrakte Methode ohne abstrakt Keyword } }else{ block = stmtGen.convert(body.block()); } if(parentClass.equals(new JavaClassName(name))){ //TODO: Constructor darf nicht Rückgabetyp void bekommen: Hier als Rückgabetyp die Klasse inklusive generische Variablen //retType = TypeGenerator.convertTypeName(name, gtvDeclarations, header.getStart(), reg, localGenerics); return new Constructor(name, retType, modifiers, parameterList, block, gtvDeclarations, header.getStart()); }else{ return new Method(name, retType, modifiers, parameterList,block, gtvDeclarations, header.getStart()); } } 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 = reg.getName(ctx.Identifier().getText()); GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, ""); Token offset = ctx.getStart(); GenericDeclarationList genericClassParameters; if(ctx.typeParameters() == null){ genericClassParameters = createEmptyGenericDeclarationList(ctx.Identifier()); }else{ genericClassParameters = TypeGenerator.convert(ctx.typeParameters(), name, "",reg, generics); } List fielddecl = convertFields(ctx.classBody(), generics); List methods = convertMethods(ctx.classBody(), name, generics); List konstruktoren = new ArrayList<>(); for(int i = 0; i implementedInterfaces = convert(ctx.superinterfaces(), generics); return new ClassOrInterface(modifiers, name, fielddecl, methods, konstruktoren, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); } private List convert(Java8Parser.SuperinterfacesContext ctx, GenericsRegistry generics) { if(ctx == null)return new ArrayList<>(); return convert(ctx.interfaceTypeList(), generics); } private List convert(Java8Parser.InterfaceTypeListContext ctx, GenericsRegistry generics) { List ret = new ArrayList<>(); for(Java8Parser.InterfaceTypeContext interfaceType : ctx.interfaceType()){ ret.add(TypeGenerator.convert(interfaceType.classType(), reg, generics)); } return ret; } private Constructor generateStandardConstructor(String className, GenericDeclarationList classGenerics, Token offset){ RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); int modifiers = 0; ParameterList params = new ParameterList(new ArrayList<>(), offset); //TODO: Konstruktor muss Felder initialisieren: Block block = new Block(new ArrayList<>(), offset); return new Constructor(className, classType, modifiers, params, block, classGenerics, offset); } private RefType convert(Java8Parser.SuperclassContext superclass) { throw new NotImplementedException(); } private List convertMethods(Java8Parser.ClassBodyContext classBodyContext, JavaClassName parentClass, GenericsRegistry generics) { 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){ ret.add(this.convert(classMemberDeclarationContext.methodDeclaration(), parentClass, generics)); } } } return ret; } private List convertFields(Java8Parser.ClassBodyContext classBodyContext, GenericsRegistry generics) { 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(), generics)); }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; } public static int convertInterfaceModifier(List methodModifierContexts) { int ret = 0; for(Java8Parser.InterfaceMethodModifierContext mod : methodModifierContexts){ if(mod.annotation() == null)convertModifier(mod.getText()); } return ret; } private List convert(Java8Parser.FieldDeclarationContext fieldDeclarationContext, GenericsRegistry generics) { List ret = new ArrayList<>(); int modifiers = 0; for(Java8Parser.FieldModifierContext fieldModifierContext : fieldDeclarationContext.fieldModifier()){ modifiers+=(convert(fieldModifierContext)); } RefTypeOrTPHOrWildcardOrGeneric fieldType; if(fieldDeclarationContext.unannType() != null){ fieldType = TypeGenerator.convert(fieldDeclarationContext.unannType(), reg, generics); }else{ fieldType = TypePlaceholder.fresh(fieldDeclarationContext.getStart()); } 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 throw new NotImplementedException(); } 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.contains(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()); } private int convert(Java8Parser.InterfaceModifierContext ctx) { if(ctx.annotation() != null)return 0; return convertModifier(ctx.getText()); } private ClassOrInterface convertEnum(Java8Parser.EnumDeclarationContext ctx){ return null; } private ClassOrInterface convertInterface(Java8Parser.InterfaceDeclarationContext ctx){ if(ctx.normalInterfaceDeclaration() != null){ return convertNormal(ctx.normalInterfaceDeclaration()); }else{ throw new NotImplementedException(); } } private ClassOrInterface convertNormal(Java8Parser.NormalInterfaceDeclarationContext ctx) { int modifiers = 0; if(ctx.interfaceModifier() != null){ for( Java8Parser.InterfaceModifierContext mod : ctx.interfaceModifier()){ int newModifier = convert(mod); modifiers += newModifier; } } JavaClassName name = reg.getName(ctx.Identifier().getText()); GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, ""); List fields = convertFields(ctx.interfaceBody()); List methods = convertMethods(ctx.interfaceBody(), name, generics); GenericDeclarationList genericParams; if(ctx.typeParameters() != null){ genericParams = TypeGenerator.convert(ctx.typeParameters(), name, "",reg, generics); }else{ genericParams = createEmptyGenericDeclarationList(ctx.Identifier()); } RefType superClass = new ASTFactory(reg).createObjectClass().getType(); List extendedInterfaces = convert(ctx.extendsInterfaces(), generics); return new ClassOrInterface(modifiers, name, fields, methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, ctx.getStart()); } private GenericDeclarationList createEmptyGenericDeclarationList(TerminalNode classNameIdentifier) { CommonToken gtvOffset = new CommonToken(classNameIdentifier.getSymbol()); gtvOffset.setCharPositionInLine(gtvOffset.getCharPositionInLine()+classNameIdentifier.getText().length()); gtvOffset.setStartIndex(gtvOffset.getStopIndex()+1); return new GenericDeclarationList(new ArrayList<>(), gtvOffset); } private GenericsRegistry createGenerics(Java8Parser.TypeParametersContext ctx, JavaClassName parentClass, String parentMethod) { GenericsRegistry ret = new GenericsRegistry(); if(ctx == null || ctx.typeParameterList() == null)return ret; for(Java8Parser.TypeParameterContext tp : ctx.typeParameterList().typeParameter()){ TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret); } return ret; } private List convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) { if(extendsInterfacesContext == null)return new ArrayList<>(); return convert(extendsInterfacesContext.interfaceTypeList(), generics); } private List convertMethods(Java8Parser.InterfaceBodyContext interfaceBodyContext, JavaClassName parentClass, GenericsRegistry generics) { List ret = new ArrayList<>(); for(Java8Parser.InterfaceMemberDeclarationContext member : interfaceBodyContext.interfaceMemberDeclaration()){ if(member.interfaceMethodDeclaration() != null){ ret.add(this.convert(member.interfaceMethodDeclaration(), parentClass, generics)); //new Method(name, type, modifier, params, null, genericDecls, member.interfaceMethodDeclaration().getStart()); }else{ throw new NotImplementedException(); } } return ret; } private List convertFields(Java8Parser.InterfaceBodyContext interfaceBodyContext) { List ret = new ArrayList<>(); for(Java8Parser.InterfaceMemberDeclarationContext member : interfaceBodyContext.interfaceMemberDeclaration()){ if(member.constantDeclaration() != null){ //TODO: Erstelle hier ein Feld! throw new NotImplementedException(); } } return ret; } }