JavaTXCompilerInJavaTX/javatx-src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.jav-back
2024-04-27 17:37:15 +02:00

210 lines
6.3 KiB
Plaintext

package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
//import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import java.lang.Boolean;
import java.lang.String;
import java.lang.Integer;
/**
* 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()
protected int modifiers;
protected JavaClassName name;
private final String fileName;
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<Method> staticInitializer;
private List<Method> methods = new ArrayList<>();
private GenericDeclarationList genericClassParameters;
private RefType superClass;
protected boolean isInterface;
protected boolean isFunctionalInterface;
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors;
public ClassOrInterface(modifiers, name, fielddecl, fieldInitializations, staticInitializer, methods, constructors, genericClassParameters, superClass, isInterface, isFunctionalInterface, implementedInterfaces, permittedSubtypes, offset, fileName) {
super(offset);
if (isInterface) {
modifiers = modifiers | Modifier.INTERFACE | Modifier.ABSTRACT;
}
this.modifiers = modifiers;
this.name = name;
this.fields = fielddecl;
this.fieldInitializations = fieldInitializations;
this.staticInitializer = staticInitializer;
this.genericClassParameters = genericClassParameters;
this.superClass = superClass;
this.isInterface = isInterface;
this.isFunctionalInterface= isFunctionalInterface;
this.implementedInterfaces = implementedInterfaces;
this.permittedSubtypes = permittedSubtypes;
this.methods = methods;
this.constructors = constructors;
this.fileName = fileName;
}
/*
* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte alle anderen Datenobjekte werden nur kopiert.
*/
public ClassOrInterface(cl) {
super(cl.getOffset());
this.modifiers = cl.modifiers;
this.name = cl.name;
this.fields = new ArrayList<>(cl.fields);
this.fieldInitializations = cl.fieldInitializations;
this.staticInitializer = cl.staticInitializer;
this.genericClassParameters = cl.genericClassParameters;
this.superClass = cl.superClass;
this.isInterface = cl.isInterface;
this.isFunctionalInterface= cl.isFunctionalInterface;
this.implementedInterfaces = cl.implementedInterfaces;
this.methods = new ArrayList<>(cl.methods);
this.constructors = new ArrayList<>(cl.constructors);
this.fileName = cl.fileName;
}
public getFileName() {
return fileName;
}
public getField(name) {
// TODO This should be a map
return fields.stream().filter(field -> field.getName().equals(name)).findFirst();
}
public getStaticInitializer() {
return staticInitializer;
}
public isInterface() {
return (Modifier.INTERFACE & this.getModifiers()) != 0;
}
public isFunctionalInterface() {
return this.isFunctionalInterface;
}
// Gets if it is added
public areMethodsAdded() {
return methodAdded;
}
// Sets that it is added
public setMethodsAdded() {
methodAdded = true;
}
// Gets class name
public getClassName() {
return this.name;
}
// Get modifiers
public getModifiers() {
return this.modifiers;
}
public getFieldDecl() {
return this.fields;
}
public getfieldInitializations() {
return this.fieldInitializations;
}
public getMethods() {
return this.methods;
}
/*
* 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 generateTypeOfClass(name, genericsOfClass, 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());
params.add(TypePlaceholder.fresh(offset));
}
return new RefType(name, params, offset);
}
/**
*
* @return die aktuelle Klasse als RefType
*/
public generateTypeOfThisClass() {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
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
*/
public getSuperClass() {
return superClass;
}
public getGenerics() {
return this.genericClassParameters;
}
@Override
public getReturnType() {
return null;
}
public getConstructors() {
return constructors;
}
@Override
public accept(visitor) {
visitor.visit(this);
}
public getSuperInterfaces() {
return implementedInterfaces;
}
public toString() {
return this.name.toString() + this.genericClassParameters.toString();
}
}