use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class AnnotationFileParser method getImportedAnnotations.
/**
* Returns all annotations imported by the annotation file, as a value for {@link
* #allAnnotations}. Note that this also modifies {@link #importedConstants} and {@link
* #importedTypes}.
*
* <p>This method misses annotations that are not imported. The {@link #getAnnotation} method
* compensates for this deficiency by adding any fully-qualified annotation that it encounters.
*
* @return a map from names to TypeElement, for all annotations imported by the annotation file.
* Two entries for each annotation: one for the simple name and another for the
* fully-qualified name, with the same value.
* @see #allAnnotations
*/
private Map<String, TypeElement> getImportedAnnotations() {
Map<String, TypeElement> result = new HashMap<>();
// TODO: The size can be greater than 1, but this ignores all but the first element.
assert !stubUnit.getCompilationUnits().isEmpty();
CompilationUnit cu = stubUnit.getCompilationUnits().get(0);
if (cu.getImports() == null) {
return result;
}
for (ImportDeclaration importDecl : cu.getImports()) {
try {
if (importDecl.isAsterisk()) {
@// https://tinyurl.com/cfissue/3094:
SuppressWarnings(// https://tinyurl.com/cfissue/3094:
"signature") @DotSeparatedIdentifiers String imported = importDecl.getName().toString();
if (importDecl.isStatic()) {
// Wildcard import of members of a type (class or interface)
TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
if (element != null) {
// Find nested annotations
// Find compile time constant fields, or values of an enum
putAllNew(result, annosInType(element));
importedConstants.addAll(getImportableMembers(element));
addEnclosingTypesToImportedTypes(element);
}
} else {
// Wildcard import of members of a package
PackageElement element = findPackage(imported, importDecl);
if (element != null) {
putAllNew(result, annosInPackage(element));
addEnclosingTypesToImportedTypes(element);
}
}
} else {
// A single (non-wildcard) import.
@// importDecl is non-wildcard, so its name is
SuppressWarnings(// importDecl is non-wildcard, so its name is
"signature") @FullyQualifiedName String imported = importDecl.getNameAsString();
final TypeElement importType = elements.getTypeElement(imported);
if (importType == null && !importDecl.isStatic()) {
// Class or nested class (according to JSL), but we can't resolve
stubWarnNotFound(importDecl, "Imported type not found: " + imported);
} else if (importType == null) {
// static import of field or method.
Pair<@FullyQualifiedName String, String> typeParts = AnnotationFileUtil.partitionQualifiedName(imported);
String type = typeParts.first;
String fieldName = typeParts.second;
TypeElement enclType = getTypeElement(type, String.format("Enclosing type of static field %s not found", fieldName), importDecl);
if (enclType != null) {
// want a warning, imported might be a method.
for (VariableElement field : ElementUtils.getAllFieldsIn(enclType, elements)) {
// field.getSimpleName() is a CharSequence, not a String
if (fieldName.equals(field.getSimpleName().toString())) {
importedConstants.add(imported);
}
}
}
} else if (importType.getKind() == ElementKind.ANNOTATION_TYPE) {
// Single annotation or nested annotation
TypeElement annoElt = elements.getTypeElement(imported);
if (annoElt != null) {
putIfAbsent(result, annoElt.getSimpleName().toString(), annoElt);
importedTypes.put(annoElt.getSimpleName().toString(), annoElt);
} else {
stubWarnNotFound(importDecl, "Could not load import: " + imported);
}
} else {
// Class or nested class
// TODO: Is this needed?
importedConstants.add(imported);
TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
importedTypes.put(element.getSimpleName().toString(), element);
}
}
} catch (AssertionError error) {
stubWarnNotFound(importDecl, error.toString());
}
}
return result;
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class BaseTypeValidator method extractParameterizedTypeTree.
/**
* If {@code tree} has a {@link ParameterizedTypeTree}, then the tree and its type is returned.
* Otherwise null and {@code type} are returned.
*
* @param tree tree to search
* @param type type to return if no {@code ParameterizedTypeTree} is found
* @return if {@code tree} has a {@code ParameterizedTypeTree}, then returns the tree and its
* type. Otherwise, returns null and {@code type}.
*/
private Pair<@Nullable ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree(Tree tree, AnnotatedDeclaredType type) {
ParameterizedTypeTree typeargtree = null;
switch(tree.getKind()) {
case VARIABLE:
Tree lt = ((VariableTree) tree).getType();
if (lt instanceof ParameterizedTypeTree) {
typeargtree = (ParameterizedTypeTree) lt;
} else {
// System.out.println("Found a: " + lt);
}
break;
case PARAMETERIZED_TYPE:
typeargtree = (ParameterizedTypeTree) tree;
break;
case NEW_CLASS:
NewClassTree nct = (NewClassTree) tree;
ExpressionTree nctid = nct.getIdentifier();
if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
typeargtree = (ParameterizedTypeTree) nctid;
/*
* This is quite tricky... for anonymous class instantiations,
* the type at this point has no type arguments. By doing the
* following, we get the type arguments again.
*/
type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree);
}
break;
case ANNOTATED_TYPE:
AnnotatedTypeTree tr = (AnnotatedTypeTree) tree;
ExpressionTree undtr = tr.getUnderlyingType();
if (undtr instanceof ParameterizedTypeTree) {
typeargtree = (ParameterizedTypeTree) undtr;
} else if (undtr instanceof IdentifierTree) {
// @Something D -> Nothing to do
} else {
// TODO: add more test cases to ensure that nested types are
// handled correctly,
// e.g. @Nullable() List<@Nullable Object>[][]
Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(undtr, type);
typeargtree = p.first;
type = p.second;
}
break;
case IDENTIFIER:
case ARRAY_TYPE:
case NEW_ARRAY:
case MEMBER_SELECT:
case UNBOUNDED_WILDCARD:
case EXTENDS_WILDCARD:
case SUPER_WILDCARD:
case TYPE_PARAMETER:
// Nothing to do.
break;
case METHOD:
// If a MethodTree is passed, it's just the return type that is validated.
// See BaseTypeVisitor#validateTypeOf.
MethodTree methodTree = (MethodTree) tree;
if (methodTree.getReturnType() instanceof ParameterizedTypeTree) {
typeargtree = (ParameterizedTypeTree) methodTree.getReturnType();
}
break;
default:
// No need to do anything further.
break;
}
return Pair.of(typeargtree, type);
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class MustCallConsistencyAnalyzer method getSuccessorsExceptIgnoredExceptions.
/**
* Get all successor blocks for some block, except for those corresponding to ignored exception
* types. See {@link #ignoredExceptionTypes}. Each exceptional successor is paired with the type
* of exception that leads to it, for use in error messages.
*
* @param block input block
* @return set of pairs (b, t), where b is a successor block, and t is the type of exception for
* the CFG edge from block to b, or {@code null} if b is a non-exceptional successor
*/
private Set<Pair<Block, @Nullable TypeMirror>> getSuccessorsExceptIgnoredExceptions(Block block) {
if (block.getType() == Block.BlockType.EXCEPTION_BLOCK) {
ExceptionBlock excBlock = (ExceptionBlock) block;
Set<Pair<Block, @Nullable TypeMirror>> result = new LinkedHashSet<>();
// regular successor
Block regularSucc = excBlock.getSuccessor();
if (regularSucc != null) {
result.add(Pair.of(regularSucc, null));
}
// non-ignored exception successors
Map<TypeMirror, Set<Block>> exceptionalSuccessors = excBlock.getExceptionalSuccessors();
for (Map.Entry<TypeMirror, Set<Block>> entry : exceptionalSuccessors.entrySet()) {
TypeMirror exceptionType = entry.getKey();
if (!isIgnoredExceptionType(((Type) exceptionType).tsym.getQualifiedName())) {
for (Block exSucc : entry.getValue()) {
result.add(Pair.of(exSucc, exceptionType));
}
}
}
return result;
} else {
Set<Pair<Block, @Nullable TypeMirror>> result = new LinkedHashSet<>();
for (Block b : block.getSuccessors()) {
result.add(Pair.of(b, null));
}
return result;
}
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class TreeParser method parseExpression.
/**
* Parse an expression.
*
* @param tokenizer the tokenizer
* @param token the first token
* @return a pair of a parsed expression and the next token
*/
private Pair<JCExpression, String> parseExpression(StringTokenizer tokenizer, String token) {
JCExpression tree = fromToken(token);
while (tokenizer.hasMoreTokens()) {
String delim = nextToken(tokenizer);
token = delim;
if (".".equals(delim)) {
token = nextToken(tokenizer);
tree = maker.Select(tree, names.fromString(token));
} else if ("(".equals(delim)) {
token = nextToken(tokenizer);
ListBuffer<JCExpression> args = new ListBuffer<>();
while (!")".equals(token)) {
Pair<JCExpression, String> p = parseExpression(tokenizer, token);
JCExpression arg = p.first;
token = p.second;
args.append(arg);
if (",".equals(token)) {
token = nextToken(tokenizer);
}
}
// For now, handle empty args only
assert ")".equals(token) : "Unexpected token: " + token;
tree = maker.Apply(List.nil(), tree, args.toList());
} else if ("[".equals(token)) {
token = nextToken(tokenizer);
Pair<JCExpression, String> p = parseExpression(tokenizer, token);
JCExpression index = p.first;
token = p.second;
assert "]".equals(token) : "Unexpected token: " + token;
tree = maker.Indexed(tree, index);
} else {
return Pair.of(tree, token);
}
assert tokenizer != null : "@AssumeAssertion(nullness): side effects";
}
return Pair.of(tree, token);
}
use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.
the class AnnotatedTypes method fixUpRawTypes.
/**
* Some times we create type arguments for types that were raw. When we do an asSuper we lose
* these arguments. If in the converted type (i.e. the subtype as super) is missing type arguments
* AND those type arguments should come from the original subtype's type arguments then we copy
* the original type arguments to the converted type. e.g. We have a type W, that "wasRaw" {@code
* ArrayList<? extends Object>} When W is converted to type A, List, using asSuper it no longer
* has its type argument. But since the type argument to List should be the same as that to
* ArrayList we copy over the type argument of W to A. A becomes {@code List<? extends Object>}
*
* @param originalSubtype the subtype before being converted by asSuper
* @param asSuperType he subtype after being converted by asSuper
* @param supertype the supertype for which asSuperType should have the same underlying type
* @param types the types utility
*/
private static void fixUpRawTypes(final AnnotatedTypeMirror originalSubtype, final AnnotatedTypeMirror asSuperType, final AnnotatedTypeMirror supertype, final Types types) {
if (asSuperType == null || asSuperType.getKind() != TypeKind.DECLARED || originalSubtype.getKind() != TypeKind.DECLARED) {
return;
}
final AnnotatedDeclaredType declaredAsSuper = (AnnotatedDeclaredType) asSuperType;
final AnnotatedDeclaredType declaredSubtype = (AnnotatedDeclaredType) originalSubtype;
if (!declaredAsSuper.isUnderlyingTypeRaw() || !declaredAsSuper.getTypeArguments().isEmpty() || declaredSubtype.getTypeArguments().isEmpty()) {
return;
}
Set<Pair<Integer, Integer>> typeArgMap = TypeArgumentMapper.mapTypeArgumentIndices((TypeElement) declaredSubtype.getUnderlyingType().asElement(), (TypeElement) declaredAsSuper.getUnderlyingType().asElement(), types);
if (typeArgMap.size() != declaredSubtype.getTypeArguments().size()) {
return;
}
List<Pair<Integer, Integer>> orderedByDestination = new ArrayList<>(typeArgMap);
orderedByDestination.sort(Comparator.comparingInt(o -> o.second));
if (typeArgMap.size() == ((AnnotatedDeclaredType) supertype).getTypeArguments().size()) {
List<? extends AnnotatedTypeMirror> subTypeArgs = declaredSubtype.getTypeArguments();
List<AnnotatedTypeMirror> newTypeArgs = CollectionsPlume.mapList(mapping -> subTypeArgs.get(mapping.first).deepCopy(), orderedByDestination);
declaredAsSuper.setTypeArguments(newTypeArgs);
} else {
declaredAsSuper.setTypeArguments(Collections.emptyList());
}
}
Aggregations