From 7e88ddc3d577b427bd6f4d79d752f26ca9c3b1a3 Mon Sep 17 00:00:00 2001 From: Aldaron7 Date: Wed, 14 Mar 2018 13:02:10 +0100 Subject: [PATCH] Type implementiert --- .../strucTypes/CheckTypeVisitor.java | 32 --- .../strucTypes/ClassOrInterfaceFactory.java | 25 ++ .../strucTypes/DefaultASTVisitor.java | 2 +- .../dhbwstuttgart/strucTypes/StrucTYPE.java | 50 +++- .../strucTypes/StrucTypeVisitor.java | 187 ------------- src/de/dhbwstuttgart/strucTypes/TYPEExpr.java | 250 +++++++++--------- .../strucTypes/TypeAssumptions.java | 5 - .../dhbwstuttgart/strucTypes/TypeExtract.java | 98 +++++++ .../{ => constraint}/ConstraintsSet.java | 8 +- .../{ => constraint}/FieldConstraint.java | 23 +- .../{ => constraint}/MethodConstraint.java | 26 +- .../{ => constraint}/SubTypeConstraint.java | 17 +- .../printutils/PrintConstraints.java | 42 +++ .../printutils/PrintInferredTypes.java | 14 + .../{ => printutils}/SyntaxTreePrinter.java | 19 +- test/strucType/TestStrucType.java | 49 ++++ test/strucType/TestSyntaxTreePrinter.java | 2 +- test/strucType/javFiles/testCast.jav | 8 +- test/strucType/javFiles/testFieldMethod.jav | 5 + test/strucType/javFiles/testFieldVar.jav | 2 + test/strucType/javFiles/testLocalVar.jav | 4 +- test/strucType/javFiles/testNew.jav | 8 +- test/strucType/javFiles/testPaperExample.jav | 2 + test/strucType/typedtestclasses/A.java | 19 ++ test/strucType/typedtestclasses/A2.java | 9 + test/strucType/typedtestclasses/B.java | 20 ++ test/strucType/typedtestclasses/C.java | 27 ++ 27 files changed, 560 insertions(+), 393 deletions(-) delete mode 100644 src/de/dhbwstuttgart/strucTypes/CheckTypeVisitor.java create mode 100644 src/de/dhbwstuttgart/strucTypes/ClassOrInterfaceFactory.java delete mode 100644 src/de/dhbwstuttgart/strucTypes/StrucTypeVisitor.java delete mode 100644 src/de/dhbwstuttgart/strucTypes/TypeAssumptions.java create mode 100644 src/de/dhbwstuttgart/strucTypes/TypeExtract.java rename src/de/dhbwstuttgart/strucTypes/{ => constraint}/ConstraintsSet.java (72%) rename src/de/dhbwstuttgart/strucTypes/{ => constraint}/FieldConstraint.java (71%) rename src/de/dhbwstuttgart/strucTypes/{ => constraint}/MethodConstraint.java (70%) rename src/de/dhbwstuttgart/strucTypes/{ => constraint}/SubTypeConstraint.java (78%) create mode 100644 src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java create mode 100644 src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java rename src/de/dhbwstuttgart/strucTypes/{ => printutils}/SyntaxTreePrinter.java (92%) create mode 100644 test/strucType/TestStrucType.java create mode 100644 test/strucType/typedtestclasses/A.java create mode 100644 test/strucType/typedtestclasses/A2.java create mode 100644 test/strucType/typedtestclasses/B.java create mode 100644 test/strucType/typedtestclasses/C.java diff --git a/src/de/dhbwstuttgart/strucTypes/CheckTypeVisitor.java b/src/de/dhbwstuttgart/strucTypes/CheckTypeVisitor.java deleted file mode 100644 index 45b05013..00000000 --- a/src/de/dhbwstuttgart/strucTypes/CheckTypeVisitor.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.dhbwstuttgart.strucTypes; - -import de.dhbwstuttgart.syntaxtree.type.RefType; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; - -public class CheckTypeVisitor extends DefaultASTVisitor { - - private boolean isTypeVariable; - private String name; - - @Override - public void visit(RefType refType) { - this.isTypeVariable = true; - this.name = refType.getName().toString(); - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - this.isTypeVariable = false; - this.name = typePlaceholder.getName(); - } - - public boolean isTypeVariable() { - return isTypeVariable; - } - - public String getName() { - return name; - } - - -} diff --git a/src/de/dhbwstuttgart/strucTypes/ClassOrInterfaceFactory.java b/src/de/dhbwstuttgart/strucTypes/ClassOrInterfaceFactory.java new file mode 100644 index 00000000..56fb4eb2 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/ClassOrInterfaceFactory.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.strucTypes; + +import java.util.Optional; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.RefType; + +public class ClassOrInterfaceFactory { + + public static Optional createClass(JavaClassName name) { + try { + return Optional.of(ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(name.toString()))); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return Optional.empty(); + } + + public static Optional createClass(RefType refType) { + return ClassOrInterfaceFactory.createClass(refType.getName()); + } +} diff --git a/src/de/dhbwstuttgart/strucTypes/DefaultASTVisitor.java b/src/de/dhbwstuttgart/strucTypes/DefaultASTVisitor.java index 6514f882..3ad90069 100644 --- a/src/de/dhbwstuttgart/strucTypes/DefaultASTVisitor.java +++ b/src/de/dhbwstuttgart/strucTypes/DefaultASTVisitor.java @@ -47,7 +47,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -public class DefaultASTVisitor implements ASTVisitor { +public abstract class DefaultASTVisitor implements ASTVisitor { @Override public void visit(ArgumentList argumentList) { diff --git a/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java b/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java index e5a07769..c69d6c66 100644 --- a/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java +++ b/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java @@ -1,16 +1,52 @@ package de.dhbwstuttgart.strucTypes; +import java.util.HashMap; +import java.util.Map; + +import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -public class StrucTYPE { +public class StrucTYPE extends DefaultASTVisitor { - private TypeAssumptions assumptions; private SourceFile sourceFile; - - public StrucTYPE(TypeAssumptions assumptions, SourceFile sourceFile) { - this.assumptions = assumptions; + private ConstraintsSet constraintsSet = new ConstraintsSet(); + private Map inferredTypes = new HashMap<>(); + + public StrucTYPE(SourceFile sourceFile) { this.sourceFile = sourceFile; } - - + + public ConstraintsSet getConstraints() { + for (ClassOrInterface cls : sourceFile.getClasses()) { + TYPEExpr typeExpr = new TYPEExpr(); + cls.accept(typeExpr); + this.evaluateTypeExpr(typeExpr); + cls.getMethods().forEach(m -> m.accept(this)); + } + return this.constraintsSet; + } + + public Map getInferredTypes() { + return inferredTypes; + } + + @Override + public void visit(Method method) { + // Es gibt nur ein Return Statement + Expression retexpr = ((Return) method.block.statements.get(0)).retexpr; + // ordnet dem Methodentyp den Returntyp zu [sigma(Mt)] + this.inferredTypes.put((TypePlaceholder) method.getReturnType(), retexpr.getType()); + } + + private void evaluateTypeExpr(TYPEExpr typeExpr) { + this.inferredTypes.putAll(typeExpr.getInferredTypes()); + this.constraintsSet.addConstraintsSet(typeExpr.getConstraints()); + } + } diff --git a/src/de/dhbwstuttgart/strucTypes/StrucTypeVisitor.java b/src/de/dhbwstuttgart/strucTypes/StrucTypeVisitor.java deleted file mode 100644 index 1c3689e8..00000000 --- a/src/de/dhbwstuttgart/strucTypes/StrucTypeVisitor.java +++ /dev/null @@ -1,187 +0,0 @@ -package de.dhbwstuttgart.strucTypes; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; -import de.dhbwstuttgart.syntaxtree.ASTVisitor; -import de.dhbwstuttgart.syntaxtree.Constructor; -import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; -import de.dhbwstuttgart.syntaxtree.GenericTypeVar; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.Binary; -import de.dhbwstuttgart.syntaxtree.statement.DoStmt; -import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; -import de.dhbwstuttgart.syntaxtree.statement.ForStmt; -import de.dhbwstuttgart.syntaxtree.statement.IfStmt; -import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; -import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; -import de.dhbwstuttgart.syntaxtree.statement.NewArray; -import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; -import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; -import de.dhbwstuttgart.syntaxtree.statement.Super; -import de.dhbwstuttgart.syntaxtree.statement.SuperCall; -import de.dhbwstuttgart.syntaxtree.statement.UnaryPlus; -import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; -import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; -import de.dhbwstuttgart.syntaxtree.statement.literal.Null; -import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; -import de.dhbwstuttgart.syntaxtree.type.GenericRefType; -import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; - -public abstract class StrucTypeVisitor implements ASTVisitor { - @Override - public void visit(LambdaExpression lambdaExpression) { - throw new NotImplementedException(); - } - - @Override - public void visit(Assign assign) { - throw new NotImplementedException(); - - } - - @Override - public void visit(Binary binary) { - throw new NotImplementedException(); - - } - - @Override - public void visit(EmptyStmt emptyStmt) { - throw new NotImplementedException(); - - } - - @Override - public void visit(ForStmt forStmt) { - throw new NotImplementedException(); - - } - - @Override - public void visit(IfStmt ifStmt) { - throw new NotImplementedException(); - - } - - @Override - public void visit(InstanceOf instanceOf) { - throw new NotImplementedException(); - - } - - @Override - public void visit(LocalVarDecl localVarDecl) { - throw new NotImplementedException(); - - } - - @Override - public void visit(NewArray newArray) { - throw new NotImplementedException(); - - } - - @Override - public void visit(ReturnVoid aReturn) { - throw new NotImplementedException(); - - } - - @Override - public void visit(StaticClassName staticClassName) { - throw new NotImplementedException(); - - } - - @Override - public void visit(Super aSuper) { - throw new NotImplementedException(); - - } - - @Override - public void visit(UnaryPlus unaryPlus) { - throw new NotImplementedException(); - - } - - @Override - public void visit(WhileStmt whileStmt) { - throw new NotImplementedException(); - - } - - @Override - public void visit(DoStmt whileStmt) { - throw new NotImplementedException(); - - } - - @Override - public void visit(Null aNull) { - throw new NotImplementedException(); - - } - - @Override - public void visit(Literal literal) { - throw new NotImplementedException(); - - } - - @Override - public void visit(AssignToField assignLeftSide) { - throw new NotImplementedException(); - - } - - @Override - public void visit(AssignToLocal assignLeftSide) { - throw new NotImplementedException(); - - } - - @Override - public void visit(SuperCall superCall) { - throw new NotImplementedException(); - - } - - @Override - public void visit(GenericTypeVar genericTypeVar) { - throw new NotImplementedException(); - - } - - @Override - public void visit(GenericDeclarationList genericTypeVars) { - throw new NotImplementedException(); - - } - - @Override - public void visit(Constructor field) { - throw new NotImplementedException(); - - } - - @Override - public void visit(SuperWildcardType superWildcardType) { - throw new NotImplementedException(); - - } - - @Override - public void visit(ExtendsWildcardType extendsWildcardType) { - throw new NotImplementedException(); - - } - - @Override - public void visit(GenericRefType genericRefType) { - throw new NotImplementedException(); - - } -} diff --git a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java index aee55872..f5e4fa4e 100644 --- a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java +++ b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java @@ -1,188 +1,192 @@ package de.dhbwstuttgart.strucTypes; -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; -import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; +import de.dhbwstuttgart.strucTypes.constraint.FieldConstraint; +import de.dhbwstuttgart.strucTypes.constraint.MethodConstraint; +import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; -import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.Field; -import de.dhbwstuttgart.syntaxtree.FormalParameter; -import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; -import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.Method; -import de.dhbwstuttgart.syntaxtree.ParameterList; -import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.Binary; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.CastExpr; -import de.dhbwstuttgart.syntaxtree.statement.DoStmt; -import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; import de.dhbwstuttgart.syntaxtree.statement.FieldVar; -import de.dhbwstuttgart.syntaxtree.statement.ForStmt; -import de.dhbwstuttgart.syntaxtree.statement.IfStmt; -import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; import de.dhbwstuttgart.syntaxtree.statement.LocalVar; -import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; import de.dhbwstuttgart.syntaxtree.statement.MethodCall; -import de.dhbwstuttgart.syntaxtree.statement.NewArray; import de.dhbwstuttgart.syntaxtree.statement.NewClass; import de.dhbwstuttgart.syntaxtree.statement.Return; -import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; -import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; -import de.dhbwstuttgart.syntaxtree.statement.Super; -import de.dhbwstuttgart.syntaxtree.statement.SuperCall; import de.dhbwstuttgart.syntaxtree.statement.This; -import de.dhbwstuttgart.syntaxtree.statement.UnaryPlus; -import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; -import de.dhbwstuttgart.syntaxtree.statement.literal.Literal; -import de.dhbwstuttgart.syntaxtree.statement.literal.Null; -import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; -import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -public class TYPEExpr extends StrucTypeVisitor { +public class TYPEExpr extends DefaultASTVisitor { - private TypeAssumptions assumptions; - private ConstraintsSet constraints; - - public TYPEExpr(TypeAssumptions assumptions) { - this.assumptions = assumptions; + private ClassOrInterface aThis; + private ConstraintsSet constraints = new ConstraintsSet(); + private Map inferredTypes = new HashMap<>(); + + public TYPEExpr() { } - - public ConstraintsSet getConstraints(){ + + public ConstraintsSet getConstraints() { return this.constraints; } - - @Override - public void visit(SourceFile sourceFile) { - // TODO Auto-generated method stub - throw new NotImplementedException(); + + public Map getInferredTypes() { + return inferredTypes; } @Override public void visit(ClassOrInterface classOrInterface) { - // TODO Auto-generated method stub - throw new NotImplementedException(); - - } - - @Override - public void visit(Field field) { - // TODO Auto-generated method stub - throw new NotImplementedException(); - - } - - @Override - public void visit(Method method) { - // TODO Auto-generated method stub - throw new NotImplementedException(); - - } - - @Override - public void visit(ParameterList formalParameters) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(FormalParameter formalParameter) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(Block block) { - // TODO Auto-generated method stub - throw new NotImplementedException(); - - } - - @Override - public void visit(Return aReturn) { - // TODO Auto-generated method stub - throw new NotImplementedException(); - - } - - @Override - public void visit(ExpressionReceiver expressionReceiver) { - // TODO Auto-generated method stub - + this.aThis = classOrInterface; + classOrInterface.getMethods().forEach(m -> m.accept(this)); } @Override public void visit(LocalVar localVar) { - // keine neuen Constraints - + // keine neuen Constraints. Typisierung bereits im SyntaxTree vorhanden. } @Override public void visit(FieldVar fieldVar) { fieldVar.receiver.accept(this); - CheckTypeVisitor fieldTypeVisitor = new CheckTypeVisitor(); - fieldVar.getType().accept(fieldTypeVisitor); - //TODO check ty in Ass && rty f in fields(ty) - if(!fieldTypeVisitor.isTypeVariable()){} // keine neuen Constraints - else{ - FieldConstraint fieldConstraint = new FieldConstraint(fieldVar.receiver.getType(), fieldVar.getType(), fieldVar.fieldVarName); + + // Löst Typen zwischen Feld und Feldvariable auf + this.inferFieldVarTypes(fieldVar); + + // Ermittelt den Typ ty von fieldVar.receiver und fields(f) + TypeExtract fieldTypeVisitor = new TypeExtract(); + fieldVar.receiver.getType().accept(fieldTypeVisitor); + + if (!fieldTypeVisitor.isTypeVariable()) { + fieldTypeVisitor.getField(fieldVar.fieldVarName).ifPresent( + f -> this.inferredTypes.put((TypePlaceholder) fieldVar.receiver.getType(), (RefType) f.getType())); + } // keine neuen Constraints + else { + FieldConstraint fieldConstraint = new FieldConstraint(fieldVar.receiver.getType(), fieldVar.fieldVarName, + fieldVar.getType()); this.constraints.addConstraint(fieldConstraint); } - + } + + private void inferFieldVarTypes(FieldVar fieldVar) { + if (fieldVar.receiver instanceof This) { + this.aThis.getFieldDecl().stream().filter(f -> f.getName().equals(fieldVar.fieldVarName)) + // keine statische Polymorphie zugelassen + .findFirst() + .ifPresent(f -> this.inferredTypes.put((TypePlaceholder) fieldVar.getType(), f.getType())); + } } @Override public void visit(MethodCall methodCall) { - // TODO Auto-generated method stub - + methodCall.receiver.accept(this); + methodCall.arglist.accept(this); + + // ermittelt den Typ ty0 von methodCall.receiver und mtype(m, ty0) + TypeExtract methodTypeVisitor = new TypeExtract(); + methodCall.receiver.getType().accept(methodTypeVisitor); + + List arguments = methodCall.getArgumentList().getArguments(); + if (!methodTypeVisitor.isTypeVariable()) { + methodTypeVisitor.getMethod(methodCall.name, arguments.size()).ifPresent(m -> { + for (int i = 0; i < arguments.size(); i++) { + this.constraints.addConstraint(new SubTypeConstraint(arguments.get(i).getType(), + m.getParameterList().getParameterAt(i).getType())); + } + this.inferredTypes.put((TypePlaceholder) methodCall.getType(), (RefType) m.getReturnType()); + }); + } else { + MethodConstraint methodConstraint = new MethodConstraint(methodCall.receiver.getType(), methodCall.name, + new ArrayList(), methodCall.getType()); + arguments.forEach(e -> methodConstraint.addArguments(e.getType())); + this.constraints.addConstraint(methodConstraint); + } } @Override public void visit(ArgumentList argumentList) { - // TODO Auto-generated method stub - + argumentList.getArguments().forEach(a -> a.accept(this)); } @Override public void visit(CastExpr castExpr) { - // TODO Auto-generated method stub - + castExpr.expr.accept(this); + // TODO RefType equals implementieren + if (((RefType) castExpr.getType()).getName().equals(this.aThis.getClassName())) { + // keine neuen Constraints + } else { + // TODO implement generics + } } @Override public void visit(NewClass newClass) { - // TODO Auto-generated method stub - + newClass.getArgumentList().accept(this); + RefType type = (RefType) newClass.getType(); + TypeExtract typeExtract = new TypeExtract(); + // TODO RefType equals implementieren + if (type.getName().equals(this.aThis.getType().getName())) { + this.aThis.accept(typeExtract); + } else { + type.accept(typeExtract); + // TODO implement generics + } + this.createNewClassSubTypeConstraints(newClass, typeExtract); } - @Override - public void visit(RefType refType) { - // TODO Auto-generated method stub - - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - // TODO Auto-generated method stub - + private void createNewClassSubTypeConstraints(NewClass newClass, TypeExtract typeExtract) { + List arguments = newClass.getArgumentList().getArguments(); + List fields = typeExtract.getFields(); + int argumentsSize = arguments.size(); + int fieldsSize = fields.size(); + if (argumentsSize != fieldsSize) { + throw new IllegalArgumentException(String.format( + "The number of fields (%d) in %s doesn't match the number of arguments (%d) passed to its constructor.", + fieldsSize, newClass.name, argumentsSize)); + } + for (int i = 0; i < argumentsSize; i++) { + SubTypeConstraint subTypeConstraint = new SubTypeConstraint(arguments.get(i).getType(), + fields.get(i).getType()); + this.constraints.addConstraint(subTypeConstraint); + } } @Override public void visit(This aThis) { - // TODO Auto-generated method stub - + if (this.aThis != null) { + this.inferredTypes.put((TypePlaceholder) aThis.getType(), (RefType) this.aThis.getType()); + } + } + @Override + public void visit(ExpressionReceiver expressionReceiver) { + expressionReceiver.expr.accept(this); + } + + @Override + public void visit(Method method) { + method.block.accept(this); + } + + @Override + public void visit(Block block) { + // Es gibt nur ein Statement: Return + block.getStatements().forEach(s -> s.accept(this)); + } + + @Override + public void visit(Return aReturn) { + aReturn.retexpr.accept(this); + } } - diff --git a/src/de/dhbwstuttgart/strucTypes/TypeAssumptions.java b/src/de/dhbwstuttgart/strucTypes/TypeAssumptions.java deleted file mode 100644 index 3397fd29..00000000 --- a/src/de/dhbwstuttgart/strucTypes/TypeAssumptions.java +++ /dev/null @@ -1,5 +0,0 @@ -package de.dhbwstuttgart.strucTypes; - -public class TypeAssumptions { - -} diff --git a/src/de/dhbwstuttgart/strucTypes/TypeExtract.java b/src/de/dhbwstuttgart/strucTypes/TypeExtract.java new file mode 100644 index 00000000..47fbc5ec --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/TypeExtract.java @@ -0,0 +1,98 @@ +package de.dhbwstuttgart.strucTypes; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * Extrahiert die typisierten Felder und Methoden von ClassOrInterface bzw. von + * RefType rekursiv über alle Superklassen und implementierten Interfaces. + * + * @author mvr + * + */ +public class TypeExtract extends DefaultASTVisitor { + + private List fields = new ArrayList<>(); + private List methods = new ArrayList<>(); + private List constructors = new ArrayList<>(); + private boolean typeVariable = false; + private boolean initialClass = true; + + public List getFields() { + return this.fields; + } + + public List getMethods() { + return this.methods; + } + + public List getConstructors() { + return constructors; + } + + public Optional getField(String fieldName) { + return this.fields.stream().filter(f -> f.getName().equals(fieldName)) + // keine statische Polymorphie zugelassen + .findFirst(); + } + + public Optional getMethod(String methodName, int parameterCount) { + return this.methods.stream() + .filter(m -> m.getName().equals(methodName) && m.getParameterList().getFormalparalist().size() == parameterCount) + // keine statische Polymorphie zugelassen + .findFirst(); + } + + public boolean isTypeVariable() { + return this.typeVariable; + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + classOrInterface.getFieldDecl().forEach(f -> f.accept(this)); + classOrInterface.getMethods().forEach(m -> m.accept(this)); + classOrInterface.getConstructors().forEach(c -> {if(c != null && this.initialClass) c.accept(this);}); + this.initialClass = false; + // superClass(Object) -> Object => unendliche Rekursionstiefe! + if (!classOrInterface.getClassName().equals(new JavaClassName("java.lang.Object"))) { + classOrInterface.getSuperClass().accept(this); + classOrInterface.implementedInterfaces.forEach(i -> i.accept(this)); + } + } + + @Override + public void visit(RefType refType) { + this.typeVariable = false; + ClassOrInterfaceFactory.createClass(refType).ifPresent(c -> c.accept(this)); + } + + @Override + public void visit(Field field) { + this.fields.add(field); + } + + @Override + public void visit(Method method) { + this.methods.add(method); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + this.typeVariable = true; + } + + @Override + public void visit(Constructor constructor) { + this.constructors.add(constructor); + } + +} diff --git a/src/de/dhbwstuttgart/strucTypes/ConstraintsSet.java b/src/de/dhbwstuttgart/strucTypes/constraint/ConstraintsSet.java similarity index 72% rename from src/de/dhbwstuttgart/strucTypes/ConstraintsSet.java rename to src/de/dhbwstuttgart/strucTypes/constraint/ConstraintsSet.java index 710329ad..6024e674 100644 --- a/src/de/dhbwstuttgart/strucTypes/ConstraintsSet.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/ConstraintsSet.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.strucTypes; +package de.dhbwstuttgart.strucTypes.constraint; import java.util.ArrayList; import java.util.List; @@ -39,6 +39,12 @@ public class ConstraintsSet { this.methodConstraints.add(constraint); } + public void addConstraintsSet(ConstraintsSet constraintsSet){ + constraintsSet.getSubTypeConstraints().forEach(this::addConstraint); + constraintsSet.getFieldConstraints().forEach(this::addConstraint); + constraintsSet.getMethodConstraints().forEach(this::addConstraint); + } + } diff --git a/src/de/dhbwstuttgart/strucTypes/FieldConstraint.java b/src/de/dhbwstuttgart/strucTypes/constraint/FieldConstraint.java similarity index 71% rename from src/de/dhbwstuttgart/strucTypes/FieldConstraint.java rename to src/de/dhbwstuttgart/strucTypes/constraint/FieldConstraint.java index e569b83a..014491af 100644 --- a/src/de/dhbwstuttgart/strucTypes/FieldConstraint.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/FieldConstraint.java @@ -1,18 +1,24 @@ -package de.dhbwstuttgart.strucTypes; +package de.dhbwstuttgart.strucTypes.constraint; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +/** + * fc(c, f, c') : Klasse/Typ c hat ein Feld f mit Typ c' + * + * @author mvr + * + */ public class FieldConstraint { private RefTypeOrTPHOrWildcardOrGeneric classType; - private RefTypeOrTPHOrWildcardOrGeneric fieldType; private String fieldName; - - public FieldConstraint(RefTypeOrTPHOrWildcardOrGeneric classType, RefTypeOrTPHOrWildcardOrGeneric fieldType, - String fieldName) { + private RefTypeOrTPHOrWildcardOrGeneric fieldType; + + public FieldConstraint(RefTypeOrTPHOrWildcardOrGeneric classType, String fieldName, + RefTypeOrTPHOrWildcardOrGeneric fieldType) { this.classType = classType; - this.fieldType = fieldType; this.fieldName = fieldName; + this.fieldType = fieldType; } public RefTypeOrTPHOrWildcardOrGeneric getClassType() { @@ -26,8 +32,5 @@ public class FieldConstraint { public String getFieldName() { return fieldName; } - - - - + } diff --git a/src/de/dhbwstuttgart/strucTypes/MethodConstraint.java b/src/de/dhbwstuttgart/strucTypes/constraint/MethodConstraint.java similarity index 70% rename from src/de/dhbwstuttgart/strucTypes/MethodConstraint.java rename to src/de/dhbwstuttgart/strucTypes/constraint/MethodConstraint.java index 07d04037..0aa6846f 100644 --- a/src/de/dhbwstuttgart/strucTypes/MethodConstraint.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/MethodConstraint.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.strucTypes; +package de.dhbwstuttgart.strucTypes.constraint; import java.util.List; @@ -7,15 +7,22 @@ import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +/** + * mc(c, m, C, (c', C')) : Klasse/Typ c hat Methode m mit Argumenten von Typ C + * mit Rückgabewert c' und Subtyp-Constraints C <. C' wobei C = {c1,... , cn) + * + * @author mvr + * + */ public class MethodConstraint { private RefTypeOrTPHOrWildcardOrGeneric classType; private RefTypeOrTPHOrWildcardOrGeneric returnType; private String methodName; private List arguments; - - public MethodConstraint(RefTypeOrTPHOrWildcardOrGeneric classType, RefTypeOrTPHOrWildcardOrGeneric returnType, - String methodName, List arguments) { + + public MethodConstraint(RefTypeOrTPHOrWildcardOrGeneric classType, String methodName, + List arguments, RefTypeOrTPHOrWildcardOrGeneric returnType) { this.classType = classType; this.returnType = returnType; this.methodName = methodName; @@ -37,14 +44,14 @@ public class MethodConstraint { public List getArguments() { return arguments; } - - public void addArgument(SubTypeConstraint... subTypeConstraints){ + + public void addArguments(SubTypeConstraint... subTypeConstraints) { for (SubTypeConstraint subTypeConstraint : subTypeConstraints) { this.arguments.add(subTypeConstraint); } } - - public void addArgument(RefTypeOrTPHOrWildcardOrGeneric... parameters){ + + public void addArguments(RefTypeOrTPHOrWildcardOrGeneric... parameters) { for (RefTypeOrTPHOrWildcardOrGeneric parameter : parameters) { Token offset = parameter.getOffset(); TypePlaceholder tph = TypePlaceholder.fresh(offset); @@ -52,6 +59,5 @@ public class MethodConstraint { this.arguments.add(subTypeConstraint); } } - - + } diff --git a/src/de/dhbwstuttgart/strucTypes/SubTypeConstraint.java b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java similarity index 78% rename from src/de/dhbwstuttgart/strucTypes/SubTypeConstraint.java rename to src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java index 8102ca02..f17f970c 100644 --- a/src/de/dhbwstuttgart/strucTypes/SubTypeConstraint.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java @@ -1,22 +1,29 @@ -package de.dhbwstuttgart.strucTypes; +package de.dhbwstuttgart.strucTypes.constraint; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +/** + * c <. c' : c ist subtyp von c' + * + * @author mvr + * + */ public class SubTypeConstraint { - + private RefTypeOrTPHOrWildcardOrGeneric subtype; private RefTypeOrTPHOrWildcardOrGeneric supertype; - + public SubTypeConstraint(RefTypeOrTPHOrWildcardOrGeneric subtype, RefTypeOrTPHOrWildcardOrGeneric supertype) { this.subtype = subtype; this.supertype = supertype; } + public RefTypeOrTPHOrWildcardOrGeneric getSubtype() { return subtype; } + public RefTypeOrTPHOrWildcardOrGeneric getSupertype() { return supertype; } - - + } diff --git a/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java b/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java new file mode 100644 index 00000000..e12eed43 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/printutils/PrintConstraints.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.strucTypes.printutils; + +import java.util.List; + +import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; +import de.dhbwstuttgart.strucTypes.constraint.FieldConstraint; +import de.dhbwstuttgart.strucTypes.constraint.MethodConstraint; +import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; + +public class PrintConstraints { + + public static void print(ConstraintsSet constraintsSet){ + printSubTypeConstraints(constraintsSet.getSubTypeConstraints()); + printFieldConstraints(constraintsSet.getFieldConstraints()); + printMethodConstraints(constraintsSet.getMethodConstraints()); + } + + public static void printSubTypeConstraints(List constraints) { + System.out.println("\n SubTypeConstraints:"); + constraints.forEach(c-> System.out.println(c.getSubtype() + " < " + c.getSupertype())); + } + + public static void printFieldConstraints(List constraints){ + System.out.println("\n FieldConstraints:"); + constraints.forEach(c -> System.out.println(String.format("F(%s,%s,%s)", c.getClassType() , c.getFieldName() , c.getFieldType()))); + } + + public static void printMethodConstraints(List constraints){ + System.out.println("\n MethodConstraints:"); + constraints.forEach(c-> { + StringBuilder sb = new StringBuilder("M("); + sb.append(c.getClassType() + ","); + sb.append(c.getMethodName() + ",["); + c.getArguments().forEach(a -> sb.append(a.getSubtype() + ",")); + sb.append("],(" + c.getReturnType() + ",["); + c.getArguments().forEach(a-> sb.append(a.getSupertype() + ",")); + sb.append("]))"); + System.out.println(sb.toString()); + }); + + } +} diff --git a/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java b/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java new file mode 100644 index 00000000..4c76c9f2 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.strucTypes.printutils; + +import java.util.Map; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class PrintInferredTypes { + + public static void print(Map inferredTypes){ + System.out.println("\n Inferred Types:"); + inferredTypes.keySet().forEach(key -> System.out.println(key + " <=> " + inferredTypes.get(key))); + } +} diff --git a/src/de/dhbwstuttgart/strucTypes/SyntaxTreePrinter.java b/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java similarity index 92% rename from src/de/dhbwstuttgart/strucTypes/SyntaxTreePrinter.java rename to src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java index d35112a8..e1728747 100644 --- a/src/de/dhbwstuttgart/strucTypes/SyntaxTreePrinter.java +++ b/src/de/dhbwstuttgart/strucTypes/printutils/SyntaxTreePrinter.java @@ -1,4 +1,4 @@ -package de.dhbwstuttgart.strucTypes; +package de.dhbwstuttgart.strucTypes.printutils; import java.util.List; @@ -66,16 +66,18 @@ public class SyntaxTreePrinter implements ASTVisitor { @Override public void visit(ClassOrInterface classOrInterface) { JavaClassName className = classOrInterface.getClassName(); + RefTypeOrTPHOrWildcardOrGeneric type = classOrInterface.getType(); List fields = classOrInterface.getFieldDecl(); List methods = classOrInterface.getMethods(); RefType superClass = classOrInterface.getSuperClass(); List implementedInterfaces = classOrInterface.implementedInterfaces; - System.out.println("class: " + className); + System.out.print("class: " + className + " : "); + type.accept(this); fields.forEach(f->f.accept(this)); methods.forEach(m->m.accept(this)); - System.out.print("superClass: "); + System.out.print("\n superClass: "); superClass.accept(this); - System.out.println("implemented Interfaces: "); + System.out.println("\n implemented Interfaces: "); implementedInterfaces.forEach(i -> i.accept(this)); } @@ -94,7 +96,7 @@ public class SyntaxTreePrinter implements ASTVisitor { String name = method.getName(); RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); ParameterList parameterList = method.getParameterList(); - System.out.print("method: " + name + " : "); + System.out.print("\n method: " + name + " : "); returnType.accept(this); parameterList.accept(this); method.block.accept(this); @@ -199,7 +201,7 @@ public class SyntaxTreePrinter implements ASTVisitor { public void visit(This aThis) { ArgumentList arglist = aThis.arglist; RefTypeOrTPHOrWildcardOrGeneric type = aThis.getType(); - System.out.print("this: " + " : "); + System.out.print("this : "); type.accept(this); if( arglist != null) arglist.accept(this); } @@ -208,7 +210,10 @@ public class SyntaxTreePrinter implements ASTVisitor { public void visit(RefType refType) { JavaClassName name = refType.getName(); System.out.println(name); - + if(!refType.getParaList().isEmpty()){ + System.out.println(" generics: "); + refType.getParaList().forEach(p->p.accept(this)); + } } @Override diff --git a/test/strucType/TestStrucType.java b/test/strucType/TestStrucType.java new file mode 100644 index 00000000..491c84c2 --- /dev/null +++ b/test/strucType/TestStrucType.java @@ -0,0 +1,49 @@ +package strucType; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.strucTypes.StrucTYPE; +import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; +import de.dhbwstuttgart.strucTypes.printutils.PrintConstraints; +import de.dhbwstuttgart.strucTypes.printutils.PrintInferredTypes; +import de.dhbwstuttgart.strucTypes.printutils.SyntaxTreePrinter; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class TestStrucType { + public static final String rootDirectory = System.getProperty("user.dir") + "/test/strucType/javFiles/"; + + @org.junit.Test + public void test() throws ClassNotFoundException, IOException { + ArrayList files = new ArrayList<>(); +// files.add(new File(rootDirectory + "testLocalVar.jav")); +// files.add(new File(rootDirectory + "testCast.jav")); + files.add(new File(rootDirectory + "testNew.jav")); +// files.add(new File(rootDirectory + "testFieldVar.jav")); +// files.add(new File(rootDirectory + "testFieldMethod.jav")); +// files.add(new File(rootDirectory + "testPaperExample.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(files); + for (File f : compiler.sourceFiles.keySet()) { + String name = f.getName(); + System.out.println("Filename: " + name); + SourceFile sourceFile = compiler.sourceFiles.get(f); + //Print SourceFile Infos + sourceFile.accept(new SyntaxTreePrinter()); + + StrucTYPE strucTYPE = new StrucTYPE(sourceFile); + + ConstraintsSet constraints = strucTYPE.getConstraints(); + PrintConstraints.print(constraints); + + Map inferredTypes = strucTYPE.getInferredTypes(); + PrintInferredTypes.print(inferredTypes); + + System.out.println("____________________________________________________________________________"); + } + } +} diff --git a/test/strucType/TestSyntaxTreePrinter.java b/test/strucType/TestSyntaxTreePrinter.java index d9d15916..2819fdcb 100644 --- a/test/strucType/TestSyntaxTreePrinter.java +++ b/test/strucType/TestSyntaxTreePrinter.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import de.dhbwstuttgart.core.JavaTXCompiler; -import de.dhbwstuttgart.strucTypes.SyntaxTreePrinter; +import de.dhbwstuttgart.strucTypes.printutils.SyntaxTreePrinter; public class TestSyntaxTreePrinter { public static final String rootDirectory = System.getProperty("user.dir")+"/test/strucType/javFiles/"; diff --git a/test/strucType/javFiles/testCast.jav b/test/strucType/javFiles/testCast.jav index 757d5a27..30ed4bc1 100644 --- a/test/strucType/javFiles/testCast.jav +++ b/test/strucType/javFiles/testCast.jav @@ -1,4 +1,10 @@ +package strucType.input; +import strucType.typedtestclasses.A; +import strucType.typedtestclasses.A2; +import strucType.typedtestclasses.B; + class C { - mC(x){return (Integer)x; } + mA(A x){return (A2)x; } + mB(c) { return (B)c; } } \ No newline at end of file diff --git a/test/strucType/javFiles/testFieldMethod.jav b/test/strucType/javFiles/testFieldMethod.jav index 06356bdd..98a56240 100644 --- a/test/strucType/javFiles/testFieldMethod.jav +++ b/test/strucType/javFiles/testFieldMethod.jav @@ -1,5 +1,10 @@ +package strucType.input; +import java.lang.Integer; + class M { f; mM(x, y) { return f.mF(x, y); } + mInt(Integer x) { return x.doubleValue(); } + } \ No newline at end of file diff --git a/test/strucType/javFiles/testFieldVar.jav b/test/strucType/javFiles/testFieldVar.jav index 50466e04..7b1d6643 100644 --- a/test/strucType/javFiles/testFieldVar.jav +++ b/test/strucType/javFiles/testFieldVar.jav @@ -1,3 +1,5 @@ +package strucType.input; + class F { f; diff --git a/test/strucType/javFiles/testLocalVar.jav b/test/strucType/javFiles/testLocalVar.jav index ff887250..615306f8 100644 --- a/test/strucType/javFiles/testLocalVar.jav +++ b/test/strucType/javFiles/testLocalVar.jav @@ -1,6 +1,6 @@ -import java.util.List; +package strucType.input; -class C1 implements List +class C { m(x) { return x; } } diff --git a/test/strucType/javFiles/testNew.jav b/test/strucType/javFiles/testNew.jav index 6633683f..9f877591 100644 --- a/test/strucType/javFiles/testNew.jav +++ b/test/strucType/javFiles/testNew.jav @@ -1,4 +1,10 @@ +package strucType.input; +import strucType.typedtestclasses.A; +import strucType.typedtestclasses.B; class N { - mN(s) {return new String(s); } + a; + + mA(){ return new A(a); } + mB(x){ return new B(x,a); } } \ No newline at end of file diff --git a/test/strucType/javFiles/testPaperExample.jav b/test/strucType/javFiles/testPaperExample.jav index 5b52508b..347a1656 100644 --- a/test/strucType/javFiles/testPaperExample.jav +++ b/test/strucType/javFiles/testPaperExample.jav @@ -1,3 +1,5 @@ +package strucType.input; + class A { mt(x, y, z) { return x.sub(y).add(z); } diff --git a/test/strucType/typedtestclasses/A.java b/test/strucType/typedtestclasses/A.java new file mode 100644 index 00000000..9a7da22c --- /dev/null +++ b/test/strucType/typedtestclasses/A.java @@ -0,0 +1,19 @@ +package strucType.typedtestclasses; + +public class A { + + public A a; + + public A(A a) { + this.a = a; + } + + public A getA() { + return this.a; + } + + public B getB(B b) { + return b; + } + +} diff --git a/test/strucType/typedtestclasses/A2.java b/test/strucType/typedtestclasses/A2.java new file mode 100644 index 00000000..b5862912 --- /dev/null +++ b/test/strucType/typedtestclasses/A2.java @@ -0,0 +1,9 @@ +package strucType.typedtestclasses; + +public class A2 extends A { + + public A2(A a) { + super(a); + } + +} diff --git a/test/strucType/typedtestclasses/B.java b/test/strucType/typedtestclasses/B.java new file mode 100644 index 00000000..6fd3db35 --- /dev/null +++ b/test/strucType/typedtestclasses/B.java @@ -0,0 +1,20 @@ +package strucType.typedtestclasses; + +public class B { + + public E e; + public A a; + public B(E e, A a) { + this.e = e; + this.a = a; + } + + public E getGeneric(){ + return this.e; + } + + public A getInput(){ + return this.a; + } + +} diff --git a/test/strucType/typedtestclasses/C.java b/test/strucType/typedtestclasses/C.java new file mode 100644 index 00000000..cc751d43 --- /dev/null +++ b/test/strucType/typedtestclasses/C.java @@ -0,0 +1,27 @@ +package strucType.typedtestclasses; + +public class C { + + + public E e; + public F f; + + + + public C(E e, F f) { + this.e = e; + this.f = f; + } + + public E getGeneric1(){ + return this.e; + } + + public F getGeneric2(){ + return this.f; + } + + public C> convert(A a, B b){ + return new C<>(a,b); + } +}