use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.
the class CheckerMain method getAllCheckerClassNames.
/**
* Returns the list of fully qualified names of the checkers found in checker.jar. This covers
* only checkers with the name ending in "Checker". Checkers with a name ending in "Subchecker"
* are not included in the returned list. Note however that it is possible for a checker with the
* name ending in "Checker" to be used as a subchecker.
*
* @return fully qualified names of the checkers found in checker.jar
*/
private List<@FullyQualifiedName String> getAllCheckerClassNames() {
ArrayList<@FullyQualifiedName String> checkerClassNames = new ArrayList<>();
try {
final JarInputStream checkerJarIs = new JarInputStream(new FileInputStream(checkerJar));
ZipEntry entry;
while ((entry = checkerJarIs.getNextEntry()) != null) {
final String name = entry.getName();
// Checkers ending in "Subchecker" are not included in this list used by CheckerMain.
if ((name.startsWith(CHECKER_BASE_DIR_NAME) || name.startsWith(COMMON_BASE_DIR_NAME)) && name.endsWith("Checker.class")) {
// Forward slash is used instead of File.separator because checker.jar uses / as
// the separator.
// string manipulation
@SuppressWarnings("signature") @FullyQualifiedName String fqName = String.join(".", name.substring(0, name.length() - ".class".length()).split("/"));
checkerClassNames.add(fqName);
}
}
checkerJarIs.close();
} catch (IOException e) {
// Issue a warning instead of aborting execution.
System.err.printf("Could not read %s. Shorthand processor names will not work.%n", checkerJar);
}
return checkerClassNames;
}
use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.
the class AnnotationFileParser method getImportableMembers.
/**
* Get all members of a Type that are importable in an annotation file. Currently these are values
* of enums, or compile time constants.
*
* @param typeElement the type whose members to return
* @return a list of fully-qualified member names
*/
private static List<@FullyQualifiedName String> getImportableMembers(TypeElement typeElement) {
List<VariableElement> memberElements = ElementFilter.fieldsIn(typeElement.getEnclosedElements());
List<@FullyQualifiedName String> result = new ArrayList<>();
for (VariableElement varElement : memberElements) {
if (varElement.getConstantValue() != null || varElement.getKind() == ElementKind.ENUM_CONSTANT) {
// string concatenation
@SuppressWarnings("signature") @FullyQualifiedName String fqName = typeElement.getQualifiedName().toString() + "." + varElement.getSimpleName().toString();
result.add(fqName);
}
}
return result;
}
use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.
the class TypeAnnotationMover method getAnnotationDeclaration.
/**
* Returns the TypeElement for an annotation, or null if it cannot be found.
*
* @param annotation a JavaParser annotation
* @return the TypeElement for {@code annotation}, or null if it cannot be found
*/
@Nullable
private TypeElement getAnnotationDeclaration(AnnotationExpr annotation) {
// https://tinyurl.com/cfissue/3094
@SuppressWarnings("signature") @FullyQualifiedName String annoNameFq = annotation.getNameAsString();
TypeElement annoTypeElt = allAnnotations.get(annoNameFq);
if (annoTypeElt == null) {
annoTypeElt = elements.getTypeElement(annoNameFq);
if (annoTypeElt == null) {
// Not a supported annotation.
return null;
}
AnnotationFileParser.putAllNew(allAnnotations, AnnotationFileParser.createNameToAnnotationMap(Collections.singletonList(annoTypeElt)));
}
return annoTypeElt;
}
use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.
the class AnnotationFileParser method processTypeDecl.
/**
* Process a type declaration: copy its annotations to {@code #annotationFileAnnos}.
*
* <p>This method stores the declaration's type parameters in {@link #typeParameters}. When
* processing an ajava file, where traversal is handled externaly by a {@link
* org.checkerframework.framework.ajava.JointJavacJavaParserVisitor}, these type variables must be
* removed after processing the type's members. Otherwise, this method removes them.
*
* @param typeDecl the type declaration to process
* @param outertypeName the name of the containing class, when processing a nested class;
* otherwise null
* @param classTree the tree corresponding to typeDecl if processing an ajava file, null otherwise
* @return a list of types variables for {@code typeDecl}. Only non-null if processing an ajava
* file, in which case the contents should be removed from {@link #typeParameters} after
* processing the type declaration's members
*/
private List<AnnotatedTypeVariable> processTypeDecl(TypeDeclaration<?> typeDecl, String outertypeName, @Nullable ClassTree classTree) {
assert typeBeingParsed != null;
if (skipNode(typeDecl)) {
return null;
}
String innerName;
@FullyQualifiedName String fqTypeName;
TypeElement typeElt;
if (classTree != null) {
typeElt = TreeUtils.elementFromDeclaration(classTree);
innerName = typeElt.getQualifiedName().toString();
typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
fqTypeName = typeBeingParsed.toString();
} else {
String packagePrefix = outertypeName == null ? "" : outertypeName + ".";
innerName = packagePrefix + typeDecl.getNameAsString();
typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
fqTypeName = typeBeingParsed.toString();
typeElt = elements.getTypeElement(fqTypeName);
}
if (!isAnnotatedForThisChecker(typeDecl.getAnnotations())) {
return null;
}
if (typeElt == null) {
if (debugAnnotationFileParser || (!warnIfNotFoundIgnoresClasses && !hasNoAnnotationFileParserWarning(typeDecl.getAnnotations()) && !hasNoAnnotationFileParserWarning(packageAnnos))) {
if (elements.getAllTypeElements(fqTypeName).isEmpty()) {
stubWarnNotFound(typeDecl, "Type not found: " + fqTypeName);
} else {
stubWarnNotFound(typeDecl, "Type not found uniquely: " + fqTypeName + " : " + elements.getAllTypeElements(fqTypeName));
}
}
return null;
}
List<AnnotatedTypeVariable> typeDeclTypeParameters = null;
if (typeElt.getKind() == ElementKind.ENUM) {
if (!(typeDecl instanceof EnumDeclaration)) {
warn(typeDecl, innerName + " is an enum, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
typeDeclTypeParameters = processEnum((EnumDeclaration) typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
} else if (typeElt.getKind() == ElementKind.ANNOTATION_TYPE) {
if (!(typeDecl instanceof AnnotationDeclaration)) {
warn(typeDecl, innerName + " is an annotation, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
stubWarnNotFound(typeDecl, "Skipping annotation type: " + fqTypeName);
} else if (typeDecl instanceof ClassOrInterfaceDeclaration) {
if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
warn(typeDecl, innerName + " is a class or interface, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
typeDeclTypeParameters = processType(typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
} else if (typeDecl instanceof RecordDeclaration) {
typeDeclTypeParameters = processType(typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
}
// of this method.
if (fileType == AnnotationFileType.AJAVA) {
return typeDeclTypeParameters;
}
if (typeDecl instanceof RecordDeclaration) {
NodeList<Parameter> recordMembers = ((RecordDeclaration) typeDecl).getParameters();
LinkedHashMap<String, RecordComponentStub> byName = new LinkedHashMap<>();
for (Parameter recordMember : recordMembers) {
RecordComponentStub stub = processRecordField(recordMember, findFieldElement(typeElt, recordMember.getNameAsString(), recordMember));
byName.put(recordMember.getNameAsString(), stub);
}
annotationFileAnnos.records.put(typeDecl.getFullyQualifiedName().get(), new RecordStub(byName));
}
Pair<Map<Element, BodyDeclaration<?>>, Map<Element, List<BodyDeclaration<?>>>> members = getMembers(typeDecl, typeElt, typeDecl);
for (Map.Entry<Element, BodyDeclaration<?>> entry : members.first.entrySet()) {
final Element elt = entry.getKey();
final BodyDeclaration<?> decl = entry.getValue();
switch(elt.getKind()) {
case FIELD:
processField((FieldDeclaration) decl, (VariableElement) elt);
break;
case ENUM_CONSTANT:
// the TRACKER enum constant annotated with DefaultType:
if (decl instanceof FieldDeclaration) {
processField((FieldDeclaration) decl, (VariableElement) elt);
} else if (decl instanceof EnumConstantDeclaration) {
processEnumConstant((EnumConstantDeclaration) decl, (VariableElement) elt);
} else {
throw new BugInCF("Unexpected decl type " + decl.getClass() + " for ENUM_CONSTANT kind, original: " + decl);
}
break;
case CONSTRUCTOR:
case METHOD:
processCallableDeclaration((CallableDeclaration<?>) decl, (ExecutableElement) elt);
break;
case CLASS:
case INTERFACE:
// Not processing an ajava file, so ignore the return value.
processTypeDecl((ClassOrInterfaceDeclaration) decl, innerName, null);
break;
case ENUM:
// Not processing an ajava file, so ignore the return value.
processTypeDecl((EnumDeclaration) decl, innerName, null);
break;
default:
/* do nothing */
stubWarnNotFound(decl, "AnnotationFileParser ignoring: " + elt);
break;
}
}
for (Map.Entry<Element, List<BodyDeclaration<?>>> entry : members.second.entrySet()) {
ExecutableElement fakeOverridden = (ExecutableElement) entry.getKey();
List<BodyDeclaration<?>> fakeOverrideDecls = entry.getValue();
for (BodyDeclaration<?> bodyDecl : fakeOverrideDecls) {
processFakeOverride(fakeOverridden, (CallableDeclaration<?>) bodyDecl, typeElt);
}
}
if (typeDeclTypeParameters != null) {
typeParameters.removeAll(typeDeclTypeParameters);
}
return null;
}
use of org.checkerframework.checker.signature.qual.FullyQualifiedName 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;
}
Aggregations