All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.uka.ilkd.key.util.removegenerics.GenericResolutionTransformation Maven / Gradle / Ivy

The newest version!
/* This file is part of KeY - https://key-project.org
 * KeY is licensed under the GNU General Public License Version 2
 * SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.util.removegenerics;

import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import recoder.CrossReferenceServiceConfiguration;
import recoder.NamedModelElement;
import recoder.abstraction.ArrayType;
import recoder.abstraction.ParameterizedType;
import recoder.abstraction.Type;
import recoder.abstraction.TypeParameter;
import recoder.java.NamedProgramElement;
import recoder.java.ProgramElement;
import recoder.java.declaration.MethodDeclaration;
import recoder.java.declaration.TypeParameterDeclaration;
import recoder.kit.TwoPassTransformation;

/**
 * This is the base class to all transformations used in the generics removal process.
 * 

* It allows 2 things: 1) calculating the target type of a type (which is the type when type * variables are no longer) and 2) to print out debug info. *

* String creation is a little tedious in recoder so {@link #toString(Object)} does a lot of it. * * @author MU */ public class GenericResolutionTransformation extends TwoPassTransformation { // allow debug output public static boolean DEBUG_OUTPUT = Boolean.getBoolean("resolvegen.verbose"); private static final Logger LOGGER = LoggerFactory.getLogger(GenericResolutionTransformation.class); public GenericResolutionTransformation() { super(); } public GenericResolutionTransformation(CrossReferenceServiceConfiguration sc) { super(sc); } /** * get the type of the reference that it will have in a generic-free environment. If the * expression once had type V for some (unbound) type variable it will then have * java.lang.Object etc. * * @param t the type to be resolved * @return the coresponding type in the generic-free environment */ protected Type targetType(Type t) { int dimension = 0; boolean changed = false; Type origType = t; while (t instanceof ArrayType) { t = ((ArrayType) t).getBaseType(); dimension++; } if (t instanceof ParameterizedType) { t = ((ParameterizedType) t).getGenericType(); changed = true; } /* * it might be necessary to do the following block more than once in a situation like: * G<A, B extends A> where B would be replaced by A, which needs to be resolved to * Object. */ while (t instanceof TypeParameter typeParameter) { changed = true; int boundNo = typeParameter.getBoundCount(); if (boundNo == 0) { t = getNameInfo().getJavaLangObject(); if (t == null) { throw new IllegalStateException("java.lang.Object not known"); } } else { String bound = typeParameter.getBoundName(0); if (typeParameter instanceof TypeParameterDeclaration tdecl) { // TP - Declaration needs to know context (bound may rely on // imports) t = getSourceInfo().getType(bound, tdecl); } else { // TP - Info from Class file is always complete (I hope) t = getNameInfo().getType(bound); } } } if (changed) { if (dimension > 0) { t = getNameInfo().createArrayType(t, dimension); } return t; } else { return origType; } } /** * if the global debug flag {@link #DEBUG_OUTPUT} is set to true print out a message. *

* First the message-head is printed followed by a ':', followed by a ;-separated list of the * arguments. Each argument is converted to a string using the {@link #toString(Object)}. * * @param msg the message's head * @param arg 0 or more objects that will be expanded to a ;-separated list after the message */ public static void debugOut(String msg, Object... arg) { if (DEBUG_OUTPUT) { var args = new StringBuilder(); if (arg.length > 0) { args.append(":"); for (int i = 1; i < arg.length; i++) { args.append("; ").append(toString(arg[i])); } } LOGGER.debug(msg + args); } } /** * convert an object to a String. *

* For some classes {@link Object#toString()} is lame, so that the following classes are caught * here: *

    *
  • {@link MethodDeclaration} *
  • {@link NamedModelElement} *
  • {@link Collection} - which handle each element with toString
  • Anything else will be * transoformed using {@link Object#toString()}. * * @param object the object to be transformed, may be null * @return a String representing the object. */ public static String toString(Object object) { if (object instanceof MethodDeclaration md) { return md.getFullName() + toString(md.getSignature()); } if (object instanceof NamedModelElement ne) { String name = ne.getName(); if (object instanceof NamedProgramElement) { ProgramElement parent = ((NamedProgramElement) ne).getASTParent(); if (parent instanceof NamedModelElement p) { return p.getName() + "::" + name; } } else { return name; } } if (object instanceof Collection coll) { StringBuilder ret = new StringBuilder("[ "); for (Object o : coll) { ret.append(toString(o)).append(" "); } return ret + "]"; } if (object == null) { return "(null)"; } return object.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy