Added sealed classes to AST

This commit is contained in:
luca9913 2023-07-14 08:52:51 +02:00
parent 1643412f1b
commit c0c46e197f
7 changed files with 235 additions and 210 deletions

View File

@ -85,6 +85,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import javassist.compiler.SyntaxError;
public class SyntaxTreeGenerator { public class SyntaxTreeGenerator {
private JavaClassRegistry reg; private JavaClassRegistry reg;
@ -219,22 +220,15 @@ public class SyntaxTreeGenerator {
implementedInterfaces.addAll(convert(ctx.typeList(0), generics)); implementedInterfaces.addAll(convert(ctx.typeList(0), generics));
} }
// Ist Bit für 'sealed'-Modifier gesetzt // Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0) { if ((modifiers & 4096) != 0 && !Objects.isNull(ctx.PERMITS())) {
switch (ctx.typeList().size()) { // permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
case 1: { permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
permittedSubtypes.addAll(convert(ctx.typeList(0), generics)); } else {
break; // falls sealed modifier ohne 'permits'-List oder umgekehrt
throw new NotImplementedException("Invalid sealed class declaration");
} }
case 2: { return new ClassOrInterface(modifiers, name, fielddecl, Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset)), methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
permittedSubtypes.addAll(convert(ctx.typeList(1), generics));
break;
}
default: {
break;
}
}
}
return new ClassOrInterface(modifiers, name, fielddecl, Optional.of(this.generatePseudoConstructor(ctx.identifier().getText(), name, superClass, genericClassParameters, offset)), methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset);
} }
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) { private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
@ -388,7 +382,16 @@ public class SyntaxTreeGenerator {
if (!Objects.isNull(ctx.EXTENDS())) { if (!Objects.isNull(ctx.EXTENDS())) {
extendedInterfaces.addAll(convert(ctx.typeList(0), generics)); extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
} }
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, ctx.getStart()); List<RefType> permittedSubtypes = new ArrayList<>();
// Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0 && !Objects.isNull(ctx.PERMITS())) {
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
} else {
// falls sealed modifier ohne 'permits'-List oder umgekehrt
throw new NotImplementedException("Invalid sealed class declaration");
}
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(), genericParams, superClass, true, extendedInterfaces, permittedSubtypes, ctx.getStart());
} }
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) { private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {

View File

@ -2,7 +2,6 @@ package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.statement.Literal;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import java.util.Iterator; import java.util.Iterator;
@ -274,4 +273,47 @@ public abstract class AbstractASTWalker implements ASTVisitor {
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
this.visit((MethodCall) superCall); this.visit((MethodCall) superCall);
} }
@Override
public void visit(Switch switchStmt) {
switchStmt.getSwitch().accept(this);
switchStmt.getBlocks().stream().forEach((switchBlock) -> {
switchBlock.accept(this);
});
}
@Override
public void visit(SwitchBlock switchBlock) {
switchBlock.getLabels().stream().forEach((label) -> {
label.accept(this);
});
switchBlock.getStatements().stream().forEach((stmt) -> {
stmt.accept(this);
});
}
@Override
public void visit(SwitchLabel switchLabel) {
switchLabel.getExpression().accept(this);
}
@Override
public void visit(Yield aYield) {
aYield.accept(this);
}
@Override
public void visit(Pattern aPattern) {
}
@Override
public void visit(RecordPattern aRecordPattern) {
}
@Override
public void visit(GuardedPattern aGuardedPattern) {
}
} }

View File

