framework.src.org.checkerframework.framework.type.AnnotatedTypeReplacer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java’s type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.framework.type;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* Duplicates annotated types and replaces components according to a replacement map.
*/
public class AnnotatedTypeReplacer {
/**
* Return a copy of type after making the specified replacements.
* @param type the type that will be copied with replaced components
* @param replacementMap a mapping of {@literal referenceToReplace -> referenceOfReplacement}
* @return a duplicate of type in which every reference that was a key in replacementMap
* has been replaced by its corresponding value
*/
public static AnnotatedTypeMirror replace(
AnnotatedTypeMirror type,
Map replacementMap) {
return new Visitor(replacementMap).visit(type);
}
/**
* AnnotatedTypeCopier maintains a mapping of {@literal typeVisited -> copyOfTypeVisited}
* When a reference, typeVisited, is encountered again, it will use the recorded reference,
* copyOfTypeVisited, instead of generating a new copy of typeVisited. Visitor pre-populates
* this mapping so that references are replaced not by their copies but by those in the
* replacementMap provided in the constructor.
*
* All types NOT in the replacement map are duplicated as per AnnotatedTypeCopier.visit
*/
protected static class Visitor extends AnnotatedTypeCopier {
private final IdentityHashMap originalMappings;
public Visitor(final Map mappings) {
originalMappings = new IdentityHashMap<>(mappings);
}
@Override
public AnnotatedTypeMirror visit(AnnotatedTypeMirror type) {
return type.accept(this, new IdentityHashMap<>(originalMappings));
}
public AnnotatedTypeMirror visitTypeVariable(AnnotatedTypeVariable original, IdentityHashMap originalToCopy) {
// AnnotatedTypeCopier will visit the type parameters of a method and copy them
// Without this flag, any mappings in originalToCopy would replace the type parameters.
// However, we do not replace the type parameters in an AnnotatedExecutableType. Also,
// AnnotatedExecutableType.typeVarTypes is of type List so if
// the mapping contained a type parameter -> (Non-type variable AnnotatedTypeMirror) then
// a runtime exception would occur.
if (visitingExecutableTypeParam) {
visitingExecutableTypeParam = false;
final AnnotatedTypeVariable copy = (AnnotatedTypeVariable) AnnotatedTypeMirror.createType(
original.getUnderlyingType(), original.atypeFactory, original.isDeclaration());
maybeCopyPrimaryAnnotations(original, copy);
originalToCopy.put(original, copy);
if (original.getUpperBoundField() != null) {
copy.setUpperBoundField(visit(original.getUpperBoundField(), originalToCopy));
}
if (original.getLowerBoundField() != null) {
copy.setLowerBoundField(visit(original.getLowerBoundField(), originalToCopy));
}
return copy;
}
return super.visitTypeVariable(original, originalToCopy);
}
}
}