package de.dhbwstuttgart.target.generate; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.target.tree.type.TargetType; import java.util.*; public class GenericsResult { private final GenerateGenerics generics; GenericsResult(GenerateGenerics generics) { this.generics = generics; } public GenericsResultSet get(ClassOrInterface clazz) { var generics = this.generics.computedGenericsOfClasses.get(clazz); return new GenericsResultSet(generics, this.generics.equality); } // TODO Compute generics if not present? public GenericsResultSet get(Method method) { var generics = this.generics.computedGenericsOfMethods.get(method); return new GenericsResultSet(generics, this.generics.equality); } public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) { return getBounds(type, clazz, null); } public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz, Method method) { var resolvedType = resolve(type); type = resolvedType; if (type instanceof TypePlaceholder) { var methodGenerics = get(method); var classGenerics = get(clazz); List result = new ArrayList<>(); Optional bound = Optional.empty(); do { bound = Optional.empty(); for (var pair : methodGenerics) { if (pair.left.resolve().equals(type)) { type = pair.resolveRight(); bound = Optional.of(new Bound(true, type)); break; } } if (bound.isEmpty()) { for (var pair : classGenerics) { if (pair.left.resolve().equals(type)) { type = pair.resolveRight(); bound = Optional.of(new Bound(false, type)); break; } } } bound.ifPresent(result::add); } while (bound.isPresent()); return new BoundsList(resolvedType, result); } return new BoundsList(resolvedType, List.of()); } public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { if (type instanceof TypePlaceholder tph) return this.generics.getType(tph); return type; } public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) { return this.generics.getTargetType(type); } }