@ -24,45 +24,46 @@ import java.util.Optional;
/** /**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces * Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
*/ */
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private Boolean methodAdded = false; //wird benoetigt bei in JavaTXCompiler.getConstraints() private Boolean methodAdded = false; // wird benoetigt bei in JavaTXCompiler.getConstraints()
protected int modifiers; protected int modifiers;
protected JavaClassName name; protected JavaClassName name;
private List<Field> fields = new ArrayList<>(); private List<Field> fields = new ArrayList<>();
private Optional<Constructor> fieldInitializations; //PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen private Optional<Constructor> fieldInitializations; // PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen
private List<Method> methods = new ArrayList<>(); private List<Method> methods = new ArrayList<>();
private GenericDeclarationList genericClassParameters; private GenericDeclarationList genericClassParameters;
private RefType superClass; private RefType superClass;
protected boolean isInterface; protected boolean isInterface;
private List<RefType> implementedInterfaces; private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors; private List<Constructor> constructors;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset) {
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters,
RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset){
super(offset); super(offset);
if(isInterface && !Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE; if (isInterface && !Modifier.isInterface(modifiers))
modifiers += Modifier.INTERFACE;
this.modifiers = modifiers; this.modifiers = modifiers;
this.name = name; this.name = name;
this.fields = fielddecl; this.fields = fielddecl;
this.fieldInitializations= fieldInitializations; this.fieldInitializations = fieldInitializations;
this.genericClassParameters = genericClassParameters; this.genericClassParameters = genericClassParameters;
this.superClass = superClass; this.superClass = superClass;
this.isInterface = isInterface; this.isInterface = isInterface;
this.implementedInterfaces = implementedInterfaces; this.implementedInterfaces = implementedInterfaces;
this.permittedSubtypes = permittedSubtypes;
this.methods = methods; this.methods = methods;
this.constructors = constructors; this.constructors = constructors;
} }
/* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte /*
* alle anderen Datenobjekte werden nur kopiert. * erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte alle anderen Datenobjekte werden nur kopiert.
*/ */
public ClassOrInterface(ClassOrInterface cl){ public ClassOrInterface(ClassOrInterface cl) {
super(cl.getOffset()); super(cl.getOffset());
this.modifiers = cl.modifiers; this.modifiers = cl.modifiers;
this.name = cl.name; this.name = cl.name;
this.fields = new ArrayList<>(cl.fields); this.fields = new ArrayList<>(cl.fields);
this.fieldInitializations= cl.fieldInitializations; this.fieldInitializations = cl.fieldInitializations;
this.genericClassParameters = cl.genericClassParameters; this.genericClassParameters = cl.genericClassParameters;
this.superClass = cl.superClass; this.superClass = cl.superClass;
this.isInterface = cl.isInterface; this.isInterface = cl.isInterface;
@ -71,49 +72,47 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
this.constructors = new ArrayList<>(cl.constructors); this.constructors = new ArrayList<>(cl.constructors);
} }
//Gets if it is added // Gets if it is added
public Boolean areMethodsAdded() { public Boolean areMethodsAdded() {
return methodAdded; return methodAdded;
} }
//Sets that it is added // Sets that it is added
public void setMethodsAdded() { public void setMethodsAdded() {
methodAdded = true; methodAdded = true;
} }
// Gets class name // Gets class name
public JavaClassName getClassName(){ public JavaClassName getClassName() {
return this.name; return this.name;
} }
// Get modifiers // Get modifiers
public int getModifiers(){ public int getModifiers() {
return this.modifiers; return this.modifiers;
} }
public List<Field> getFieldDecl(){ public List<Field> getFieldDecl() {
return this.fields; return this.fields;
} }
public Optional<Constructor> getfieldInitializations(){ public Optional<Constructor> getfieldInitializations() {
return this.fieldInitializations; return this.fieldInitializations;
} }
public List<Method> getMethods(){ public List<Method> getMethods() {
return this.methods; return this.methods;
} }
/* /*
public RefType getType() { * public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset());
}
*/ */
//TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt // TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt
public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass ,Token offset){ public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass, Token offset) {
//Hier wird immer ein generischer Typ generiert, also mit Type placeholdern // Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar genericTypeVar : genericsOfClass){ for (GenericTypeVar genericTypeVar : genericsOfClass) {
//params.add(genericTypeVar.getTypePlaceholder()); // params.add(genericTypeVar.getTypePlaceholder());
params.add(TypePlaceholder.fresh(offset)); params.add(TypePlaceholder.fresh(offset));
} }
return new RefType(name, params, offset); return new RefType(name, params, offset);
@ -123,17 +122,17 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
* *
* @return die aktuelle Klasse als RefType * @return die aktuelle Klasse als RefType
*/ */
public RefType generateTypeOfThisClass(){ public RefType generateTypeOfThisClass() {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar genericTypeVar : this.getGenerics()){ for (GenericTypeVar genericTypeVar : this.getGenerics()) {
//params.add(genericTypeVar.getTypePlaceholder()); // params.add(genericTypeVar.getTypePlaceholder());
params.add(new GenericRefType(genericTypeVar.getName(), new NullToken())); params.add(new GenericRefType(genericTypeVar.getName(), new NullToken()));
} }
return new RefType(name, params, new NullToken()); return new RefType(name, params, new NullToken());
} }
/** /**
* Die Superklasse im Kontext dieser ClassOrInterface * Die Superklasse im Kontext dieser ClassOrInterface Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
* Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
*/ */
public RefType getSuperClass() { public RefType getSuperClass() {
return superClass; return superClass;

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.syntaxtree; package de.dhbwstuttgart.syntaxtree;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -11,6 +12,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
public class Record extends ClassOrInterface { public class Record extends ClassOrInterface {
public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) { public Record(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset) {
super(modifiers, name, fielddecl, fieldInitializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, offset); super(modifiers, name, fielddecl, fieldInitializations, methods, constructors, genericClassParameters, superClass, isInterface, implementedInterfaces, new ArrayList<>(), offset);
} }
} }

View File

@ -29,13 +29,11 @@ import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
/** /**
* Anmerkung: * Anmerkung: Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen, dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen.
* Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen,
* dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen.
*/ */
public class ASTFactory { public class ASTFactory {
public static ClassOrInterface createClass(java.lang.Class jreClass){ public static ClassOrInterface createClass(java.lang.Class jreClass) {
// TODO Inner classes // TODO Inner classes
@ -82,7 +80,7 @@ public class ASTFactory {
} }
}; };
classReader.accept(classVisitor, new Attribute[]{new JavaTXSignatureAttribute()}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); classReader.accept(classVisitor, new Attribute[] { new JavaTXSignatureAttribute() }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
classSignature = classVisitor.classSignature; classSignature = classVisitor.classSignature;
} }
} catch (IOException e) { } catch (IOException e) {
@ -92,7 +90,7 @@ public class ASTFactory {
JavaClassName name = new JavaClassName(jreClass.getName()); JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>(); List<Method> methoden = new ArrayList<>();
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>(); List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
for(java.lang.reflect.Constructor constructor : jreClass.getConstructors()){ for (java.lang.reflect.Constructor constructor : jreClass.getConstructors()) {
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor))); var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c)); createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
} }
@ -100,53 +98,59 @@ public class ASTFactory {
Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods())); Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods()));
Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods); Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods);
allInheritedMethods.removeAll(allDeclaredMethods); allInheritedMethods.removeAll(allDeclaredMethods);
for(java.lang.reflect.Method method : allDeclaredMethods){ for (java.lang.reflect.Method method : allDeclaredMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, false)); methoden.add(createMethod(method, signature, jreClass, false));
} }
for(java.lang.reflect.Method method : allInheritedMethods){ for (java.lang.reflect.Method method : allInheritedMethods) {
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method))); var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, true)); methoden.add(createMethod(method, signature, jreClass, true));
} }
List<Field> felder = new ArrayList<>(); List<Field> felder = new ArrayList<>();
for(java.lang.reflect.Field field : jreClass.getDeclaredFields()){ for (java.lang.reflect.Field field : jreClass.getDeclaredFields()) {
felder.add(createField(field, name)); felder.add(createField(field, name));
} }
int modifier = jreClass.getModifiers(); int modifier = jreClass.getModifiers();
boolean isInterface = jreClass.isInterface(); boolean isInterface = jreClass.isInterface();
//see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class // see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class
ParameterizedType parameterSuperClass = null; ParameterizedType parameterSuperClass = null;
Type tempSuperClass = jreClass.getGenericSuperclass(); Type tempSuperClass = jreClass.getGenericSuperclass();
if(tempSuperClass != null && tempSuperClass instanceof ParameterizedType) if (tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
parameterSuperClass = (ParameterizedType) tempSuperClass; parameterSuperClass = (ParameterizedType) tempSuperClass;
java.lang.Class superjreClass = jreClass.getSuperclass(); java.lang.Class superjreClass = jreClass.getSuperclass();
RefType superClass; RefType superClass;
if(parameterSuperClass != null){ if (parameterSuperClass != null) {
superClass = (RefType) createType(parameterSuperClass); superClass = (RefType) createType(parameterSuperClass);
}else if(superjreClass != null){ } else if (superjreClass != null) {
superClass = (RefType) createType(superjreClass); superClass = (RefType) createType(superjreClass);
}else{//Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!) } else {// Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!)
superClass = (RefType) createType(java.lang.Object.class); superClass = (RefType) createType(java.lang.Object.class);
} }
List<RefType> implementedInterfaces = new ArrayList<>(); List<RefType> implementedInterfaces = new ArrayList<>();
for(Type jreInterface : jreClass.getGenericInterfaces()){ for (Type jreInterface : jreClass.getGenericInterfaces()) {
implementedInterfaces.add((RefType) createType(jreInterface)); implementedInterfaces.add((RefType) createType(jreInterface));
} }
List<RefType> permittedSubtypes = new ArrayList<>();
if (jreClass.isSealed()) {
for (Class subclass : jreClass.getPermittedSubclasses()) {
permittedSubtypes.add((RefType) createType(subclass));
}
}
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature); GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature);
Token offset = new NullToken(); //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde Token offset = new NullToken(); // Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
return new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */,methoden, konstruktoren, genericDeclarationList, superClass,isInterface, implementedInterfaces, offset); return new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */, methoden, konstruktoren, genericDeclarationList, superClass, isInterface, implementedInterfaces, permittedSubtypes, offset);
} }
private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) { private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) {
return new Field(field.getName(), createType(field.getGenericType()), field.getModifiers(), new NullToken()); return new Field(field.getName(), createType(field.getGenericType()), field.getModifiers(), new NullToken());
} }
//private static RefType createType(Class classType) { // private static RefType createType(Class classType) {
// return createClass(classType).getType(); // return createClass(classType).getType();
//} // }
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) { private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
String name = constructor.getName(); String name = constructor.getName();
@ -155,10 +159,11 @@ public class ASTFactory {
Type[] jreGenericParams = constructor.getGenericParameterTypes(); Type[] jreGenericParams = constructor.getGenericParameterTypes();
List<FormalParameter> params = new ArrayList<>(); List<FormalParameter> params = new ArrayList<>();
int i = 0; int i = 0;
for(Type jreParam : jreGenericParams){ for (Type jreParam : jreGenericParams) {
if (jreParam == null) continue; if (jreParam == null)
continue;
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam); RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
i++; i++;
} }
ParameterList parameterList = new ParameterList(params, new NullToken()); ParameterList parameterList = new ParameterList(params, new NullToken());
@ -167,20 +172,20 @@ public class ASTFactory {
Token offset = new NullToken(); Token offset = new NullToken();
int modifier = constructor.getModifiers(); int modifier = constructor.getModifiers();
if(inClass.equals(java.lang.Object.class)){ if (inClass.equals(java.lang.Object.class)) {
return Optional.empty(); return Optional.empty();
} }
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset /*, new ArrayList<>() geloescht PL 2018-11-24 */)); return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name, returnType, parameterList, block, gtvDeclarations, offset /* , new ArrayList<>() geloescht PL 2018-11-24 */));
} }
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited){ public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited) {
String name = jreMethod.getName(); String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType; RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType; Type jreRetType;
if(jreMethod.getGenericReturnType()!=null){ if (jreMethod.getGenericReturnType() != null) {
jreRetType = jreMethod.getGenericReturnType(); jreRetType = jreMethod.getGenericReturnType();
}else{ } else {
jreRetType = jreMethod.getReturnType(); jreRetType = jreMethod.getReturnType();
} }
returnType = createType(jreRetType); returnType = createType(jreRetType);
@ -188,10 +193,11 @@ public class ASTFactory {
Type[] jreGenericParams = jreMethod.getGenericParameterTypes(); Type[] jreGenericParams = jreMethod.getGenericParameterTypes();
List<FormalParameter> params = new ArrayList<>(); List<FormalParameter> params = new ArrayList<>();
int i = 0; int i = 0;
for(Type jreParam : jreGenericParams){ for (Type jreParam : jreGenericParams) {
if (jreParam == null) continue; if (jreParam == null)
continue;
RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam); RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam);
params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); params.add(new FormalParameter(jreParams[i].getName(), paramType, new NullToken()));
i++; i++;
} }
ParameterList parameterList = new ParameterList(params, new NullToken()); ParameterList parameterList = new ParameterList(params, new NullToken());
@ -199,13 +205,13 @@ public class ASTFactory {
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature); GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
Token offset = new NullToken(); Token offset = new NullToken();
return new Method(jreMethod.getModifiers(), name,returnType, parameterList, block, gtvDeclarations, offset, isInherited); return new Method(jreMethod.getModifiers(), name, returnType, parameterList, block, gtvDeclarations, offset, isInherited);
} }
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) { public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
if (signature == null) { if (signature == null) {
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>(); List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
for(TypeVariable jreTV : typeParameters){ for (TypeVariable jreTV : typeParameters) {
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName); de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv); gtvs.add(gtv);
} }
@ -217,7 +223,8 @@ public class ASTFactory {
} }
public static GenericDeclarationList createGenerics(String signature) { public static GenericDeclarationList createGenerics(String signature) {
if (signature == null) return new GenericDeclarationList(new ArrayList<>(), new NullToken()); if (signature == null)
return new GenericDeclarationList(new ArrayList<>(), new NullToken());
var gtvs = new ArrayList<GenericTypeVar>(); var gtvs = new ArrayList<GenericTypeVar>();
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) { var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
@ -226,7 +233,8 @@ public class ASTFactory {
final Stack<RefType> classTypes = new Stack<>(); final Stack<RefType> classTypes = new Stack<>();
// All hail the mighty visitor pattern // All hail the mighty visitor pattern
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {}; final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {
};
char wildcard = '='; char wildcard = '=';
@ -334,61 +342,61 @@ public class ASTFactory {
return new GenericDeclarationList(gtvs, new NullToken()); return new GenericDeclarationList(gtvs, new NullToken());
} }
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type){ private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type) {
if(type == null || type.getTypeName().equals("void")){ if (type == null || type.getTypeName().equals("void")) {
return new Void(new NullToken()); return new Void(new NullToken());
}else if(type.getTypeName().equals("int")){ } else if (type.getTypeName().equals("int")) {
return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("byte")){ } else if (type.getTypeName().equals("byte")) {
return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("boolean")){ } else if (type.getTypeName().equals("boolean")) {
return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("char")){ } else if (type.getTypeName().equals("char")) {
return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("short")){ } else if (type.getTypeName().equals("short")) {
return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("double")){ } else if (type.getTypeName().equals("double")) {
return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken());
}else if(type.getTypeName().equals("long")){ } else if (type.getTypeName().equals("long")) {
return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken()); return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken());
}else{ } else {
if(type instanceof TypeVariable){ if (type instanceof TypeVariable) {
//GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()" // GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
return new GenericRefType(type.getTypeName(), new NullToken()); return new GenericRefType(type.getTypeName(), new NullToken());
} }
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
if(type instanceof ParameterizedType){ if (type instanceof ParameterizedType) {
for(Type t : ((ParameterizedType)type).getActualTypeArguments()){ for (Type t : ((ParameterizedType) type).getActualTypeArguments()) {
params.add(createType(t)); params.add(createType(t));
} }
} }
String name = type.getTypeName(); String name = type.getTypeName();
if(name.contains("<")){ //Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A> if (name.contains("<")) { // Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A>
//Diese entfernen: // Diese entfernen:
name = name.split("<")[0]; name = name.split("<")[0];
} }
if(type instanceof java.lang.reflect.WildcardType){ if (type instanceof java.lang.reflect.WildcardType) {
java.lang.reflect.WildcardType wildcardType = (java.lang.reflect.WildcardType) type; java.lang.reflect.WildcardType wildcardType = (java.lang.reflect.WildcardType) type;
if(wildcardType.getLowerBounds().length > 0){ if (wildcardType.getLowerBounds().length > 0) {
return new SuperWildcardType(createType(wildcardType.getLowerBounds()[0]), new NullToken()); return new SuperWildcardType(createType(wildcardType.getLowerBounds()[0]), new NullToken());
}else if(wildcardType.getUpperBounds().length > 0){ } else if (wildcardType.getUpperBounds().length > 0) {
return new ExtendsWildcardType(createType(wildcardType.getUpperBounds()[0]), new NullToken()); return new ExtendsWildcardType(createType(wildcardType.getUpperBounds()[0]), new NullToken());
}else{//Es handelt sich um den '?'-Typ: } else {// Es handelt sich um den '?'-Typ:
return new ExtendsWildcardType(createObjectType(), new NullToken()); return new ExtendsWildcardType(createObjectType(), new NullToken());
} }
}else{ } else {
RefType ret = new RefType(new JavaClassName(name), params, new NullToken()); RefType ret = new RefType(new JavaClassName(name), params, new NullToken());
return ret; return ret;
} }
} }
} }
public static de.dhbwstuttgart.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod){ public static de.dhbwstuttgart.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod) {
JavaClassName parentClass = new JavaClassName(context.getName()); JavaClassName parentClass = new JavaClassName(context.getName());
List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>();
java.lang.reflect.Type[] bounds = jreTypeVar.getBounds(); java.lang.reflect.Type[] bounds = jreTypeVar.getBounds();
if(bounds.length > 0){ if (bounds.length > 0) {
for(java.lang.reflect.Type bound : bounds){ for (java.lang.reflect.Type bound : bounds) {
genericBounds.add(createType(bound)); genericBounds.add(createType(bound));
} }
} }
@ -404,48 +412,26 @@ public class ASTFactory {
} }
/* /*
public Constructor createEmptyConstructor(Class parent){ * public Constructor createEmptyConstructor(Class parent){ Block block = new Block(); block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); block.statements.add(new SuperCall(block));
Block block = new Block(); *
block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); * return ASTFactory.createConstructor(parent, new ParameterList(), block); }
block.statements.add(new SuperCall(block)); *
* public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ block.parserPostProcessing(superClass);
return ASTFactory.createConstructor(parent, new ParameterList(), block); *
} * Method method = ASTFactory.createMethod("<init>", paralist, block, superClass); method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
*
public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ * return new Constructor(method, superClass); }
block.parserPostProcessing(superClass); *
* public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) { // TODO bytecode createClass //String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara Class generatedClass = new Class(className, type, modifiers, supertypeGenPara); generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass));
Method method = ASTFactory.createMethod("<init>", paralist, block, superClass); *
method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); * generatedClass.parserPostProcessing(parent);
*
return new Constructor(method, superClass); * return generatedClass; }
} *
* public static Class createObject(){ return createClass(java.lang.Object.class); }
public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) { *
// TODO bytecode createClass * public static Class createInterface(String className, RefType superClass, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent){ Class generatedClass = new Class(new JavaClassName(className), new ArrayList<Method>(), new ArrayList<Field>(), modifiers, true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1); generatedClass.parserPostProcessing(parent); return generatedClass; }
//String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara *
Class generatedClass = new Class(className, type, modifiers, supertypeGenPara); * public static RefType createObjectType(){ return createObjectClass().getType(); }
generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass));
generatedClass.parserPostProcessing(parent);
return generatedClass;
}
public static Class createObject(){
return createClass(java.lang.Object.class);
}
public static Class createInterface(String className, RefType superClass, Modifiers modifiers,
Menge supertypeGenPara, SourceFile parent){
Class generatedClass = new Class(new JavaClassName(className), new ArrayList<Method>(), new ArrayList<Field>(), modifiers,
true, superClass, new ArrayList<RefType>(), new GenericDeclarationList(), -1);
generatedClass.parserPostProcessing(parent);
return generatedClass;
}
public static RefType createObjectType(){
return createObjectClass().getType();
}
*/ */
} }

