// ino.module.Class.8553.package package de.dhbwstuttgart.syntaxtree; // ino.end // ino.module.Class.8553.import import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import javax.lang.model.element.Modifier; import org.apache.commons.bcel6.generic.ClassGen; import org.apache.commons.bcel6.generic.ConstantPoolGen; import org.apache.commons.bcel6.generic.InstructionFactory; import org.apache.commons.bcel6.generic.InstructionHandle; import org.apache.commons.bcel6.generic.InstructionList; import org.apache.commons.bcel6.generic.MethodGen; import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.logger.Section; import de.dhbwstuttgart.logger.SectionLogger; import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen; import de.dhbwstuttgart.bytecode.DHBWInstructionFactory; import de.dhbwstuttgart.core.AClassOrInterface; import de.dhbwstuttgart.core.IItemWithOffset; import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.misc.DeclId; import de.dhbwstuttgart.syntaxtree.misc.UsedId; import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; import de.dhbwstuttgart.syntaxtree.modifier.Static; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.Expr; import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.statement.SuperCall; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.WildcardType; import de.dhbwstuttgart.typeinference.*; import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.DebugException; import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typeinference.unify.FC_TTO; import de.dhbwstuttgart.typeinference.unify.Unify; import org.apache.commons.bcel6.generic.*; import org.apache.commons.bcel6.classfile.*; import org.apache.commons.bcel6.*; import java.io.*; // ino.class.Class.23010.declaration public class Class extends GTVDeclarationContext implements AClassOrInterface, IItemWithOffset, Generic, GenericTypeInsertable // ino.end // ino.class.Class.23010.body { /** * Log4j - Loggerinstanzen */ protected static Logger inferencelog = Logger.getLogger("inference"); protected static Logger codegenlog = Logger.getLogger("codegen"); protected static Logger parserlog = Logger.getLogger("parser"); protected UsedId pkgName; protected Modifiers modifiers; protected String name; /** * * @param resultSet - Fehlende Typen im Syntaxbaum werden nach diesem ResultSet aufgelöst * @return */ public ByteCodeResult genByteCode(TypeinferenceResults typeinferenceResults) { InstructionFactory _factory; DHBWConstantPoolGen _cp; ClassGenerator _cg; Menge results = new Menge(); SectionLogger logger = Logger.getSectionLogger(this.getClass().getName(), Section.CODEGEN); logger.debug("Test"); if(pkgName != null)throw new NotImplementedException(); short constants = Constants.ACC_PUBLIC; //Per Definition ist jede Methode public _cg = new ClassGenerator(name, this.getSuperClass(), name + ".java", constants , new String[] { }, typeinferenceResults); //letzter Parameter sind implementierte Interfaces _cp = _cg.getConstantPool(); _factory = new DHBWInstructionFactory(_cg, _cp); //Die Felder in Methoden Felder und Konstruktoren aufteilen: Menge fieldDeclarations = new Menge<>(); Menge constructors = new Menge<>(); Menge methods = new Menge<>(); for(Field field : this.fielddecl){ if(field instanceof Constructor)constructors.add((Constructor)field); if(field instanceof Method && ! (field instanceof Constructor))methods.add((Method)field); if(field instanceof FieldDeclaration)fieldDeclarations.add((FieldDeclaration)field); //field.genByteCode(_cg); } //Zuerst die Methoden und Felder abarbeiten: for(Method m : methods){ m.genByteCode(_cg); } InstructionList fieldInitializations = new InstructionList(); for(FieldDeclaration f : fieldDeclarations){ fieldInitializations.append(f.genByteCode(_cg, typeinferenceResults.getTypeReconstructions().firstElement())); } //Die Konstruktoren müssen die Feld initialisierungswerte beinhalten: for(Constructor c : constructors){ c.genByteCode(_cg, fieldInitializations); } return new ByteCodeResult(_cg); } private Menge superif = new Menge(); public UsedId getPackageName() { return pkgName; } public void setPackageName(UsedId pkgName) { this.pkgName = pkgName; } public JavaClassName getName() { return new JavaClassName((this.pkgName!=null ? this.pkgName.toString() +"." : "") +this.name); } public void setName(String strName) { name = strName; } public void setModifiers(Modifiers mod) { this.modifiers = mod; } public Modifiers getModifiers() { return this.modifiers; } /** * Liefert die AccessFlags fuer den Bytecode zurueck. */ public short getAccessFlags() { short ret = 0; if (modifiers != null) { ret = modifiers.calculate_access_flags(); } return ret; } public Menge getSuperInterfaces() { return superif; } @Override public void setSuperInterfaces(Menge superif) { this.superif = superif; } // ino.attribute.superclassid.23014.decldescription type=line // private Status status; // ino.end // ino.attribute.superclassid.23014.declaration public UsedId superclassid = (SourceFile.READ_OBJECT_SUPERCLASSES_FROM_JRE?UsedId.createFromQualifiedName("Object",-1):null); // ino.end // ino.attribute.class_block.23020.decldescription type=line // private Class java; // ino.end // ino.attribute.class_block.23020.declaration private Block class_block; // ino.end // ino.attribute.paralist.23023.declaration //private Menge paralist = new Menge(); // Parameterliste 'class xy{}' wird gespeichert // ino.end // ino.attribute.parahash.23026.declaration private Hashtable parahash = new Hashtable(); // parametrisierten Attrib. werden mit den Paramet.aus paralist verk. // ino.end // ino.attribute.isFirstLocalVarDecl.23029.declaration public static boolean isFirstLocalVarDecl; //Hilfsvariable fuer Offsets, hoth // ino.end //private Menge genericClassParameters=new Menge(); // ino.attribute.containedTypes.23032.decldescription type=line // PL 05-07-30 eingefuegt. Vektor aller Typdeklarationen, die in der Klasse // vorkommen. Wird in der Studienarbeit von Andreas Stadelmeier nur für Verifizierung der Tests eingesetzt. // ino.end // ino.attribute.containedTypes.23032.declaration private Menge containedTypes = new Menge(); // ino.end // ino.attribute.usedIdsToCheck.23035.declaration private Menge usedIdsToCheck = new Menge(); // ino.end private TypeAssumptions typeAssumptions = null;//muss mit null Initialisiert werden. Darf nur über getTypeAssumptions abgerufen werden. // ino.attribute.parserlog.23038.declaration //protected Logger parselog = Logger.getLogger("parser"); // ino.end protected Logger typinferenzLog = Logger.getLogger(Class.class.getName()); private SyntaxTreeNode parent; private Menge fielddecl = new Menge(); private GenericDeclarationList genericClassParameters; private int offset; private Type superClass; // ino.method.Class.23041.definition public Class(String name, int offset) // ino.end // ino.method.Class.23041.body { this.name = name; if(name.equals("java.lang.Object")){ superclassid=null; } this.offset = offset; if(!name.equals("Object") && !name.equals("java.lang.Object"))//Alle Klassen außer Object erben von Object: this.superClass = new Class("java.lang.Object", -1).getType(); } // ino.end /** * Erstellt eine Klasse, welche nur für die Assumptions verwendet wird. * Sie enthält keine unnötigen Informationen, wie Offset oder ClassBody. * @param name * @param superClass * @param modifiers * @param supertypeGenPara - Eine Liste von Namen, welche die Generischen Parameter der Klasse darstellen. */ public Class(String name, Type superClass, Modifiers modifiers, Menge supertypeGenPara) { this(name,superClass,modifiers,0); if(supertypeGenPara == null)return; Menge gtvs = new Menge<>(); for(Object gname : supertypeGenPara){ if(gname instanceof String){ GenericTypeVar newGTV=new GenericTypeVar((String)gname,this,0); gtvs.add(newGTV); }else if(gname instanceof GenericTypeVar){ gtvs.add((GenericTypeVar) gname); }else{ GenericTypeVar newGTV=new GenericTypeVar(gname.toString(),this,0); gtvs.add(newGTV); throw new RuntimeException(gname.toString()); } } this.setGenericParameter(new GenericDeclarationList(gtvs,0)); } public Class(String name, Type superClass, Modifiers mod, int offset){ this(name,mod,offset); if(superClass == null)this.superClass = new Class("java.lang.Object",-1).getType(); else this.superClass = superClass; } // ino.method.Class.23044.definition public Class(String name, Modifiers mod, int offset) // ino.end // ino.method.Class.23044.body { this(name, offset); this.modifiers = mod; } // ino.end public Class(String name, Modifiers mod, ClassBody cb, Menge ct, Menge usedIdsToCheck, UsedId superclass, Menge superif, Menge paralist, int offset){ this(name, mod, cb, ct, usedIdToRefType(superclass),usedIdToRefType(superif),paralist,offset); } public Class(String name, ClassBody cb, Menge ct, UsedId superclass, Menge superif, Menge paralist, int offset) { this(name,null,cb,ct,usedIdToRefType(superclass),superif,paralist,offset); } public Class(String name2, Modifiers modifiers2, ClassBody classBody, Menge containedTypes2, UsedId usedId, Menge typeMenge, Menge paraMenge, int offset2) { this(name2, modifiers2, classBody, containedTypes2, usedIdToRefType(usedId),typeMenge, paraMenge, offset2); } public Class(String name2, Modifiers object, ClassBody classBody, Menge containedTypes2, Menge typeMenge, Menge paraMenge, int offset2) { this(name2, object, classBody, containedTypes2,(Type)null, typeMenge, paraMenge, offset2); } private static Menge usedIdToRefType(Menge superif2) { Menge ret = new Menge<>(); for(UsedId id : superif2)ret.add(usedIdToRefType(id)); return ret; } private static Type usedIdToRefType(UsedId superclass2) { RefType ret = new RefType(superclass2.getSimpleName(), null, superclass2.getOffset()); ret.set_ParaList(superclass2.get_ParaList()); return ret; } // ino.method.Class.23047.defdescription type=javadoc /** * Konstruktor, der die Angabe aller Parameter ermoeglicht. * Zur Uebersichtlichkeit in der Grammatik. */ // ino.end // ino.method.Class.23047.definition public Class(String name, Modifiers mod, ClassBody cb, Menge ct, Type superclass, Menge Menge, Menge paralist, int offset) // ino.end // ino.method.Class.23047.body { this(name,offset); this.modifiers = mod; if (cb != null) set_ClassBody(cb); if (ct != null) setContainedTypes(ct); if (superclass != null){ this.superClass = superclass; } if (Menge != null) setSuperInterfaces(Menge); if (paralist != null && !paralist.isEmpty()){ Type lastPara = paralist.lastElement(); Integer lastItemOffset = lastPara.getOffset() + lastPara.get_Name().length(); this.setGenericParameter(new GenericDeclarationList((Menge)paralist, lastItemOffset)); /* //this.set_ParaList(paralist); Menge gtvList = new Menge<>(); int lastItemOffset = 0; for(Type paraT : paralist){ GenericTypeVar gtv = new GenericTypeVar(paraT.get_Name(),this, paraT.getOffset()); gtvList.add(gtv); lastItemOffset = paraT.getOffset() + paraT.get_Name().length(); } this.genericClassParameters = new GenericDeclarationList(gtvList, lastItemOffset); */ } if(usedIdsToCheck!=null) this.usedIdsToCheck=usedIdsToCheck; // HOTI 10.5.06 // Object darf natuerlich nicht Object als Superklasse haben // Sonst gibt es eine endlosaufloesung if(name.equals("java.lang.Object")){ superclassid=null; } //parserlog.debug("Neue Klasse: " + name); } // ino.end public Menge getFields() { return fielddecl; } /** * @author Andreas Stadelmeier, a10023 * Fügt der Klasse eine Feld hinzu. * Prüft dabei, ob es sich um einen Constructor handelt und wandelt diesen direkt um. * @param feld */ public void addField(Field i) { fielddecl.addElement(i); } // ino.method.getUsedIdsToCheck.23050.definition public Menge getUsedIdsToCheck() // ino.end // ino.method.getUsedIdsToCheck.23050.body { return usedIdsToCheck; } // ino.end // ino.method.setContainedTypes.23053.definition public void setContainedTypes(Menge containedTypes) // ino.end // ino.method.setContainedTypes.23053.body { this.containedTypes = containedTypes; } // ino.end // ino.method.getContainedTypes.23056.definition public Menge getContainedTypes() // ino.end // ino.method.getContainedTypes.23056.body { return containedTypes; } // ino.end /* // ino.method.complete_paralist.23062.definition public Menge complete_paralist(boolean ext) // ino.end // ino.method.complete_paralist.23062.body { //Diese Funktion vervollt�ndigt die Parameterliste f�r vererbte Klassen Menge child = paralist; paralist = (Menge)superclassid.get_ParaList(); for(Enumeration e = child.elements();e.hasMoreElements();){ paralist.addElement(e.nextElement()); } return this.paralist; } // ino.end */ /** * Generiert die ClassFile für diese Klasse. * @param typeinferenceResult - Das ResultSet einer Typinferierung oder null, falls alle Typen eindeutig feststehen. * @return * @throws JVMCodeException // ino.method.codegen.23071.definition public ClassFile codegen(ResultSet typeinferenceResult) throws JVMCodeException // ino.end // ino.method.codegen.23071.body { ClassFile classfile = new ClassFile(); String superClass; // Handling der Superklasse if(superclassid != null) { superClass = superclassid.get_codegen_UsedId(); } else { superClass = "java/lang/Object"; } // Handling der Package //String pkgName = ""; //if (sf.getPackageName() != null) { // pkgName = sf.getPackageName().get_codegen_UsedId() + "/"; //} //geändert von Andreas Stadelmeier: pkgName wird nicht mehr aus dem SourceFile ausgelesen: String packageName = ""; if(pkgName != null) packageName = pkgName.get_Name_1Element(); classfile.add_class(getName(), superClass, getAccessFlags()); // Handling fuer Superinterfaces classfile.addSuperInterfaces(getSuperInterfaces()); // Generics hinzufuegen - falls erforderlich classfile.addGenerics(this.paralist,superclassid, this.getSuperInterfaces()); // Body der Classfile generieren //if(body != null) { this.codegen(classfile, this.paralist); //} // Ueberpruefung, ob Konstruktor generiert // Falls nicht, default-Konstruktor erzeugen if(!classfile.get_constructor_founded()) { classfile.add_method("", "()V", null, null, null, (short)0, this.paralist, false); } //classfile.codegen(); codegenlog.info("Compilierung erfolgreich abgeschlossen, "+ getName() + ".class erstellt."); return classfile; } */ public void set_UsedId (UsedId uid) // ino.end // ino.method.set_UsedId.23074.body { this.superclassid = uid; } // ino.end /** * Setzt den ClassBody dieser Klasse. Wird zum Parsen benötigt. * Der ClassBody enthält sämtliche Felder dieser Klasse. * Mit dem Aufruf dieser Methode werden alle Felder des ClassBody in diese Class übertragen. * (Nur einmal während des Parsens aufrufen!) */ public void set_ClassBody(ClassBody body) { Menge tempFields=body.getFields(); for(Field f : this.getFields()){ if(f instanceof Method){ //Wenn es sich um eine Methode handelt ist eine zusätzliche Prüfung erfoderlich: (Ist es ein Konstruktor?) Method m = (Method)f; /* * Ermitteln ob es sich bei der Methode um einen Konstruktor handelt: * (Parser kann nicht zwischen Methode und Konstruktor unterscheiden. * Denn für einen Konstruktor gelten besondere Regeln: * -Typ des Blocks eines Konstruktor ist void (kein Return-Statement) * -Rückgabetyp der Methode/Konstruktors ist der Typ der Klasse * -Ein Konstruktor kann nicht aufgerufen werden (nur mit new) */ if(m.get_Method_Name().equals(""))throw new TypeinferenceException(" ist kein gültiger Methodenname", m); if((m.get_Method_Name().equals(this.getName()))) { Constructor constructor = new Constructor(m, this); tempFields.add(constructor); //Den Konstruktor anstatt der Methode anfügen }else{ //Handelt es sich um keinen Konstruktor, dann die Methode unverändert den Feldern hinzufügen: tempFields.add(m); } }else{ tempFields.add(f); //Ansonsten das Feld anfügen... } } this.fielddecl = tempFields; } // ino.method.set_class_block.23080.definition public void set_class_block(Block block) // ino.end // ino.method.set_class_block.23080.body { this.class_block = block; } // ino.end // ino.method.get_Superclass_Name.23086.definition public JavaClassName get_Superclass_Name() // ino.end // ino.method.get_Superclass_Name.23086.body { if(superclassid!=null) return superclassid.getQualifiedName(); else return null; } // ino.end // ino.method.get_class_block.23092.definition public Block get_class_block() // ino.end // ino.method.get_class_block.23092.body { return class_block; } // ino.end // ino.method.does_Class_extend.23095.definition public boolean does_Class_extend() // ino.end // ino.method.does_Class_extend.23095.body { if(superclassid==null) return false; else return true; } // ino.end /* // ino.method.set_ParaList.23098.definition public void set_ParaList(Menge para) // ino.end // ino.method.set_ParaList.23098.body { this.paralist = para; } // ino.end */ // ino.method.get_ParaList.23101.definition public Menge get_ParaList() // ino.end // ino.method.get_ParaList.23101.body { //if(this.paralist == null)return new Menge(); return this.getGenericParameter(); } // ino.end // ino.method.set_ParaHash.23104.definition public void set_ParaHash(Hashtable hash) // ino.end // ino.method.set_ParaHash.23104.body { this.parahash = hash; } // ino.end // ino.method.get_ParaHash.23107.definition public Hashtable get_ParaHash() // ino.end // ino.method.get_ParaHash.23107.body { return this.parahash; } ///////////////////////////////////////////////////////////////////////// // TypeReconstructionAlgorithmus ///////////////////////////////////////////////////////////////////////// // ino.method.TRProg.23110.defdescription type=javadoc /** * Ausgangspunkt f�r den Typrekonstruktionsalgorithmus. Hier werden zun�chst * die Mengen von Typannahmen V_fields_methods und V_i erstellt, die als Eingabe * f�r den Algorithmus dienen.
* (siehe Algorithmus 5.17 TRProg, Martin Pl�micke) *
Author: J�rg B�uerle * @param supportData * @param globalAssumptions * @return Liste aller bisher berechneten, m�glichen Typkombinationen * @throws CTypeReconstructionException */ // ino.end // ino.method.TRProg.23110.definition public ConstraintsSet typeReconstruction(FC_TTO supportData, TypeAssumptions globalAssumptions) // ino.end // ino.method.TRProg.23110.body { /* */ ////////////////////////////// // Und los geht's: ////////////////////////////// inferencelog.info("Rufe TRStart()...", Section.TYPEINFERENCE); typinferenzLog.debug("Erstellte FiniteClosure: "+supportData, Section.TYPEINFERENCE); ////////////////////////////// // Ab hier ... // @author A10023 - Andreas Stadelmeier: ////////////////////////////// //Erzeuge Assumptions: TypeAssumptions assumptions = this.getPrivateFieldAssumptions(); //Globale Assumptions anfügen: assumptions.add(globalAssumptions); ConstraintsSet oderConstraints = new ConstraintsSet(); for(Type gparam : this.get_ParaList()){ if(gparam instanceof GenericTypeVar)assumptions.add(((GenericTypeVar)gparam).createAssumptions()); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen } for(Type gparam : this.get_ParaList()){ if(gparam instanceof GenericTypeVar)oderConstraints.add(((GenericTypeVar)gparam).TYPE(assumptions)); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen } typinferenzLog.debug("Erstellte Assumptions: "+assumptions, Section.TYPEINFERENCE); /* //Generiere Liste mit Expressions, welche zur Initialisierung von Feldern verwendet werden. Menge fieldInitializers = new Menge(); for(FieldDeclaration field : body.getFieldInitializations()){ Assign fieldAssign = new Assign(0,0); Expr expr1 = new LocalOrFieldVar(field.getName(), 0); Expr expr2 = field.getWert(); fieldAssign.set_Expr(expr1, expr2); fieldInitializers.add(fieldAssign); } */ //ConstraintsSet oderConstraints = this.TYPE(this.getMethodList(), fieldInitializers, assumptions); this.superClass = this.superClass.TYPE(assumptions, this); for(Field f:this.getFields()){ oderConstraints.add(f.TYPE(assumptions)); } typinferenzLog.debug("Erstellte Constraints: "+oderConstraints, Section.TYPEINFERENCE); return oderConstraints; } /** * Ermittelt alle privaten Felder und Methoden der Klasse und Erstellt eine Assumption für diese. * Bemerkung: Momentan werden noch alle Felder dieser Klasse zurückgegeben. * @return Die erstellten TypeAssumptions */ private TypeAssumptions getPrivateFieldAssumptions() { if(this.typeAssumptions != null)return this.typeAssumptions; //Das sorgt dafür, dass die Assumptions nur einmalig generiert werden. TypeAssumptions assumptions = new TypeAssumptions(this.getName()); //this.getMethodList(); //Diese Funktion muss zuerst ausgeführt werden. //Assumption für this, also die aktuelle Klasse: (ist nicht mehr nötig, da jedes AssumptionSet einer Klasse (dem namen einer Klasse) zugewiesen ist. //CLocalVarTypeAssumption thisAssumption = new CLocalVarTypeAssumption(this.name, name, 0, 0, name, "this", new RefType(name,0), 0, 0, null); //assumptions.setThisV(thisAssumption); for(Field field : this.getFields()){ if(!field.isPublic())assumptions.add(field.createTypeAssumptions(this)); } //Eine Assumption für den Standardkonstruktor: // (Ein Standardkonstruktor wird immer angefügt, da es momentan keine statischen Klassen gibt) //auskommentiert, da der Standardkonstruktor beim Parser-Postprocessing angefügt wird. //if(assumptions.getMethodAssumptions(this.getName(), "").size()==0){ //Falls kein Konstruktor für diese Klasse definiert wurde: // assumptions.addMethodAssumption(new RefType(this.getName(),0), "", new RefType(this.getName(),0), new Menge()); //} this.typeAssumptions = assumptions; //Diese müssen anschließend nicht wieder generiert werden. return assumptions; } // ino.method.toString.23125.defdescription type=javadoc /** *
Author: Martin Pl�micke * @return */ // ino.end // ino.method.toString.23125.definition public String toString() // ino.end // ino.method.toString.23125.body { //return superclassid.toString() + body.toString(); //geaendert PL 07-07-28 return name; } // ino.end // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.defdescription type=javadoc /** * Alle Methoden der Klassen überprüfen, ob sie als * RefType deklarierte Attribute haben, die aber GenericTypeVars sind * und ggf. ersetzen * * Bsp.: * bei public E elementAt(i){...} wird E vorerst als RefType erkannt * */ // ino.end // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.definition public void wandleRefTypeAttributes2GenericAttributes() // ino.end // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.body { for(Field f : this.getFields()){ //f.wandleRefTypeAttributes2GenericAttributes(paralist); } } /** * HOTI * Liefert bei Klassen die fullyQualified angegeben wurden * nur den schlussendlichen Bezeichner * p.ex. de.dhbwstuttgart.typeinference.Menge => Menge * @return */ // ino.end // ino.method.getSimpleName.23140.definition public String getSimpleName() // ino.end // ino.method.getSimpleName.23140.body { return UsedId.createFromQualifiedName(getName().toString(),-1).getSimpleName(); } // ino.end public String getTypeInformation(Menge methodList, Menge fieldList){ String ret = this.name+": "; for(Expr field : fieldList){ ret+=field.getTypeInformation()+"\n"; } for(Method m : methodList){ ret+=m.getTypeInformation()+"\n"; } return ret; } /** * Generiert den JavaCode dieser Klasse im Falle für das übergebene resultSet. * Dem ResultSet entsprechend werden in diesem Java-Code die TypePlaceholder durch die in ResultSet stehenden Typen ersetzt. * @return Java-Sourcefile */ public String printJavaCode(TypeinferenceResultSet reconstructionResult){ JavaCodeResult ret = new JavaCodeResult("class "); JavaCodeResult classBodyCode = new JavaCodeResult(); if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach(" "); classBodyCode.attach(this.name + " extends ").attach(superclassid.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach("\n"); JavaCodeResult bodyString = new JavaCodeResult("{\n"); for(Field field : this.fielddecl)bodyString.attach( field.printJavaCode(reconstructionResult.getUnifiedConstraints()) ).attach( "\n" ); bodyString.attach("}\n"); classBodyCode.attach(bodyString); //Zuerst die generischen Parameter für diese Klasse berechnen: //this.createGenericTypeVars(classBodyCode.getUnresolvedTPH()); if(this.genericClassParameters != null && this.genericClassParameters.size()>0){ ret.attach("<"); Iterator it = this.genericClassParameters.iterator(); while(it.hasNext()){ GenericTypeVar tph = it.next(); ret.attach(tph.printJavaCode(reconstructionResult.getUnifiedConstraints())); if(it.hasNext())ret.attach(", "); } ret.attach(">"); } String stringReturn = ret.attach(classBodyCode).toString(); return stringReturn; } /** * Errechnet die Generischen Parameter der Klasse für diese Klasse. * Die berechneten Variablen werden anschließend in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars überschrieben. * @param tphs : Alle übriggebliebenen TypePLaceholder private void createGenericTypeVars(Menge tphs){ this.genericClassParameters = new GenericDeclarationList(new Menge()); for(TypePlaceholder tph : tphs){ GenericTypeVar toAdd = new GenericTypeVar(tph,this.getOffset()); if(!this.genericClassParameters.contains(toAdd))this.genericClassParameters.add(toAdd); } } */ /** * Errechnet die Generischen Parameter der Klasse für diese Klasse. * Die berechneten Variablen werden anschließend in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars überschrieben. * @param reconstructionResult public void createGenericTypeVars(TypeinferenceResultSet reconstructionResult){ this.genericClassParameters = new Menge(); for(Pair pair : reconstructionResult.getUnifiedConstraints()){ if(pair.TA2 instanceof TypePlaceholder && pair.TA1 instanceof TypePlaceholder){// if(pair.OperatorSmallerExtends() || pair.OperatorSmaller()){ Type ta1=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA1); Type ta2=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA2); this.genericClassParameters.add(new GenericTypeVar(new Pair(ta1,ta2),this.getOffset())); } } for(Pair pair : reconstructionResult.getConstraints()){ if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA1)){ this.genericClassParameters.add(new GenericTypeVar(pair.TA1,this.getOffset())); } if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA2)){ this.genericClassParameters.add(new GenericTypeVar(pair.TA2, this.getOffset())); } } } */ public int getOffset(){ return this.offset; } /** * Erstellt einen RefType, welcher auf diese Klasse verweist * Ersetzt alle Generischen Variablen in der Parameterliste mit TPH * @return */ public RefType getType() { /* Menge parameter = new Menge(); for(Type param : this.get_ParaList()){ parameter.add(((GenericTypeVar)param).getTypePlaceHolder());//(TypePlaceholder.fresh()); //Hier ist kein ReplacementListener notwendig. Der Typ soll nie eingesetzt werden. Der TPH wird nur gebraucht, damit das Unifizieren funktioniert. } */ return new RefType(this.getName().toString(), this.get_ParaList(),this, 0); } /** * Ermittelt die Sichtbaren Felder und Methoden der Klasse. * (Momentan sind im Projekt alle Felder und Methoden "package private", da der Parser keine Access-Modifier einlesen kann. * @return */ public TypeAssumptions getPublicFieldAssumptions() { TypeAssumptions ret = new TypeAssumptions();//this.getPrivateFieldAssumptions(); ret.addClassAssumption(new ClassAssumption(this)); for(Field f : this.getFields()){ if(f.isPublic())ret.add(f.createTypeAssumptions(this)); } for(GenericTypeVar gtv : this.getGenericParameter()){ ret.add(gtv.createAssumptions()); } return ret; } @Override public void parserPostProcessing(SyntaxTreeNode parent) { //Wenn keine Superklasse, dann erbt die Klasse zwangsweise von Object: if(superclassid == null || superclassid.get_Name().size()<1){ int superclassidOffset = superclassid == null ? 0 : superclassid.getOffset(); superclassid = new UsedId("Object", superclassidOffset); } //Alle Methoden auf Konstruktoren durchsuchen und diese umwandeln: Menge tempFields = new Menge(); for(Field f : this.getFields()){ if(f instanceof Method && !(f instanceof Constructor)){ //Der Check, ob f ein Konstruktor ist eigentlich obsolet, da der Parser keinen Konstruktor generiert Method method = (Method)f; if(method.get_Method_Name().equals(this.getName().toString()) ){ tempFields.add(new Constructor(method, this)); }else{ tempFields.add(f); } }else{ tempFields.add(f); } } this.fielddecl = tempFields; //Prüfen ob ein Konstruktor vorhanden ist: boolean constructorVorhanden = false; for(Field f : this.getFields()){ if(f instanceof Constructor){ constructorVorhanden = true; break; } } if(!constructorVorhanden){//Falls kein Konstruktor vorhanden ist, muss noch der Standardkonstruktor angefügt werden: Block konstruktorBlock = new Block(); konstruktorBlock.statements.add(new SuperCall(konstruktorBlock)); Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(konstruktorBlock,this.getName().toString(), this), this); //Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(this.getName().toString(), this)); this.addField(standardKonstruktor); } if(this.genericClassParameters == null)this.setGenericParameter(new GenericDeclarationList(new Menge(), 0)); /*//Nicht mehr notwendig, Generische Klassenparameter werden nun immer direkt in die genericClassParameters gespeichert. for(Type t : this.get_ParaList()){ if(t instanceof GenericTypeVar)this.genericClassParameters.add((GenericTypeVar)t); else this.genericClassParameters.add(new GenericTypeVar(t.get_Name(),this,-1)); } */ /* for(Type t : this.get_ParaList()){ t.parserPostProcessing(this); } */ /* for(GenericTypeVar gtv : this.getGenericParameter()){ gtv.setParentClass(this);; } */ //TODO: Umwandlung zu RefTypes funktioniert noch nicht richtig. (siehe LambdaTest2) //Als RefType geparste Generische Variablen umwandeln: this.wandleRefTypeAttributes2GenericAttributes(); //Erst am Schluss, nachdem Methoden zu Konstruktoren umgewandelt wurden: super.parserPostProcessing(parent); } @Override public SyntaxTreeNode getParent() { return this; } @Override public Menge getChildren() { Menge ret = new Menge(); //for(Field f : this.getFields()){ // ret.add(f); //} ret.addAll(this.getFields()); ret.addAll(this.get_ParaList()); ret.addAll(this.getGenericParameter()); return ret; } @Override public boolean equals(Object obj){ if(!(obj instanceof Class))return false; Class cl = (Class) obj; if(!(cl.getName().equals(this.getName())))return false; return true; } @Override public Menge getGenericParameter() { if(this.genericClassParameters == null)return new Menge(); return this.genericClassParameters.getMenge(); } @Override public String getDescription(){ return "class "+this.getName(); } @Override public int getVariableLength() { // TODO Auto-generated method stub return 0; } @Override public void setGenericParameter(GenericDeclarationList params) { this.genericClassParameters = params; } @Override public String getGenericVarDeclarationString(String genericVarDeclaration) { if(this.genericClassParameters != null){ return ", "+genericVarDeclaration; }else{ return "<"+genericVarDeclaration+">"; } } @Override public int getGenericVarDeclarationOffset(){ // Falls Generische Parameterliste vorhanden, hier Wert der Liste zurückgegebn if(this.genericClassParameters != null){ return this.genericClassParameters.getEndOffset(); }else{ return this.offset; } } /** * Die Super Klasse dieser Klasse. * @return null für Klasse Object */ public Type getSuperClass(){ return this.superClass; } @Override public boolean isClass() { return true; } public boolean isInterface(){ return false; } /* private Collection getGenericClasses() { Collection results = new Menge<>(); for(Field field : this.fielddecl){ Type type = field.getType(); //Der Type des Feldes if(type instanceof RefType){ RefType refType = (RefType) type; if(!refType.getCombinedType(null).equals(refType.get_Name().replace(".", "%"))){ results.addAll(generateGenericClass(refType.getCombinedType(null), new Class("java/util/Vector",-1))); } } if(field instanceof Method){ Method method = (Method) field; ParameterList parameterList = method.getParameterList(); //Die Typen der Methodenparameter for(FormalParameter parameter: parameterList){ Type parameterType = parameter.getType(); if(parameterType instanceof RefType){ RefType refType = (RefType) parameterType; if(!refType.getCombinedType(null).equals(refType.get_Name().replace(".", "%"))){ results.addAll(generateGenericClass(refType.getCombinedType(null), new Class("java/util/Vector",-1))); } } } } } return results; } */ /* private Menge generateGenericClass(String name, Class superClass){ //TODO: bytecode -- Generics hinzuf�gen //Type superClassType = superClass.getType(); //TODO: bytecode //ClassGenerator genericClassGenerator = new ClassGenerator(name, superClassType, name + ".java", Constants.ACC_PUBLIC , new String[] { }, new TypeinferenceResultSet(null, null, null)); //TODO: bytecode -- Namen der neuen Klasse Class generatedClass = new Class(name, 0); //TODO: bytecode -- alle Konstruktoren generieren Block konstruktorBlock = new Block(); konstruktorBlock.setType(new de.dhbwstuttgart.syntaxtree.type.Void(konstruktorBlock, 0)); konstruktorBlock.statements.add(new SuperCall(konstruktorBlock)); Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(konstruktorBlock, name, superClass), superClass); standardKonstruktor.parserPostProcessing(generatedClass); generatedClass.addField(standardKonstruktor); return generatedClass.genByteCode(new TypeinferenceResultSet(generatedClass, new Menge<>(), new ResultSet())); } */ } // ino.end