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.Void;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import javassist.compiler.SyntaxError;
public class SyntaxTreeGenerator {
private JavaClassRegistry reg;
@ -219,22 +220,15 @@ public class SyntaxTreeGenerator {
implementedInterfaces.addAll(convert(ctx.typeList(0), generics));
}
// Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0) {
switch (ctx.typeList().size()) {
case 1: {
permittedSubtypes.addAll(convert(ctx.typeList(0), generics));
break;
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");
}
case 2: {
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);
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);
}
private de.dhbwstuttgart.syntaxtree.Record convertRecord(RecordDeclarationContext recordDeclaration, int modifiers) {
@ -388,7 +382,16 @@ public class SyntaxTreeGenerator {
if (!Objects.isNull(ctx.EXTENDS())) {
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) {

View File

@ -2,7 +2,6 @@ package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.statement.Literal;
import de.dhbwstuttgart.syntaxtree.type.*;
import java.util.Iterator;
@ -274,4 +273,47 @@ public abstract class AbstractASTWalker implements ASTVisitor {
public void visit(SuperCall 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
*/
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
private Boolean methodAdded = false; //wird benoetigt bei in JavaTXCompiler.getConstraints()
public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private Boolean methodAdded = false; // wird benoetigt bei in JavaTXCompiler.getConstraints()
protected int modifiers;
protected JavaClassName name;
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 GenericDeclarationList genericClassParameters;
private RefType superClass;
protected boolean isInterface;
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
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, 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, List<RefType> permittedSubtypes, Token offset) {
super(offset);
if(isInterface && !Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE;
if (isInterface && !Modifier.isInterface(modifiers))
modifiers += Modifier.INTERFACE;
this.modifiers = modifiers;
this.name = name;
this.fields = fielddecl;
this.fieldInitializations= fieldInitializations;
this.fieldInitializations = fieldInitializations;
this.genericClassParameters = genericClassParameters;
this.superClass = superClass;
this.isInterface = isInterface;
this.implementedInterfaces = implementedInterfaces;
this.permittedSubtypes = permittedSubtypes;
this.methods = methods;
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());
this.modifiers = cl.modifiers;
this.name = cl.name;
this.fields = new ArrayList<>(cl.fields);
this.fieldInitializations= cl.fieldInitializations;
this.fieldInitializations = cl.fieldInitializations;
this.genericClassParameters = cl.genericClassParameters;
this.superClass = cl.superClass;
this.isInterface = cl.isInterface;
@ -71,49 +72,47 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
this.constructors = new ArrayList<>(cl.constructors);
}
//Gets if it is added
// Gets if it is added
public Boolean areMethodsAdded() {
return methodAdded;
}
//Sets that it is added
// Sets that it is added
public void setMethodsAdded() {
methodAdded = true;
}
// Gets class name
public JavaClassName getClassName(){
public JavaClassName getClassName() {
return this.name;
}
// Get modifiers
public int getModifiers(){
public int getModifiers() {
return this.modifiers;
}
public List<Field> getFieldDecl(){
public List<Field> getFieldDecl() {
return this.fields;
}
public Optional<Constructor> getfieldInitializations(){
public Optional<Constructor> getfieldInitializations() {
return this.fieldInitializations;
}
public List<Method> getMethods(){
public List<Method> getMethods() {
return this.methods;
}
/*
public RefType getType() {
return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset());
}
* public RefType getType() { return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); }
*/
//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){
//Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
// 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) {
// Hier wird immer ein generischer Typ generiert, also mit Type placeholdern
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar genericTypeVar : genericsOfClass){
//params.add(genericTypeVar.getTypePlaceholder());
for (GenericTypeVar genericTypeVar : genericsOfClass) {
// params.add(genericTypeVar.getTypePlaceholder());
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(name, params, offset);
@ -123,17 +122,17 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
*
* @return die aktuelle Klasse als RefType
*/
public RefType generateTypeOfThisClass(){
public RefType generateTypeOfThisClass() {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(GenericTypeVar genericTypeVar : this.getGenerics()){
//params.add(genericTypeVar.getTypePlaceholder());
for (GenericTypeVar genericTypeVar : this.getGenerics()) {
// params.add(genericTypeVar.getTypePlaceholder());
params.add(new GenericRefType(genericTypeVar.getName(), new NullToken()));
}
return new RefType(name, params, new NullToken());
}
/**
* Die Superklasse im Kontext dieser ClassOrInterface
* Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
* Die Superklasse im Kontext dieser ClassOrInterface Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind
*/
public RefType getSuperClass() {
return superClass;

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.syntaxtree;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@ -11,6 +12,6 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
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) {
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;
/**
* 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.
* 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.
*/
public class ASTFactory {
public static ClassOrInterface createClass(java.lang.Class jreClass){
public static ClassOrInterface createClass(java.lang.Class jreClass) {
// 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;
}
} catch (IOException e) {
@ -92,7 +90,7 @@ public class ASTFactory {
JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = 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)));
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> allInheritedMethods = new HashSet<>(allMethods);
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)));
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)));
methoden.add(createMethod(method, signature, jreClass, true));
}
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));
}
int modifier = jreClass.getModifiers();
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;
Type tempSuperClass = jreClass.getGenericSuperclass();
if(tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
if (tempSuperClass != null && tempSuperClass instanceof ParameterizedType)
parameterSuperClass = (ParameterizedType) tempSuperClass;
java.lang.Class superjreClass = jreClass.getSuperclass();
RefType superClass;
if(parameterSuperClass != null){
if (parameterSuperClass != null) {
superClass = (RefType) createType(parameterSuperClass);
}else if(superjreClass != null){
} else if (superjreClass != null) {
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);
}
List<RefType> implementedInterfaces = new ArrayList<>();
for(Type jreInterface : jreClass.getGenericInterfaces()){
for (Type jreInterface : jreClass.getGenericInterfaces()) {
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);
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) {
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();
//}
// }
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
String name = constructor.getName();
@ -155,10 +159,11 @@ public class ASTFactory {
Type[] jreGenericParams = constructor.getGenericParameterTypes();
List<FormalParameter> params = new ArrayList<>();
int i = 0;
for(Type jreParam : jreGenericParams){
if (jreParam == null) continue;
for (Type jreParam : jreGenericParams) {
if (jreParam == null)
continue;
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++;
}
ParameterList parameterList = new ParameterList(params, new NullToken());
@ -167,20 +172,20 @@ public class ASTFactory {
Token offset = new NullToken();
int modifier = constructor.getModifiers();
if(inClass.equals(java.lang.Object.class)){
if (inClass.equals(java.lang.Object.class)) {
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();
RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType;
if(jreMethod.getGenericReturnType()!=null){
if (jreMethod.getGenericReturnType() != null) {
jreRetType = jreMethod.getGenericReturnType();
}else{
} else {
jreRetType = jreMethod.getReturnType();
}
returnType = createType(jreRetType);
@ -188,10 +193,11 @@ public class ASTFactory {
Type[] jreGenericParams = jreMethod.getGenericParameterTypes();
List<FormalParameter> params = new ArrayList<>();
int i = 0;
for(Type jreParam : jreGenericParams){
if (jreParam == null) continue;
for (Type jreParam : jreGenericParams) {
if (jreParam == null)
continue;
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++;
}
ParameterList parameterList = new ParameterList(params, new NullToken());
@ -199,13 +205,13 @@ public class ASTFactory {
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
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) {
if (signature == null) {
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);
gtvs.add(gtv);
}
@ -217,7 +223,8 @@ public class ASTFactory {
}
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 signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
@ -226,7 +233,8 @@ public class ASTFactory {
final Stack<RefType> classTypes = new Stack<>();
// All hail the mighty visitor pattern
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {};
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {
};
char wildcard = '=';
@ -334,61 +342,61 @@ public class ASTFactory {
return new GenericDeclarationList(gtvs, new NullToken());
}
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type){
if(type == null || type.getTypeName().equals("void")){
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type) {
if (type == null || type.getTypeName().equals("void")) {
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());
}else if(type.getTypeName().equals("byte")){
} else if (type.getTypeName().equals("byte")) {
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());
}else if(type.getTypeName().equals("char")){
} else if (type.getTypeName().equals("char")) {
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());
}else if(type.getTypeName().equals("double")){
} else if (type.getTypeName().equals("double")) {
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());
}else{
if(type instanceof TypeVariable){
//GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
} else {
if (type instanceof TypeVariable) {
// GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()"
return new GenericRefType(type.getTypeName(), new NullToken());
}
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
if(type instanceof ParameterizedType){
for(Type t : ((ParameterizedType)type).getActualTypeArguments()){
if (type instanceof ParameterizedType) {
for (Type t : ((ParameterizedType) type).getActualTypeArguments()) {
params.add(createType(t));
}
}
String name = type.getTypeName();
if(name.contains("<")){ //Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A>
//Diese entfernen:
if (name.contains("<")) { // Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type<A>
// Diese entfernen:
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;
if(wildcardType.getLowerBounds().length > 0){
if (wildcardType.getLowerBounds().length > 0) {
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());
}else{//Es handelt sich um den '?'-Typ:
} else {// Es handelt sich um den '?'-Typ:
return new ExtendsWildcardType(createObjectType(), new NullToken());
}
}else{
} else {
RefType ret = new RefType(new JavaClassName(name), params, new NullToken());
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());
List<RefTypeOrTPHOrWildcardOrGeneric> genericBounds = new ArrayList<>();
java.lang.reflect.Type[] bounds = jreTypeVar.getBounds();
if(bounds.length > 0){
for(java.lang.reflect.Type bound : bounds){
if (bounds.length > 0) {
for (java.lang.reflect.Type bound : bounds) {
genericBounds.add(createType(bound));
}
}
@ -404,48 +412,26 @@ public class ASTFactory {
}
/*
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));
return ASTFactory.createConstructor(parent, new ParameterList(), block);
}
public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){
block.parserPostProcessing(superClass);
Method method = ASTFactory.createMethod("<init>", paralist, block, superClass);
method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
return new Constructor(method, 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));
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();
}
* 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));
*
* return ASTFactory.createConstructor(parent, new ParameterList(), block); }
*
* public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ block.parserPostProcessing(superClass);
*
* Method method = ASTFactory.createMethod("<init>", paralist, block, superClass); method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0));
*
* return new Constructor(method, 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));
*
* 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
public void generateBC() throws Exception {
/*SourceFile sf = generateAST();
PositionFinder.getPositionOfTPH(sf, null);
TPHExtractor tphExtractor = new TPHExtractor();
List<ResultSet> results = new ArrayList<ResultSet>();
GeneratedGenericsFinder generatedGenericsFinder = new GeneratedGenericsFinder(sf, results);*/
/*
* SourceFile sf = generateAST(); PositionFinder.getPositionOfTPH(sf, null); 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<Field> fields = new ArrayList<>();
ArrayList<Method> methods = new ArrayList<>();
fields.add(generateField("fld1"));
String[] paramNames = {"a"};
String[] paramNames = { "a" };
methods.add(generateMethod("testMethode", paramNames));
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 NullToken()));
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()));
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<>();
for(String str: paramNames) {
for (String str : paramNames) {
FormalParameter fp = new FormalParameter(str, TypePlaceholder.fresh(new NullToken()), new NullToken());
parameters.add(fp);
}
ParameterList parameterList = new ParameterList(parameters, new NullToken());
return new Method(Modifier.PUBLIC, methodName, TypePlaceholder.fresh(new NullToken()), parameterList,
new Block(new ArrayList<>(), new NullToken()), generateEmptyGenericDeclList(), new NullToken());
return new Method(Modifier.PUBLIC, methodName, TypePlaceholder.fresh(new NullToken()), parameterList, new Block(new ArrayList<>(), new NullToken()), generateEmptyGenericDeclList(), new NullToken());
}
public static GenericDeclarationList generateEmptyGenericDeclList(){
public static GenericDeclarationList generateEmptyGenericDeclList() {
return new GenericDeclarationList(new ArrayList<>(), new NullToken());
}

View File

@ -25,7 +25,7 @@ public class ASTToTypedTargetAST {
@Test
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<>());
TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
assert emptyTargetClass.getName().equals("EmptyClass");