View File

@ -17,43 +17,37 @@ public class FamilyOfGenerics {
@Test @Test
public void generateBC() throws Exception { public void generateBC() throws Exception {
/*SourceFile sf = generateAST(); /*
PositionFinder.getPositionOfTPH(sf, null); * SourceFile sf = generateAST(); PositionFinder.getPositionOfTPH(sf, null); TPHExtractor tphExtractor = new TPHExtractor(); List<ResultSet> results = new ArrayList<ResultSet>(); GeneratedGenericsFinder generatedGenericsFinder = new GeneratedGenericsFinder(sf, results);
TPHExtractor tphExtractor = new TPHExtractor(); */
List<ResultSet> results = new ArrayList<ResultSet>();
GeneratedGenericsFinder generatedGenericsFinder = new GeneratedGenericsFinder(sf, results);*/
} }
public static SourceFile generateAST(){ public static SourceFile generateAST() {
ArrayList<ClassOrInterface> classes = new ArrayList<>(); ArrayList<ClassOrInterface> classes = new ArrayList<>();
ArrayList<Field> fields = new ArrayList<>(); ArrayList<Field> fields = new ArrayList<>();
ArrayList<Method> methods = new ArrayList<>(); ArrayList<Method> methods = new ArrayList<>();
fields.add(generateField("fld1")); fields.add(generateField("fld1"));
String[] paramNames = {"a"}; String[] paramNames = { "a" };
methods.add(generateMethod("testMethode", paramNames)); methods.add(generateMethod("testMethode", paramNames));
classes.add(new ClassOrInterface(Modifier.PUBLIC, new JavaClassName("Test"), fields, Optional.empty(), methods, classes.add(new ClassOrInterface(Modifier.PUBLIC, new JavaClassName("Test"), fields, Optional.empty(), methods, new ArrayList<>(), generateEmptyGenericDeclList(), new RefType(new JavaClassName("java.lang.Object"), new NullToken()), false, new ArrayList<>(), new ArrayList<>(), new NullToken()));
new ArrayList<>(), generateEmptyGenericDeclList(),
new RefType(new JavaClassName("java.lang.Object"), new NullToken()),
false, new ArrayList<>(), new NullToken()));
return new SourceFile("Test.jav", classes, new HashSet<>()); return new SourceFile("Test.jav", classes, new HashSet<>());
} }
public static Method generateMethod(String methodName, String[] paramNames){ public static Method generateMethod(String methodName, String[] paramNames) {
ArrayList<FormalParameter> parameters = new ArrayList<>(); ArrayList<FormalParameter> parameters = new ArrayList<>();
for(String str: paramNames) { for (String str : paramNames) {
FormalParameter fp = new FormalParameter(str, TypePlaceholder.fresh(new NullToken()), new NullToken()); FormalParameter fp = new FormalParameter(str, TypePlaceholder.fresh(new NullToken()), new NullToken());
parameters.add(fp); parameters.add(fp);
} }
ParameterList parameterList = new ParameterList(parameters, new NullToken()); ParameterList parameterList = new ParameterList(parameters, new NullToken());
return new Method(Modifier.PUBLIC, methodName, TypePlaceholder.fresh(new NullToken()), parameterList, return new Method(Modifier.PUBLIC, methodName, TypePlaceholder.fresh(new NullToken()), parameterList, new Block(new ArrayList<>(), new NullToken()), generateEmptyGenericDeclList(), new NullToken());
new Block(new ArrayList<>(), new NullToken()), generateEmptyGenericDeclList(), new NullToken());
} }
public static GenericDeclarationList generateEmptyGenericDeclList(){ public static GenericDeclarationList generateEmptyGenericDeclList() {
return new GenericDeclarationList(new ArrayList<>(), new NullToken()); return new GenericDeclarationList(new ArrayList<>(), new NullToken());
} }

View File

@ -25,7 +25,7 @@ public class ASTToTypedTargetAST {
@Test @Test
public void emptyClass() { public void emptyClass() {
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken()); ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new ArrayList<>(), new NullToken());
ResultSet emptyResultSet = new ResultSet(new HashSet<>()); ResultSet emptyResultSet = new ResultSet(new HashSet<>());
TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass); TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
assert emptyTargetClass.getName().equals("EmptyClass"); assert emptyTargetClass.getName().equals("EmptyClass");