// ino.module.SourceFile.8722.package package de.dhbwstuttgart.syntaxtree; // ino.end // ino.module.SourceFile.8722.import import java.io.IOException; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import java.util.function.Function; import de.dhbwstuttgart.typeinference.Menge; import java.util.stream.Stream; import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.logger.Section; import de.dhbwstuttgart.core.AClassOrInterface; import de.dhbwstuttgart.core.MyCompiler; import de.dhbwstuttgart.myexception.CTypeReconstructionException; import de.dhbwstuttgart.myexception.JVMCodeException; import de.dhbwstuttgart.myexception.SCClassException; import de.dhbwstuttgart.myexception.SCException; import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.misc.DeclId; import de.dhbwstuttgart.syntaxtree.misc.UsedId; import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; import de.dhbwstuttgart.syntaxtree.modifier.Public; import de.dhbwstuttgart.syntaxtree.type.FunN; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.ByteCodeResult; import de.dhbwstuttgart.typeinference.ConstraintsSet; import de.dhbwstuttgart.typeinference.FunNInterface; import de.dhbwstuttgart.typeinference.FunNMethod; import de.dhbwstuttgart.typeinference.KomplexeMenge; import de.dhbwstuttgart.typeinference.Pair; import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; import de.dhbwstuttgart.typeinference.TypeinferenceResults; import de.dhbwstuttgart.typeinference.UndConstraint; import de.dhbwstuttgart.typeinference.UnifyConstraintsSet; import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.DebugException; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.unify.TypeUnify; import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; public class SourceFile extends SyntaxTreeNode { // ino.attribute.LOAD_BASIC_ASSUMPTIONS_FROM_JRE.21358.decldescription type=javadoc /** * @autor HOTI * Dieses Flag bestimmt, ob die basicAssumptions (Integer, Menge, ...) direkt von * der Java-Laufzeitumgebung anhand der Imports oder von den "Fixed Hacks" geladen * werden (Mit Fixed Hacks sind die von Hand eingetragene Basetypes gemeint) */ // ino.end // ino.attribute.LOAD_BASIC_ASSUMPTIONS_FROM_JRE.21358.declaration private static final boolean LOAD_BASIC_ASSUMPTIONS_FROM_JRE = true; // ino.end // ino.attribute.READ_OBJECT_SUPERCLASSES_FROM_JRE.21361.decldescription type=javadoc /** * @autor HOTI * Wenn dieses Flag auf <b>true</b> gesetzt ist, wird immer als Superklasse Object * mit rein geladen. Dies hat natürlich zur Folge, dass man in der GUI jeden Typ * auswählen muss, weil ALLES in Java von Object erbt. Sobald die GUI das über eine * Checkbox o.ä. ausblendbar macht kann es aktiviert werden. Ebenso beeinflusst es * die superclass von allen Class-Objekten. (Wenn true ist jede Class automatisch * wenn nicht anders eingegeben Subclass von Object (Wie es sein muss)) */ // ino.end // ino.attribute.READ_OBJECT_SUPERCLASSES_FROM_JRE.21361.declaration public static final boolean READ_OBJECT_SUPERCLASSES_FROM_JRE = false; // ino.end // ino.attribute.READ_BASE_TYPE_SUPERCLASSES_FROM_JRE.21364.decldescription type=javadoc /** * Wenn dieses Flag auf <b>false</b> ist, werden für alle Basisklassen (definiert * durch die Hashtable baseTypeTranslationTable) KEINE Superklassen geladen. D.h. * Integer hat bspw. nicht die Superklasse Number sondern OBJECT. * Dies verursacht bei den Int-Operationen ein Problem * (+,-,*,/,<,>,...) */ // ino.end // ino.attribute.READ_BASE_TYPE_SUPERCLASSES_FROM_JRE.21364.declaration private static final boolean READ_BASE_TYPE_SUPERCLASSES_FROM_JRE = false; // ino.end /** * @autor PL * Wenn dieses Flag auf <b>false</b> ist, werden für alle importierten Klassen * KEINE Superklassen geladen. */ private static final boolean READ_IMPORTED_SUPERCLASSES_FROM_JRE = false; // ino.attribute.codegenlog.21367.decldescription type=line // Logger fuer Code-Gen // ino.end // ino.attribute.codegenlog.21367.declaration protected static Logger codegenlog = Logger.getLogger("codegen"); // ino.end // ino.attribute.inferencelog.21370.declaration protected static Logger inferencelog = Logger.getLogger("inference"); // ino.end // ino.attribute.pkgName.21373.declaration private UsedId pkgName; // ino.end // ino.attribute.KlassenVektor.21376.declaration public Menge<Class> KlassenVektor = new Menge<Class>(); // ino.end // ino.attribute.InterfaceVektor.21379.declaration public Menge<Interface> InterfaceVektor = new Menge<Interface>(); // ino.end /** * Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei. * SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar. */ public SourceFile(){ // HOTI 4.5.06 // Base-Type-Translations anlegen (siehe kommentar BaseTypeTranslationTable) baseTypeTranslationTable=new Hashtable<String,String>(); baseTypeTranslationTable.put("int","java.lang.Integer"); baseTypeTranslationTable.put("char","java.lang.Character"); baseTypeTranslationTable.put("boolean","java.lang.Boolean"); baseTypeTranslationTable.put("double","java.lang.Double"); baseTypeTranslationTable.put("long","java.lang.Long"); baseTypeTranslationTable.put("float","java.lang.Float"); //baseTypeTranslationTable.put("this.is.a.temporary.entry","de.dhbwstuttgart.typeinference.Menge"); auskommentiert PL 07-08-11 this.imports=new ImportDeclarations(); this.imports.add(UsedId.createFromQualifiedName("java.lang.Integer",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.String",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.Character",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.Boolean",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.Double",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.Float",-1)); this.imports.add(UsedId.createFromQualifiedName("java.lang.Long",-1)); //this.imports.add(UsedId.createFromQualifiedName("java.lang.Byte")); // HOTI 4.5.06 Wenn die Klassen immer als "Daddy" Object haben, // muss das der JCC auch kennen if(READ_OBJECT_SUPERCLASSES_FROM_JRE){ this.imports.add(UsedId.createFromQualifiedName("java.lang.Object",-1)); } } public SourceFile(Menge<Class> classDefinitions) { this.KlassenVektor = classDefinitions; } /** * HOTI 4.5.06 * Beinhaltet alle Imports des aktuell geparsten Files * in Form einer UsedId */ private ImportDeclarations imports=new ImportDeclarations(); /** * Table zum Ãbersetzen der nicht implementierten Base-Types: * Ãberall im Compiler wird statt bspw. int Integer verwendet * d.h. 1+2 liefert ein Integer * Deshalb benötigen wir hier eine Tabelle, mit der man die von * der JRE gelieferten Base-Typen (int,char, etc) und die Objekt- * Typen umwandeln können */ private Hashtable<String,String> baseTypeTranslationTable; /** * Fuegt ein neues Element (Interface oder Klasse) hinzu. * @param c */ public void addElement(AClassOrInterface e) { if (e instanceof Class) { KlassenVektor.addElement((Class) e); } else if (e instanceof Interface) { InterfaceVektor.addElement((Interface) e); } } ///////////////////////////////////////////////////////////////////////// // TypeReconstructionAlgorithmus ///////////////////////////////////////////////////////////////////////// // ino.method.typeReconstruction.21406.defdescription type=javadoc /** * Tyrekonstruktionsalgorithmus: ruft f�r jede Klasse den Algorithmus TRProg auf. * Dessen Ergebnismenge A, die Menge aller Typannahmen, f�r eine Klasse dient als * Eingabe f�r TRProg der n�chsten Klasse. Am Ende enth�lt A alle m�glichen * Typkombinationen f�r alle Klassen zusammen. * <br>Author: J�rg B�uerle * @return Liste aller m�glichen Typkombinationen * @throws CTypeReconstructionException Wenn was schief l�uft */ // ino.end // ino.method.typeReconstruction.21406.definition public Menge<TypeinferenceResultSet> typeReconstruction(TypeAssumptions globalAssumptions) throws CTypeReconstructionException // ino.end // ino.method.typeReconstruction.21406.body { Menge<TypeinferenceResultSet> ret = new Menge<TypeinferenceResultSet>(); //Logger initialisieren: Logger typinferenzLog = Logger.getLogger("Typeinference"); //Alle Assumptions für diese SourceFile sammeln: for(Class klasse : this.KlassenVektor){ globalAssumptions.add(klasse.getPublicFieldAssumptions()); } //Assumptions der importierten Klassen sammeln: TypeAssumptions importAssumptions = this.makeBasicAssumptionsFromJRE(imports, true); globalAssumptions.add(importAssumptions); typinferenzLog.debug("Von JRE erstellte Assumptions: "+importAssumptions, Section.TYPEINFERENCE); //FiniteClosure generieren: FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(globalAssumptions); typinferenzLog.debug("FiniteClosure: \n"+finiteClosure, Section.TYPEINFERENCE); ConstraintsSet oderConstraints = new ConstraintsSet(); //Alle Constraints der in dieser SourceFile enthaltenen Klassen sammeln: for(Class klasse : KlassenVektor){ oderConstraints.add(klasse.typeReconstruction(globalAssumptions)); } /*//////////////// * Paare in MPairs umwandeln * (Wird zunächst mal weggelassen. Constraints werden erst beim Unifizieren umgewandelt *///////////////// //UnifyTypeFactory.convert(oderConstraints); //////////////// //Typen in UnifyTypen umwandeln: //////////////// UnifyConstraintsSet unifyConstraints = UnifyTypeFactory.convert(oderConstraints); //Unmögliche ConstraintsSets aussortieren durch Unifizierung Function<Menge<UnifyPair>,Menge<Menge<UnifyPair>>> unifier = (pairs)->{ Menge<Menge<UnifyPair>> retValue = new Menge<>(); Set<Set<UnifyPair>> unifiedPairs = new TypeUnify().unify(pairs, finiteClosure); return retValue;}; //oderConstraints.filterWrongConstraints(unifier); //oderConstraints.unifyUndConstraints(unifier); //rausgeworfen für Tests (08.12.2015) typinferenzLog.debug("Ãbriggebliebene Konstraints:\n"+oderConstraints+"\n", Section.TYPEINFERENCE); typinferenzLog.debug("Ãbriggebliebene Konvertierte Konstraints:\n"+unifyConstraints+"\n", Section.TYPEINFERENCE); //////////////// //Karthesisches Produkt bilden: //////////////// Set<Set<UnifyPair>> xConstraints = unifyConstraints.cartesianProduct(); typinferenzLog.debug("Finite Closure: "+finiteClosure, Section.TYPEINFERENCE); typinferenzLog.debug("Karthesisches Produkt der Constraints: "+xConstraints, Section.TYPEINFERENCE); //finiteClosure.generateFullyNamedTypes(globalAssumptions); ////////////////////////////// // Unifizierung der Constraints: ////////////////////////////// boolean unifyFail = true; for(Set<UnifyPair> constraints : xConstraints){ //Alle durch das Karthesische Produkt entstandenen Möglichkeiten durchgehen: //Menge<Menge<Pair>> result = new Menge<Menge<Pair>>(); //IDEE: Man bildet Zusammenhangskomponenten von Paaren, die gemeinsame Variablen haben // und unifizert nur die Zusammenhangskomponenten in Schritten 1 - 5 /* //Schritt 1: Alle Variablen in den Paaren von Elementen einsammeln Menge<Menge<TypePlaceholder>> constraintsclonevars = constraints.stream().map(p -> {Menge<TypePlaceholder> TPHs = new Menge<>(); TPHs.addAll(p.TA1.getInvolvedTypePlaceholder()); TPHs.addAll(p.TA2.getInvolvedTypePlaceholder()); return TPHs;} ).collect(Menge::new, Menge::add, Menge::addAll); //Schritt 2: Schnittmengen jedes Elements mit jedem Elememt von vars bilden und dann index zusammenfassen //in indexset sind dann die Mengen von Indizes enthalten, die gemeisam unifiziert wreden müssen Menge<Menge<Integer>> indexeset = new Menge<>(); if (constraintsclonevars != null && constraintsclonevars.size()>0) { indexeset = Unify.schnitt(constraintsclonevars); } //Schritt 3: Umwandlung der Indizes in die zugehoerigen Elemente // In streamconstraintsclone sind die Mengen von Paar enthalten die unifiziert werden muessen Stream<Menge<MPair>> streamconstraintsclone = indexeset.stream().map(x -> x.stream() .map(i -> constraintsClone.elementAt(i)) .<Menge<MPair>>collect(Menge::new, Menge::add, Menge::addAll)); //Menge<Menge<Pair>> vecconstraintsclone = streamconstraintsclone.collect(Menge::new, Menge::add, Menge::addAll); //System.out.println(); //Schritt 4: Unifikation Set<Set<Set<MPair>>> vecunifyResult = //streamconstraintsclone.map(x -> Unify.unify(x, finiteClosure)).collect(Menge::new, Menge::add, Menge::addAll); //DEBUG-Variante streamconstraintsclone.map(x -> { Set<Set<MPair>> z = new Unify().unify(x, finiteClosure); return z; } ).collect(Menge::new, Menge::add, Menge::addAll); //card gibt die Cardinalitaet der unifizierten Mengen an Menge<Integer> card = vecunifyResult.stream().map(x -> x.size()).collect(Menge::new, Menge::add, Menge::addAll); ;//.reduce(1,(a,b) -> { if ((a > 0) && (b > 0)) return (a * b); else return 1; }); //Schritt 5: Bildung des cartesischen Produkts //sollte wieder entfernt werden: Weiterarbeit mit: //[[x_1 -> t_1, x_2 -> t2], [x_1 -> t'_1, x_2 -> t'_2]] x ... x [[x_n -> t_1n], [x_n -> t2n], [x_n -> t3n]] Set<Set<Pair>> cardprodret_start = new Menge<>(); cardprodret_start.add(new Menge<Pair>()); //cart. Produkt mit Linkverschiebung Set<Set<Pair>> unifyResult = vecunifyResult.stream().reduce(cardprodret_start, (x, y) -> { Set<Set<Pair>> cardprodret= new Menge<>(); if (y.size() > 0) { //System.out.println(y); //Menge<Menge<Pair>> cardprodretold = x; //cardprodret = new Menge<>(); for(int j = 0; j < x.size(); j++) { for (int k = 0; k < y.size(); k++){ Set<Pair> help = new Menge<>(); help.addAll(y.elementAt(k)); help.addAll(x.elementAt(j)); cardprodret.add(help); } } } else return new Menge<>(); //kein unifiziertes Ergebnis, damit wird das Geseamtergebnis [] return cardprodret; }); */ typinferenzLog.debug("\nUnifiziere Constraints:\n"+constraints, Section.TYPEINFERENCE); Set<Set<UnifyPair>> unifyResult = new TypeUnify().unify(constraints, finiteClosure); Menge<Menge<Pair>> convertedResult = unifyResult.parallelStream().<Menge<Pair>>map((Set<UnifyPair> resultSet)->{ Menge<Pair> innerConvert = resultSet.stream().map((UnifyPair mp)->UnifyTypeFactory.convert(mp)) .collect(Menge<Pair>::new, Menge::add, Menge::addAll); return innerConvert; }).collect(Menge::new, Menge::add, Menge::addAll); Menge<Pair> convertedConstraints = constraints.stream().map( (UnifyPair mp)->{return UnifyTypeFactory.convert(mp);} ).collect(Menge<Pair>::new, Menge::add, Menge::addAll); //Dann den Ergebnissen anfügen typinferenzLog.debug("\nErgebnis der Unifizierung:\n"+unifyResult, Section.TYPEINFERENCE); //result.addAll(convertedResult); typinferenzLog.debug("\nJavaFiles:\n", Section.TYPEINFERENCE); //typinferenzLog.debug(this.printJavaCode(new ResultSet(new Menge<Pair>()))); //Für jede Klasse in diesem SourceFile gilt das selbe ResultSet: for(Class klasse : this.KlassenVektor){ //Der Unifikationsalgorithmus kann wiederum auch mehrere Lösungen errechnen, diese werden im folgenden durchlaufen: for(Menge<Pair> resultSet : convertedResult){ unifyFail = false; //Ein Unifiziertes Ergebnis ist entstanden (es kann auch leer sein, das bedeutet nur, dass die Constraints mindestens in einem Fall Sinn ergaben) //Add Result set as a new ReconstructionResult to ret: TypeinferenceResultSet reconstructionResult = new TypeinferenceResultSet(klasse, convertedConstraints, new ResultSet(resultSet)); ret.add(reconstructionResult); //ResultSet res = new ResultSet(resultSet); typinferenzLog.debug("JavaFile für ResultSet "+reconstructionResult+"\n", Section.TYPEINFERENCE); typinferenzLog.debug(klasse.printJavaCode(reconstructionResult), Section.TYPEINFERENCE); } } } if(unifyFail){ if(!this.KlassenVektor.isEmpty())throw new TypeinferenceException("Fehler in Typinferierung", this.KlassenVektor.firstElement()); } return ret; } /** * Erstellt die Assumptions der standardmäÃig importierten Packages (java.lang.) sowie der von imports übergebenen Klassen zusammen. * @param imports * @param withSuptypes - Gibt an, ob auch die subklassen der Packages den Assumptions angefügt werden sollen. * @return */ public TypeAssumptions makeBasicAssumptionsFromJRE(Menge<UsedId> imports, boolean withSubtypes) // ino.end // ino.method.makeBasicAssumptionsFromJRE.21409.body { //return null; ///* Menge<UsedId> doneImports=new Menge<UsedId>(); //TypeinferenceResultSet basicAssumptions = new TypeinferenceResultSet(null); TypeAssumptions basicAssumptions = new TypeAssumptions(); Modifiers mod = new Modifiers(); mod.addModifier(new Public()); //Für Object: imports.add(new UsedId("java.lang.Object",-1)); // Für jede einzelne Klasse while (imports.size()>0) { UsedId importDecl = imports.get(0); // Properties laden java.lang.Class<?> x; try { x = java.lang.Class.forName(importDecl.getQualifiedName().toString()); } catch (ClassNotFoundException e) { throw new CTypeReconstructionException("Fehlerhafte Import-Declaration: "+e.getMessage(),importDecl); } java.lang.reflect.Field[] fields=x.getDeclaredFields(); java.lang.reflect.Method[] methods=x.getDeclaredMethods(); java.lang.reflect.Constructor[] constructors=x.getConstructors(); java.lang.reflect.TypeVariable[] tvs=x.getTypeParameters(); //String className=x.getSimpleName(); String className=x.getName(); //Ermittle die Superklasse: Class sClass = new Class("Object",0); if(withSubtypes)sClass = getSuperClassOfJREClass(x, basicAssumptions); // Namen von Generische Typen erzeugen Hashtable<String,GenericTypeVar> jreSpiderRegistry=new Hashtable<String,GenericTypeVar>(); Menge<String> typeGenPara = new Menge<String>(); for(int j=0;j<tvs.length;j++){ //GenericTypeVar gtv=new GenericTypeVar(tvs[j].getName(), parentClass,-1); typeGenPara.addElement(tvs[j].getName()); //jreSpiderRegistry.put(tvs[j].getName(),gtv); } Class parentClass = new Class(className, sClass.getType(),mod, typeGenPara); //BasicAssumptionClass myCl = new BasicAssumptionClass(className, mod); for(GenericTypeVar classParam : parentClass.getGenericParameter()){ jreSpiderRegistry.put(classParam.getName().toString(),classParam); } if(typeGenPara.size()>0){ //auskommentiert von Andreas Stadelmeier: //basicAssumptions.addGenericTypeVars(className, typeGenPara); //parentClass.set_ParaList((Menge)typeGenPara);//myCl.set_ParaList((Menge)typeGenPara); } if(x.getSuperclass()!=null){ //boolean isObject=x.getSuperclass().getSimpleName().equalsIgnoreCase("Object"); boolean isObject=x.getSuperclass().getName().equalsIgnoreCase("java.lang.Object"); boolean isBaseType=isBaseType(className); //if((!isObject || READ_OBJECT_SUPERCLASSES_FROM_JRE) && (!isBaseType|| READ_BASE_TYPE_SUPERCLASSES_FROM_JRE)) if (((!isObject || READ_OBJECT_SUPERCLASSES_FROM_JRE) && READ_IMPORTED_SUPERCLASSES_FROM_JRE) //eingefuegt 07-08-11 || (isBaseType && READ_BASE_TYPE_SUPERCLASSES_FROM_JRE)) { String superclassFullyQualifiedName = x.getSuperclass().getCanonicalName(); //Andere Methode, da Menge.contains bei Strings nicht richtig vergleicht. if(!containsString(imports,superclassFullyQualifiedName) && !containsString(doneImports,superclassFullyQualifiedName)){ imports.addElement(UsedId.createFromQualifiedName(superclassFullyQualifiedName,-1)); } //UsedId ui = new UsedId(); //ui.set_Name(x.getSuperclass().getSimpleName()); UsedId ui=UsedId.createFromQualifiedName(x.getSuperclass().getName(),-1); java.lang.Class superClass=x.getSuperclass(); java.lang.reflect.TypeVariable[] superclassTVS=superClass.getTypeParameters(); Menge<Type> supertypeGenPara = new Menge<Type>(); for(int tvi=0;tvi<superclassTVS.length;tvi++){ GenericTypeVar newGTV=new GenericTypeVar(superclassTVS[tvi].getName(),parentClass,-1); supertypeGenPara.addElement(newGTV); } if(supertypeGenPara.size()==0){ supertypeGenPara=null; } ui.set_ParaList(supertypeGenPara); ui.vParaOrg=supertypeGenPara; parentClass.set_UsedId(ui); } } //auskommentiert von Andreas Stadelmeier //this.addElement(myCl); //basicAssumptions.addClassName(className); for(int j=0;j<fields.length;j++){ if(java.lang.reflect.Modifier.isPublic(fields[j].getModifiers())){ parentClass.addField(new FieldDeclaration(fields[j].getName(),new RefType(fields[j].getType().getName(),parentClass,-1))); } } for(int j=0;j<methods.length;j++){ if(java.lang.reflect.Modifier.isPublic(methods[j].getModifiers())){ String methodName=methods[j].getName(); //if(methodName.equals("add")){ java.lang.reflect.Type genericReturnType=methods[j].getGenericReturnType(); Type returnType=createTypeFromJavaGenericType(genericReturnType,methods[j].getReturnType(),jreSpiderRegistry, parentClass); java.lang.reflect.Type[] gpt=methods[j].getGenericParameterTypes(); java.lang.Class[] pt=methods[j].getParameterTypes(); //CMethodTypeAssumption method = new CMethodTypeAssumption(new RefType(className, 0), methodName, returnType, pt.length,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); Method method = de.dhbwstuttgart.syntaxtree.Method.createEmptyMethod(methodName, parentClass); method.setType(returnType); ParameterList parameterList = new ParameterList(); for(int k=0;k<gpt.length;k++){ Type type=createTypeFromJavaGenericType(gpt[k],pt[k],jreSpiderRegistry, parentClass); // Fixme HOTI beachte overloaded id //method.addParaAssumption(new CParaTypeAssumption(className, methodName, pt.length,0,type.getName(), type, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); FormalParameter parameter = new FormalParameter(new DeclId(type.get_Name())); parameter.setType(type); parameterList.formalparameter.add(parameter); } method.setParameterList(parameterList); //basicAssumptions.addMethodIntersectionType(new CIntersectionType(method)); parentClass.addField(method); //} } } for(int j=0;j<constructors.length;j++){ String methodName=className; Method constructorMethod = de.dhbwstuttgart.syntaxtree.Method.createEmptyMethod(methodName, parentClass); if(java.lang.reflect.Modifier.isPublic(constructors[j].getModifiers())){ ParameterList paraList = new ParameterList(); for(int k=0;k<constructors[j].getParameterTypes().length;k++){ String paraType=constructors[j].getParameterTypes()[k].getName(); //String paraType=constructors[j].getParameterTypes()[k].getSimpleName(); // Fixme HOTI beachte overloaded id FormalParameter fpara = new FormalParameter(new DeclId("p"+k)); fpara.setType(new RefType(paraType,constructorMethod,-1)); paraList.formalparameter.add(fpara); } //basicAssumptions.addMethodIntersectionType(new CIntersectionType(constructor)); constructorMethod.parameterlist = paraList; Constructor constructor = new Constructor(constructorMethod, parentClass); constructor.parserPostProcessing(parentClass); parentClass.addField(constructor); } } basicAssumptions.add(parentClass.getPublicFieldAssumptions()); basicAssumptions.addClassAssumption(new ClassAssumption(parentClass)); imports.removeElement(importDecl); doneImports.addElement(importDecl); } imports.addAll(doneImports); return basicAssumptions; //*/ } // ino.end private Class getSuperClassOfJREClass(java.lang.Class<?> x, TypeAssumptions ass) { Class ret; java.lang.Class s = x.getSuperclass(); if(s == null){ return new Class("java.lang.Object",new Modifiers(), 0); } Menge<String> supertypeGenPara = new Menge<>();//Die Generischen Parameter für die Superklasse berechnen: java.lang.reflect.TypeVariable[] superclassTVS=s.getTypeParameters(); for(int tvi=0;tvi<superclassTVS.length;tvi++){ supertypeGenPara.addElement(superclassTVS[tvi].getName()); } Class ss = this.getSuperClassOfJREClass(s, ass); ret = new Class(s.getName(),ss.getType(),new Modifiers(),supertypeGenPara); ass.addClassAssumption(new ClassAssumption(ss)); //Die beiden SuperKlassen den Assumptions anfügen... ass.addClassAssumption(new ClassAssumption(ret)); return ret; } // ino.method.isBaseType.21412.definition private boolean isBaseType(String type) // ino.end // ino.method.isBaseType.21412.body { return baseTypeTranslationTable.containsValue(type); } // ino.end /*Die contains Methode des Menges vergleicht bei Strings nicht korrekt, * da zwei Strings mit dem gleichen Inhalt unterschiedliche Instanzen sind. * Deshalb diese Methode 07-01-20 luar*/ private boolean containsString(Menge<UsedId> searchMenge, String searchString) { boolean found = false; for(UsedId id : searchMenge) { String s = id.getQualifiedName().toString(); found |= s.equals(searchString); } return found; } // ino.method.createTypeFromJavaGenericType.21415.definition private Type createTypeFromJavaGenericType(java.lang.reflect.Type type, java.lang.Class<?> cl, Hashtable<String,GenericTypeVar>jreSpiderRegistry, Class parentClass) // ino.end // ino.method.createTypeFromJavaGenericType.21415.body { /* auskommentiert, da die Klassen von Sun in der Open JDK 1.8 nicht unterstützt werden. if(type instanceof TypeVariableImpl){ TypeVariableImpl tvi=((TypeVariableImpl)type); return(new GenericTypeVar(jreSpiderRegistry.get(tvi.getName()).getName().toString(),parentClass,-1)); }else{ */ GenericTypeVar gtv = jreSpiderRegistry.get(type.getTypeName()); if(gtv != null)return gtv; //new GenericTypeVar(jreSpiderRegistry.get(type.getTypeName()).getName().toString(),parentClass,-1)); //String jccNameForClass=baseTypeTranslationTable.get(cl.getSimpleName()); String jccNameForClass=baseTypeTranslationTable.get(cl.getName()); if(cl.getSimpleName().equalsIgnoreCase("void")){ return(new Void(parentClass,-1)); }else if(jccNameForClass!=null){ RefType rt=new RefType(jccNameForClass,parentClass,-1); rt.setPrimitiveFlag(true); return(rt); }else{ //return(new RefType(cl.getSimpleName())); return(new RefType(cl.getName(),parentClass,-1)); } //} } // ino.end // ino.method.makeBasicAssumptions.21418.defdescription type=javadoc /** * Erzeugt die Anfangsinformationen �ber bereits bekannte Klassen. * <br/>Achtung Workaround: Die RefTypes m�ssen sp�ter noch durch BaseTypes * ersetzt werden. <br> * Author: J�rg B�uerle * * @return A priori Typinformationen * @throws ClassNotFoundException */ // ino.end // ino.method.makeBasicAssumptions.21418.definition private TypeAssumptions makeBasicAssumptions() // ino.end // ino.method.makeBasicAssumptions.21418.body { /* if(LOAD_BASIC_ASSUMPTIONS_FROM_JRE){ Menge<UsedId> strImports=new Menge<UsedId>(); ImportDeclarations usedIdImports=getImports(); for(int i=0;i<usedIdImports.size();i++){ UsedId uid=usedIdImports.get(i); if(uid.hasWildCard()){ throw new CTypeReconstructionException("Wildcards in den Imports werden bislang nicht unterstuetzt: "+uid.getQualifiedName(),uid); //throw new ClassNotFoundException("Bei den Imports sind momentan keine Wildcards erlaubt!"); }else{ strImports.addElement(uid); } } TypeinferenceResultSet res=makeBasicAssumptionsFromJRE(strImports); ImportDeclarations newImports=new ImportDeclarations(); for(int i=0;i<strImports.size();i++){ newImports.addElement(strImports.get(i)); } setImports(newImports); return(res); } TypeinferenceResultSet foo = new TypeinferenceResultSet(null); CMethodTypeAssumption meth = null; CInstVarTypeAssumption instVar = null; Class c = null; UsedId ui = null; //Menge pl = null; Modifiers mod = new Modifiers(); mod.addModifier(new Public()); //------------------------ // Integer bauen: //------------------------ foo.addClassName("java.lang.Integer"); //PL 05-08-01 eingefuegt instVar = new CInstVarTypeAssumption("java.lang.Integer", "MAX_VALUE", new RefType("java.lang.Integer",-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>()); foo.addFieldOrLocalVarAssumption(instVar); meth = new CMethodTypeAssumption(new RefType("java.lang.Integer", 0), "<init>", new RefType("java.lang.Integer",-1), 0,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Integer", 0), "<init>", new RefType("java.lang.Integer",-1),1, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); meth.addParaAssumption(new CParaTypeAssumption("java.lang.Integer", "<init>", 1, 0,"value", new RefType("java.lang.Integer",-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Integer", 0), "intValue", new RefType("java.lang.Integer",-1), 0,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); c = new BasicAssumptionClass("java.lang.Integer", mod); // ui = new UsedId(); // ui.set_Name("Super-Class-Blub"); // c.set_UsedId(ui); // pl = new Menge(); // pl.addElement(new GenericTypeVar("bla")); // c.set_ParaList(pl); this.addElement(c); //------------------------ // Boolean bauen: //------------------------ foo.addClassName("java.lang.Boolean"); //PL 05-08-01 eingefuegt meth = new CMethodTypeAssumption(new RefType("java.lang.Boolean", 0), "<init>", new RefType("java.lang.Boolean",-1),0, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Boolean", 0), "<init>", new RefType("java.lang.Boolean",-1), 1,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); meth.addParaAssumption(new CParaTypeAssumption("java.lang.Boolean", "<init>", 1, 0, "value", new RefType("java.lang.Boolean",-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Boolean", 0), "booleanValue", new RefType("java.lang.Boolean",-1), 0,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); c = new BasicAssumptionClass("java.lang.Boolean", mod); // ui = new UsedId(); // ui.set_Name("Super-Class-Blub"); // c.set_UsedId(ui); // pl = new Menge(); // pl.addElement(new GenericTypeVar("bla")); // c.set_ParaList(pl); this.addElement(c); //------------------------ // Character bauen: //------------------------ foo.addClassName("java.lang.Character"); //PL 05-08-01 eingefuegt meth = new CMethodTypeAssumption(new RefType("java.lang.Character", 0), "<init>", new RefType("java.lang.Character",-1),0, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Character", 0), "<init>", new RefType("java.lang.Character",-1),1, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); meth.addParaAssumption(new CParaTypeAssumption("java.lang.Character", "<init>", 1, 0,"value", new RefType("java.lang.Character",-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Character", 0), "charValue", new BooleanType(),0, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); c = new BasicAssumptionClass("java.lang.Character", mod); // ui = new UsedId(); // ui.set_Name("Super-Class-Blub"); // c.set_UsedId(ui); // pl = new Menge(); // pl.addElement(new GenericTypeVar("bla")); // c.set_ParaList(pl); this.addElement(c); //------------------------ // Menge bauen: //------------------------ foo.addClassName("java.lang.Menge"); //PL 05-08-01 eingefuegt TypePlaceholder E = TypePlaceholder.fresh(); // Sp�ter ersetzen durch GenericTypeVar Menge<GenericTypeVar> typeGenPara = new Menge<GenericTypeVar>(); typeGenPara.addElement(new GenericTypeVar(E.getName(),-1)); foo.addGenericTypeVars("java.lang.Menge", typeGenPara); meth = new CMethodTypeAssumption(new RefType("java.lang.Menge", 0), "elementAt", new GenericTypeVar(E.getName(),-1), 1,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); meth.addParaAssumption(new CParaTypeAssumption("java.lang.Menge", "elementAt", 1, 0, "index", new RefType("java.lang.Integer",-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Menge", 0), "addElement", new Void(-1),1, MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); meth.addParaAssumption(new CParaTypeAssumption("java.lang.Menge", "addElement", 1, 0,"element", new GenericTypeVar(E.getName(),-1), MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>())); foo.addMethodIntersectionType(new CIntersectionType(meth)); meth = new CMethodTypeAssumption(new RefType("java.lang.Menge", 0), "size", new RefType("java.lang.Integer",-1), 0,MyCompiler.NO_LINENUMBER,MyCompiler.NO_LINENUMBER,new Menge<Integer>(),null); foo.addMethodIntersectionType(new CIntersectionType(meth)); c = new BasicAssumptionClass("java.lang.Menge", mod); // ui = new UsedId(); // ui.set_Name("Super-Class-Blub"); // c.set_UsedId(ui); // pl = new Menge(); // pl.addElement(E); // c.set_ParaList(pl); this.addElement(c); //------------------------ // Stack bauen: //------------------------ foo.addClassName("java.lang.Stack"); //PL 05-08-01 eingefuegt c = new BasicAssumptionClass("java.lang.Stack", mod); ui = new UsedId(-1); ui.set_Name("java.lang.Menge"); c.set_UsedId(ui); // pl = new Menge(); // pl.addElement(E); // c.set_ParaList(pl); this.addElement(c); return foo; */ TypeAssumptions ret = new TypeAssumptions(); //Basic Assumptions für die FunN Interfaces: //TODO: Hier mehr als Fun1-Fun5 implementieren for(int i = 0; i<6; i++){ FunNInterface funN = new FunNInterface(i); ret.add(funN.getPublicFieldAssumptions()); } return ret; //TODO: Diese TypeAssumptions mit basic-Assumptions füllen } // ino.end // ino.method.setImports.21421.definition private void setImports(ImportDeclarations newImports) // ino.end // ino.method.setImports.21421.body { this.imports=newImports; } // ino.end // ino.method.removeBasicAssumptions.21424.defdescription type=javadoc /** * L�scht die Anfangsinformation wieder aus dem Klassenvektor * <br/>Author: J�rg B�uerle */ // ino.end // ino.method.removeBasicAssumptions.21424.definition private void removeBasicAssumptions() // ino.end // ino.method.removeBasicAssumptions.21424.body { for(int i=0; i<KlassenVektor.size(); i++){ Class cl = KlassenVektor.elementAt(i); if(cl instanceof BasicAssumptionClass){ KlassenVektor.removeElementAt(i); i--; } } } // ino.end // ino.method.getPackageName.21427.defdescription type=javadoc /** * Erzeugt f�r jede Klasse einen Menge, in den Referenzen auf die GenericTypeVars * dieser Klasse gespeichert werden. Diese Mengeen werden unter den Klassennamen * in der * Ergebnisdatenstruktur abgelegt. Au�erdem werden alle Klassennamen gespeichert. * <br/>Author: J�rg B�uerle * @param res * / * /*private void addClassNamesAndGenericsToRR(CTypeReconstructionResult res){ * Iterator<Class> it = this.getClassIterator(); * while(it.hasNext()){ * Class cl = it.next(); * res.addClassName(cl.get_classname()); * Menge<GenericTypeVar> genericsList = new Menge<GenericTypeVar>(); * * for(int i =0; i<cl.get_ParaList().size(); i++){ * Type para = (Type)cl.get_ParaList().elementAt(i); * if(para instanceof GenericTypeVar){ * genericsList.addElement((GenericTypeVar)para); * } * } * res.addGenericTypeVars(cl.get_classname(), genericsList); * } * } */ // ino.end // ino.method.getPackageName.21427.definition public UsedId getPackageName() // ino.end // ino.method.getPackageName.21427.body { return pkgName; } // ino.end // ino.method.setPackageName.21430.definition public void setPackageName(UsedId pkgName) // ino.end // ino.method.setPackageName.21430.body { this.pkgName = pkgName; // Die Package-Namen fuer alle Klassen und Interfaces // im Source-File nachziehen for (int i=0; i<KlassenVektor.size(); i++) { KlassenVektor.elementAt(i).setPackageName(pkgName); } } // ino.end // ino.method.addImports.21433.definition public void addImports(ImportDeclarations imports) // ino.end // ino.method.addImports.21433.body { this.imports.addAll(imports); } // ino.end // ino.method.getImports.21436.definition public ImportDeclarations getImports() // ino.end // ino.method.getImports.21436.body { if(imports==null){ return(new ImportDeclarations()); } return(imports); } // ino.end // ino.method.getClassIterator.21439.definition public Iterator<Class> getClassIterator() // ino.end // ino.method.getClassIterator.21439.body { return KlassenVektor.iterator(); } // ino.end // ino.method.getInterfaceIterator.21442.definition public Iterator<Interface> getInterfaceIterator() // ino.end // ino.method.getInterfaceIterator.21442.body { return InterfaceVektor.iterator(); } // ino.end @Override public void parserPostProcessing(SyntaxTreeNode parent) { if(parent!=null)throw new DebugException("Eine SourceFile hat kein Elternelement im Syntaxbaum"); super.parserPostProcessing(this); //for(SyntaxTreeNode node : this.getChildren())node.parserPostProcessing(this); } @Override public SyntaxTreeNode getParent() { return null; } @Override public Menge<SyntaxTreeNode> getChildren() { Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>(); for(Class cl : this.KlassenVektor){ ret.add(cl); } return ret; } /** * SourceFile stellt eine geparste Java-Datei dar. Mit dieser Methode wird der Name der eingelesenen Datei gesetzt. * @param filename - Der Name der eingelesenen JavaDatei */ @Deprecated public void setFileName(String filename) { //this.filename = filename; } @Override public int getOffset() { // TODO Auto-generated method stub return 0; } @Override public int getVariableLength() { // TODO Auto-generated method stub return 0; } /** * Bisher wird nur der Bytecode der Klassen generiert. Nicht der Interfaces. * @return */ public Menge<ByteCodeResult> generateBytecode(TypeinferenceResults results) { Menge<ByteCodeResult> ret = new Menge<>(); for(Class cl : this.KlassenVektor){ ret.add(cl.genByteCode(results)); } return ret; } } // ino.end