From 492f11a91e38a6659ec8a3fa89404c8c1031acc9 Mon Sep 17 00:00:00 2001 From: Aldaron7 Date: Fri, 16 Mar 2018 19:39:11 +0100 Subject: [PATCH] Construct added, InferredTypes ausgelagert, TypeExpr fieldVar bei receiver = This keine Constraints mehr, InferredTypes transitive Typen aufgeloest --- .../dhbwstuttgart/strucTypes/Construct.java | 97 +++++++++++++++++++ .../strucTypes/InferredTypes.java | 85 ++++++++++++++++ .../dhbwstuttgart/strucTypes/StrucTYPE.java | 11 +-- src/de/dhbwstuttgart/strucTypes/TYPEExpr.java | 21 ++-- .../constraint/SubTypeConstraint.java | 26 +++++ .../exception/ImpossibleSubTypeException.java | 28 ++++++ .../printutils/PrintInferredTypes.java | 9 +- test/strucType/TestStrucType.java | 16 ++- 8 files changed, 261 insertions(+), 32 deletions(-) create mode 100644 src/de/dhbwstuttgart/strucTypes/Construct.java create mode 100644 src/de/dhbwstuttgart/strucTypes/InferredTypes.java create mode 100644 src/de/dhbwstuttgart/strucTypes/exception/ImpossibleSubTypeException.java diff --git a/src/de/dhbwstuttgart/strucTypes/Construct.java b/src/de/dhbwstuttgart/strucTypes/Construct.java new file mode 100644 index 00000000..cbb79f61 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/Construct.java @@ -0,0 +1,97 @@ +package de.dhbwstuttgart.strucTypes; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.strucTypes.constraint.ConstraintsSet; +import de.dhbwstuttgart.strucTypes.constraint.FieldConstraint; +import de.dhbwstuttgart.strucTypes.constraint.SubTypeConstraint; +import de.dhbwstuttgart.strucTypes.exception.ImpossibleSubTypeException; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class Construct extends DefaultASTVisitor { + + private List subTypeConstraints = new ArrayList<>(); + private ConstraintsSet constraintsSet = new ConstraintsSet(); + private List newInterf = new ArrayList<>(); + private InferredTypes inferredTypes = new InferredTypes(); + private List constructedInterfaces = new ArrayList<>(); + + public Construct(ConstraintsSet constraintsSet, InferredTypes inferredTypes) throws ImpossibleSubTypeException { + this.constraintsSet = constraintsSet; + this.inferredTypes = inferredTypes; + this.gatherSubTypeConstraints(constraintsSet); + for (SubTypeConstraint constraint : this.subTypeConstraints) { + constraint.checkConstraintPossible(); + } + } + + public InferredTypes getInferredTypes() { + return inferredTypes; + } + + public List getConstructedInterfaces() { + return constructedInterfaces; + } + + private void gatherSubTypeConstraints(ConstraintsSet constraintsSet) { + this.subTypeConstraints.addAll(constraintsSet.getSubTypeConstraints()); + constraintsSet.getFieldConstraints().forEach(fc -> this.newInterf.add(fc.getClassType())); + constraintsSet.getMethodConstraints().forEach(mc -> { + this.subTypeConstraints.addAll(mc.getArguments()); + this.newInterf.add(mc.getClassType()); + }); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + JavaClassName name = new JavaClassName("de.dhbw.constructedinterface." + typePlaceholder.getName()); + this.constructInterface(typePlaceholder, name); + } + + @Override + public void visit(RefType refType) { + JavaClassName name = refType.getName(); + this.constructInterface(refType, name); + } + + private ClassOrInterface constructInterface(RefTypeOrTPHOrWildcardOrGeneric i, JavaClassName name) { + final int modifiers = Modifier.interfaceModifiers(); + List fielddecl = new ArrayList<>(); + List methods = new ArrayList<>(); + List constructors = new ArrayList<>(); + List generics = new ArrayList<>(); + GenericDeclarationList genericClassParameters = new GenericDeclarationList(generics, i.getOffset()); + final RefType superClass = this.createSuperClass(); + final boolean isInterface = true; + List implementedInterfaces = new ArrayList<>(); + final Token offset = i.getOffset(); + + this.constraintsSet.getFieldConstraints().stream().filter(fc -> fc.getClassType().equals(i)).forEach(fc -> { + TypePlaceholder type = TypePlaceholder.fresh(i.getOffset()); + new Field(fc.getFieldName(), type, Modifier.fieldModifiers(), i.getOffset()); + }); + + return new ClassOrInterface(modifiers, name, fielddecl, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); + } + + private RefType createSuperClass(){ + JavaClassName name = new JavaClassName(Object.class.getName()); + GenericDeclarationList genericsOfClass = new GenericDeclarationList(new ArrayList<>(), new NullToken()); + return ClassOrInterface.generateTypeOfClass(name, genericsOfClass, new NullToken()); + } + +} diff --git a/src/de/dhbwstuttgart/strucTypes/InferredTypes.java b/src/de/dhbwstuttgart/strucTypes/InferredTypes.java new file mode 100644 index 00000000..7fb49e12 --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/InferredTypes.java @@ -0,0 +1,85 @@ +package de.dhbwstuttgart.strucTypes; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class InferredTypes implements Map { + + private Map inferredTypes = new HashMap<>(); + + public void resolveTransitiveTypes() { + Set keySet = this.inferredTypes.keySet(); + for (TypePlaceholder key : keySet) { + RefTypeOrTPHOrWildcardOrGeneric value = this.inferredTypes.get(key); + if (value instanceof TypePlaceholder && keySet.contains(value)) { + this.inferredTypes.put(key, this.inferredTypes.get(value)); + } + } + } + + @Override + public int size() { + return inferredTypes.size(); + } + + @Override + public boolean isEmpty() { + return inferredTypes.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return inferredTypes.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return inferredTypes.containsValue(value); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric get(Object key) { + return inferredTypes.get(key); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric put(TypePlaceholder key, RefTypeOrTPHOrWildcardOrGeneric value) { + return inferredTypes.put(key, value); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric remove(Object key) { + return inferredTypes.remove(key); + } + + @Override + public void putAll(Map m) { + inferredTypes.putAll(m); + } + + @Override + public void clear() { + inferredTypes.clear(); + } + + @Override + public Set keySet() { + return inferredTypes.keySet(); + } + + @Override + public Collection values() { + return inferredTypes.values(); + } + + @Override + public Set> entrySet() { + return inferredTypes.entrySet(); + } + +} diff --git a/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java b/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java index c69d6c66..86984efb 100644 --- a/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java +++ b/src/de/dhbwstuttgart/strucTypes/StrucTYPE.java @@ -1,22 +1,18 @@ 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 extends DefaultASTVisitor { private SourceFile sourceFile; private ConstraintsSet constraintsSet = new ConstraintsSet(); - private Map inferredTypes = new HashMap<>(); + private InferredTypes inferredTypes = new InferredTypes(); public StrucTYPE(SourceFile sourceFile) { this.sourceFile = sourceFile; @@ -32,8 +28,9 @@ public class StrucTYPE extends DefaultASTVisitor { return this.constraintsSet; } - public Map getInferredTypes() { - return inferredTypes; + public InferredTypes getInferredTypes() { + this.inferredTypes.resolveTransitiveTypes(); + return this.inferredTypes; } @Override diff --git a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java index f5e4fa4e..89a39dae 100644 --- a/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java +++ b/src/de/dhbwstuttgart/strucTypes/TYPEExpr.java @@ -1,9 +1,7 @@ package de.dhbwstuttgart.strucTypes; 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; @@ -24,14 +22,13 @@ import de.dhbwstuttgart.syntaxtree.statement.NewClass; import de.dhbwstuttgart.syntaxtree.statement.Return; import de.dhbwstuttgart.syntaxtree.statement.This; import de.dhbwstuttgart.syntaxtree.type.RefType; -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class TYPEExpr extends DefaultASTVisitor { private ClassOrInterface aThis; private ConstraintsSet constraints = new ConstraintsSet(); - private Map inferredTypes = new HashMap<>(); + private InferredTypes inferredTypes = new InferredTypes(); public TYPEExpr() { } @@ -40,7 +37,7 @@ public class TYPEExpr extends DefaultASTVisitor { return this.constraints; } - public Map getInferredTypes() { + public InferredTypes getInferredTypes() { return inferredTypes; } @@ -60,7 +57,7 @@ public class TYPEExpr extends DefaultASTVisitor { fieldVar.receiver.accept(this); // Löst Typen zwischen Feld und Feldvariable auf - this.inferFieldVarTypes(fieldVar); + boolean receiverIsThis = this.inferFieldVarTypes(fieldVar); // Ermittelt den Typ ty von fieldVar.receiver und fields(f) TypeExtract fieldTypeVisitor = new TypeExtract(); @@ -71,19 +68,23 @@ public class TYPEExpr extends DefaultASTVisitor { 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); + if (!receiverIsThis) { + FieldConstraint fieldConstraint = new FieldConstraint(fieldVar.receiver.getType(), + fieldVar.fieldVarName, fieldVar.getType()); + this.constraints.addConstraint(fieldConstraint); + } } } - private void inferFieldVarTypes(FieldVar fieldVar) { + private boolean 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())); + return true; } + return false; } @Override diff --git a/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java index f17f970c..733c2ddb 100644 --- a/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java +++ b/src/de/dhbwstuttgart/strucTypes/constraint/SubTypeConstraint.java @@ -1,5 +1,7 @@ package de.dhbwstuttgart.strucTypes.constraint; +import de.dhbwstuttgart.strucTypes.exception.ImpossibleSubTypeException; +import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; /** @@ -26,4 +28,28 @@ public class SubTypeConstraint { return supertype; } + public boolean checkConstraintPossible() throws ImpossibleSubTypeException { + if (this.subtype instanceof RefType && this.supertype instanceof RefType) { + Class subClass = this.createClass(((RefType) this.subtype).getName().toString()); + Class superClass = this.createClass(((RefType) this.supertype).getName().toString()); + if (subClass != null && superClass != null) { + if (superClass.isAssignableFrom(subClass)) + return true; + else + throw new ImpossibleSubTypeException( + String.format("%s ist kein subtyp von %s", subClass.getName(), superClass.getName())); + } + } + return true; + } + + private Class createClass(String name) { + try { + return ClassLoader.getSystemClassLoader().loadClass(name); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + } diff --git a/src/de/dhbwstuttgart/strucTypes/exception/ImpossibleSubTypeException.java b/src/de/dhbwstuttgart/strucTypes/exception/ImpossibleSubTypeException.java new file mode 100644 index 00000000..89bd123d --- /dev/null +++ b/src/de/dhbwstuttgart/strucTypes/exception/ImpossibleSubTypeException.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.strucTypes.exception; + +public class ImpossibleSubTypeException extends Exception { + + private static final long serialVersionUID = 1L; + + public ImpossibleSubTypeException() { + super(); + } + + public ImpossibleSubTypeException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ImpossibleSubTypeException(String message, Throwable cause) { + super(message, cause); + } + + public ImpossibleSubTypeException(String message) { + super(message); + } + + public ImpossibleSubTypeException(Throwable cause) { + super(cause); + } + +} diff --git a/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java b/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java index 4c76c9f2..ae6ccdc3 100644 --- a/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java +++ b/src/de/dhbwstuttgart/strucTypes/printutils/PrintInferredTypes.java @@ -1,14 +1,11 @@ package de.dhbwstuttgart.strucTypes.printutils; -import java.util.Map; - -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.strucTypes.InferredTypes; public class PrintInferredTypes { - public static void print(Map inferredTypes){ + public static void print(InferredTypes inferredTypes){ System.out.println("\n Inferred Types:"); - inferredTypes.keySet().forEach(key -> System.out.println(key + " <=> " + inferredTypes.get(key))); + inferredTypes.keySet().forEach(key -> System.out.println("[" + key + " -> " + inferredTypes.get(key) + "]")); } } diff --git a/test/strucType/TestStrucType.java b/test/strucType/TestStrucType.java index 491c84c2..f66ef6c5 100644 --- a/test/strucType/TestStrucType.java +++ b/test/strucType/TestStrucType.java @@ -3,17 +3,15 @@ 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.InferredTypes; 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/"; @@ -21,12 +19,12 @@ public class TestStrucType { @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 + "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")); + 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(); @@ -40,7 +38,7 @@ public class TestStrucType { ConstraintsSet constraints = strucTYPE.getConstraints(); PrintConstraints.print(constraints); - Map inferredTypes = strucTYPE.getInferredTypes(); + InferredTypes inferredTypes = strucTYPE.getInferredTypes(); PrintInferredTypes.print(inferredTypes); System.out.println("____________________________________________________________________________");