diff --git a/pom.xml b/pom.xml index ae0f670a..9f184c4f 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,12 @@ asm-all [4.0.0,) + @@ -92,8 +98,8 @@ org.apache.maven.plugins maven-compiler-plugin - 9 - 9 + 8 + 8 diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java index 66cfb764..211da847 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -58,48 +58,55 @@ public class FCGenerator { params.add(gtvs.get(gtv.getName())); } - Optional hasSuperclass = availableClasses.stream().filter(cl -> forType.getSuperClass().getName().equals(cl.getClassName())).findAny(); - ClassOrInterface superClass; - if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception - { - superClass = ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(forType.getSuperClass().getName().toString())); - }else{ - superClass = hasSuperclass.get(); - } - /* - Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse - modifiziert werden - Beispie: Matrix extends Vector> - Den ersten Parameter mit Vector austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen - */ - //Hier vermerken, welche Typen im der Superklasse ausgetauscht werden müssen - Iterator itGenParams = superClass.getGenerics().iterator(); - Iterator itSetParams = forType.getSuperClass().getParaList().iterator(); - while(itGenParams.hasNext()){ - RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next(); - //In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen: - RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs)); - newGTVs.put(itGenParams.next().getName(), setSetType); - } - RefTypeOrTPHOrWildcardOrGeneric superType = forType.getSuperClass().acceptTV(new TypeExchanger(newGTVs)); - - RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken()); - RefTypeOrTPHOrWildcardOrGeneric t2 = superType; - - Pair ret = new Pair(t1, t2, PairOperator.SMALLER); - - List superTypes; - //Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse: - if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){ - superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER)); - }else{ - superTypes = getSuperTypes(superClass, availableClasses, newGTVs); - } + List superClasses = new ArrayList<>(); + superClasses.add(forType.getSuperClass()); + superClasses.addAll(forType.getSuperInterfaces()); List retList = new ArrayList<>(); - retList.add(ret); - retList.addAll(superTypes); + for(RefType superType : superClasses){ + Optional hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny(); + ClassOrInterface superClass; + if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception + { + superClass = ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(superType.getName().toString())); + }else{ + superClass = hasSuperclass.get(); + } + /* + Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse + modifiziert werden + Beispie: Matrix extends Vector> + Den ersten Parameter mit Vector austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen + */ + //Hier vermerken, welche Typen im der Superklasse ausgetauscht werden müssen + Iterator itGenParams = superClass.getGenerics().iterator(); + Iterator itSetParams = superType.getParaList().iterator(); + while(itSetParams.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next(); + //In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen: + RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs)); + newGTVs.put(itGenParams.next().getName(), setSetType); + } + + RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(newGTVs)); + + RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken()); + RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType; + + Pair ret = new Pair(t1, t2, PairOperator.SMALLER); + + List superTypes; + //Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse: + if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){ + superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER)); + }else{ + superTypes = getSuperTypes(superClass, availableClasses, newGTVs); + } + + retList.add(ret); + retList.addAll(superTypes); + } return retList; } diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index ed96d2e6..b7f14f19 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -73,6 +73,7 @@ public class SyntaxTreeGenerator{ } public SourceFile convert(Java8Parser.CompilationUnitContext ctx, PackageCrawler packageCrawler) throws ClassNotFoundException{ + if(ctx.packageDeclaration()!=null)this.pkgName = convert(ctx.packageDeclaration()); List classes = new ArrayList<>(); Map imports = GatherNames.getImports(ctx, packageCrawler); this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet()); @@ -89,6 +90,15 @@ public class SyntaxTreeGenerator{ return new SourceFile(this.pkgName, classes, this.imports); } + private String convert(Java8Parser.PackageDeclarationContext packageDeclarationContext) { + String ret = ""; + for(TerminalNode identifier : packageDeclarationContext.Identifier()){ + ret += identifier.getText()+"."; + } + ret = ret.substring(0, ret.length()-1); + return ret; + } + public Method convert(Java8Parser.MethodDeclarationContext methodDeclarationContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) { Java8Parser.MethodHeaderContext header = methodDeclarationContext.methodHeader(); int modifiers = SyntaxTreeGenerator.convert(methodDeclarationContext.methodModifier()); @@ -165,8 +175,8 @@ public class SyntaxTreeGenerator{ } } String className = this.pkgName + (this.pkgName.length()>0?".":"") + ctx.Identifier().getText(); - JavaClassName name = reg.getName(className); - if(! name.toString().equals(className)){ + JavaClassName name = reg.getName(className); //Holt den Package Namen mit dazu + if(! name.toString().equals(className)){ //Kommt die Klasse schon in einem anderen Package vor? throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString() ,ctx.getStart()); } @@ -203,20 +213,20 @@ public class SyntaxTreeGenerator{ } Boolean isInterface = false; - List implementedInterfaces = convert(ctx.superinterfaces(), generics); + List 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) { + 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<>(); + 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)); + ret.add((RefType) TypeGenerator.convert(interfaceType.classType(), reg, generics)); } return ret; } @@ -400,7 +410,7 @@ public class SyntaxTreeGenerator{ List fields = convertFields(ctx.interfaceBody()); List methods = convertMethods(ctx.interfaceBody(), name, superClass, generics); - List extendedInterfaces = convert(ctx.extendsInterfaces(), generics); + List extendedInterfaces = convert(ctx.extendsInterfaces(), generics); return new ClassOrInterface(modifiers, name, fields, methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, ctx.getStart()); @@ -423,7 +433,7 @@ public class SyntaxTreeGenerator{ return ret; } - private List convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) { + private List convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) { if(extendsInterfacesContext == null)return new ArrayList<>(); return convert(extendsInterfacesContext.interfaceTypeList(), generics); } diff --git a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index 5d5fc3e2..72097fc0 100644 --- a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -13,6 +13,7 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; import org.antlr.v4.runtime.Token; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -26,11 +27,11 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ private GenericDeclarationList genericClassParameters; private RefType superClass; protected boolean isInterface; - private List implementedInterfaces; + private List implementedInterfaces; private List constructors; public ClassOrInterface(int modifiers, JavaClassName name, List fielddecl, List methods, List constructors, GenericDeclarationList genericClassParameters, - RefType superClass, Boolean isInterface, List implementedInterfaces, Token offset){ + RefType superClass, Boolean isInterface, List implementedInterfaces, Token offset){ super(offset); this.modifiers = modifiers; this.name = name; @@ -101,4 +102,8 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ public void accept(ASTVisitor visitor) { visitor.visit(this); } + + public Collection getSuperInterfaces() { + return implementedInterfaces; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index de1bec99..52921c5d 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -57,7 +57,7 @@ public class ASTFactory { superClass = (RefType) createType(java.lang.Object.class, name, ""); } List implementedInterfaces = new ArrayList<>(); - for(java.lang.Class jreInterface : jreClass.getInterfaces()){ + for(Type jreInterface : jreClass.getGenericInterfaces()){ implementedInterfaces.add((RefType) createType(jreInterface, name, "")); } GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null); @@ -92,14 +92,21 @@ public class ASTFactory { return new Field(field.getName(), createType(field.getType(), jreClass, null), field.getModifiers(), new NullToken()); } + //private static RefType createType(Class classType) { + // return createClass(classType).getType(); + //} + private static de.dhbwstuttgart.syntaxtree.Constructor createConstructor(Constructor constructor, Class inClass) { String name = constructor.getName(); RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass, new JavaClassName(inClass.getName()), name); Parameter[] jreParams = constructor.getParameters(); + Type[] jreGenericParams = constructor.getGenericParameterTypes(); List params = new ArrayList<>(); - for(Parameter jreParam : jreParams){ - RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam.getType(),new JavaClassName(inClass.getName()), name); - params.add(new FormalParameter(jreParam.getName(),paramType, new NullToken())); + int i = 0; + for(Type jreParam : jreGenericParams){ + RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam,new JavaClassName(inClass.getName()), name); + params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); + i++; } ParameterList parameterList = new ParameterList(params, new NullToken()); Block block = new Block(new ArrayList(), new NullToken()); @@ -112,21 +119,26 @@ public class ASTFactory { } return new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset, new ArrayList<>()); - } - - //private static RefType createType(Class classType) { - // return createClass(classType).getType(); - //} + } public static Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass){ String name = jreMethod.getName(); RefTypeOrTPHOrWildcardOrGeneric returnType; - returnType = createType(jreMethod.getReturnType(),new JavaClassName(inClass.getName()), name); + Type jreRetType; + if(jreMethod.getGenericReturnType()!=null){ + jreRetType = jreMethod.getGenericReturnType(); + }else{ + jreRetType = jreMethod.getReturnType(); + } + returnType = createType(jreRetType,new JavaClassName(inClass.getName()), name); Parameter[] jreParams = jreMethod.getParameters(); + Type[] jreGenericParams = jreMethod.getGenericParameterTypes(); List params = new ArrayList<>(); - for(Parameter jreParam : jreParams){ - RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam.getType(),new JavaClassName(inClass.getName()), name); - params.add(new FormalParameter(jreParam.getName(),paramType, new NullToken())); + int i = 0; + for(Type jreParam : jreGenericParams){ + RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam,new JavaClassName(inClass.getName()), name); + params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); + i++; } ParameterList parameterList = new ParameterList(params, new NullToken()); Block block = new Block(new ArrayList(), new NullToken()); @@ -184,7 +196,12 @@ public class ASTFactory { params.add(createType(t, parentClass, parentMethod)); } } - RefType ret = new RefType(new JavaClassName(type.getTypeName()), params, new NullToken()); + String name = type.getTypeName(); + if(name.contains("<")){ //Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type + //Diese entfernen: + name = name.split("<")[0]; + } + RefType ret = new RefType(new JavaClassName(name), params, new NullToken()); return ret; } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java index 62867a26..e039dcbe 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.typeinference.assumptions; +import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; @@ -25,7 +26,7 @@ public class FieldAssumption extends Assumption{ } public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { - - return null; + //TODO + throw new NotImplementedException(); } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java index 4656318c..e17281e5 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -37,7 +37,8 @@ public class MethodAssumption extends Assumption{ return receiver; } - public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + public RefTypeOrTPHOrWildcardOrGeneric getReturnType(GenericsResolver resolver) { + if(retType instanceof GenericRefType)return resolver.resolve(retType); return retType; } diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 8d87218d..19f212bf 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -349,7 +349,7 @@ public class TYPEStmt implements StatementVisitor{ */ methodConstraint.add(new Pair(forMethod.receiver.getType(), assumption.getReceiverType(resolver), PairOperator.SMALLERDOT)); - methodConstraint.add(new Pair(assumption.getReturnType(), forMethod.getType(), + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver)); return methodConstraint; @@ -393,7 +393,7 @@ public class TYPEStmt implements StatementVisitor{ for(Method m : cl.getMethods()){ if(m.getName().equals(name) && m.getParameterList().getFormalparalist().size() == numArgs){ - RefTypeOrTPHOrWildcardOrGeneric retType = info.checkGTV(m.getReturnType()); + RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();//info.checkGTV(m.getReturnType()); ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(),info), createTypeScope(cl, m))); @@ -442,7 +442,7 @@ public class TYPEStmt implements StatementVisitor{ protected Constraint generateConstructorConstraint(NewClass forConstructor, MethodAssumption assumption, TypeInferenceBlockInformation info, GenericsResolver resolver){ Constraint methodConstraint = new Constraint(); - methodConstraint.add(new Pair(assumption.getReturnType(), forConstructor.getType(), + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), PairOperator.SMALLERDOT)); methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); return methodConstraint; diff --git a/test/finiteClosure/SuperInterfacesTest.java b/test/finiteClosure/SuperInterfacesTest.java new file mode 100644 index 00000000..0e1368c3 --- /dev/null +++ b/test/finiteClosure/SuperInterfacesTest.java @@ -0,0 +1,46 @@ +package finiteClosure; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SuperInterfacesTest { + @Test + public void test() throws ClassNotFoundException { + Collection classes = new ArrayList<>(); + classes.add(ASTFactory.createClass(TestClass.class)); + System.out.println(FCGenerator.toFC(classes)); + } + + @Test + public void testGeneric() throws ClassNotFoundException { + Collection classes = new ArrayList<>(); + classes.add(ASTFactory.createClass(TestClassGeneric.class)); + System.out.println(FCGenerator.toFC(classes)); + } +} + +class TestClass implements Test2, Test3{ + +} + +class TestClassGeneric implements Test4{ + +} + +interface Test2 { + +} + +interface Test3{ + +} + +interface Test4{ + +} \ No newline at end of file diff --git a/test/javFiles/MethodCallGenerics.jav b/test/javFiles/MethodCallGenerics.jav new file mode 100644 index 00000000..0d02509b --- /dev/null +++ b/test/javFiles/MethodCallGenerics.jav @@ -0,0 +1,14 @@ +import java.lang.String; + +class Generics { + // A mt1(A a, B b){ + B mt1(B a, B b){ + return mt1(a, a); + } +} + +class Test { + methode(String s){ + return new Generics().mt1(s,s); + } +} diff --git a/test/javFiles/Package.jav b/test/javFiles/Package.jav new file mode 100644 index 00000000..bbc1e51d --- /dev/null +++ b/test/javFiles/Package.jav @@ -0,0 +1,5 @@ +package strucType.input; + +class Neu +{ +} \ No newline at end of file diff --git a/test/javFiles/Vector.jav b/test/javFiles/Vector.jav index ef3533a6..40072fe4 100644 --- a/test/javFiles/Vector.jav +++ b/test/javFiles/Vector.jav @@ -3,10 +3,6 @@ import java.util.Vector; class MyVector{ id(x){ - return id2(x); -} - -id2(x){ -return id(x); + return (x.elementAt(0)); } } \ No newline at end of file diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index 87551476..ba004cb5 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -49,6 +49,11 @@ public class JavaTXCompilerTest { execute(new File(rootDirectory+"Generics.jav")); } @Test + public void genericsMethodCall() throws IOException, ClassNotFoundException { + TestResultSet result = execute(new File(rootDirectory+"MethodCallGenerics.jav")); + //TODO: Hier sollte der Rückgabetyp der Methode String sein + } + @Test public void faculty() throws IOException, ClassNotFoundException { execute(new File(rootDirectory+"Faculty.jav")); } @@ -61,6 +66,10 @@ public class JavaTXCompilerTest { execute(new File(rootDirectory+"Matrix.jav")); } @Test + public void packageTests() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Package.jav")); + } + @Test public void vector() throws IOException, ClassNotFoundException { execute(new File(rootDirectory+"Vector.jav")); } diff --git a/test/visualisation/ToString.java b/test/visualisation/ToString.java new file mode 100644 index 00000000..00b8ddea --- /dev/null +++ b/test/visualisation/ToString.java @@ -0,0 +1,5 @@ +package visualisation; + +public class ToString { + +}