use of org.checkerframework.javacutil.UserError in project checker-framework by typetools.
the class SourceChecker method typeProcess.
/**
* Type-check the code using this checker's visitor.
*
* @see Processor#process(Set, RoundEnvironment)
*/
@Override
public void typeProcess(TypeElement e, TreePath p) {
if (javacErrored) {
reportJavacError(p);
return;
}
// Cannot use BugInCF here because it is outside of the try/catch for BugInCF.
if (e == null) {
messager.printMessage(Kind.ERROR, "Refusing to process empty TypeElement");
return;
}
if (p == null) {
messager.printMessage(Kind.ERROR, "Refusing to process empty TreePath in TypeElement: " + e);
return;
}
if (!warnedAboutGarbageCollection) {
String gcUsageMessage = SystemPlume.gcUsageMessage(.25, 60);
if (gcUsageMessage != null) {
messager.printMessage(Kind.WARNING, gcUsageMessage);
warnedAboutGarbageCollection = true;
}
}
Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
Source source = Source.instance(context);
// Also the enum constant Source.JDK1_8 was renamed at some point...
if (!warnedAboutSourceLevel && source.compareTo(Source.lookup("8")) < 0) {
messager.printMessage(Kind.WARNING, "-source " + source.name + " does not support type annotations");
warnedAboutSourceLevel = true;
}
Log log = Log.instance(context);
if (log.nerrors > this.errsOnLastExit) {
this.errsOnLastExit = log.nerrors;
javacErrored = true;
reportJavacError(p);
return;
}
if (visitor == null) {
// there. Don't also cause a NPE here.
return;
}
if (p.getCompilationUnit() != currentRoot) {
setRoot(p.getCompilationUnit());
if (hasOption("filenames")) {
// TODO: Have a command-line option to turn the timestamps on/off too, because
// they are nondeterministic across runs.
// Add timestamp to indicate how long operations are taking.
// Duplicate messages are suppressed, so this might not appear in front of every "
// is type-checking " message (when a file takes less than a second to type-check).
message(Kind.NOTE, Instant.now().toString());
message(Kind.NOTE, "%s is type-checking %s", (Object) this.getClass().getSimpleName(), currentRoot.getSourceFile().getName());
}
}
// Visit the attributed tree.
try {
visitor.visit(p);
warnUnneededSuppressions();
} catch (UserError ce) {
logUserError(ce);
} catch (TypeSystemError ce) {
logTypeSystemError(ce);
} catch (BugInCF ce) {
logBugInCF(ce);
} catch (Throwable t) {
logBugInCF(wrapThrowableAsBugInCF("SourceChecker.typeProcess", t, p));
} finally {
// Also add possibly deferred diagnostics, which will get published back in
// AbstractTypeProcessor.
this.errsOnLastExit = log.nerrors;
}
}
use of org.checkerframework.javacutil.UserError in project checker-framework by typetools.
the class AnnotationClassLoader method loadAnnotationClass.
/**
* Loads the class indicated by the name, and checks to see if it is an annotation that is
* supported by a checker.
*
* @param className the name of the class, in binary name format
* @param issueError set to true to issue a warning when a loaded annotation is not a type
* annotation. It is useful to set this to true if a given annotation must be a well-defined
* type annotation (eg for annotation class names given as command line arguments). It should
* be set to false if the annotation is a meta-annotation or non-type annotation.
* @return the loaded annotation class if it has a {@code @Target} meta-annotation with the
* required ElementType values, and is a supported annotation by a checker. If the annotation
* is not supported by a checker, null is returned.
*/
@Nullable
protected final Class<? extends Annotation> loadAnnotationClass(@BinaryName final String className, boolean issueError) {
// load the class
Class<?> cls = null;
try {
if (classLoader != null) {
cls = Class.forName(className, true, classLoader);
} else {
cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
throw new UserError(checker.getClass().getSimpleName() + ": could not load class for annotation: " + className + ". Ensure that it is a type annotation" + " and your classpath is correct.");
}
// return null
if (!cls.isAnnotation()) {
if (issueError) {
throw new UserError(checker.getClass().getSimpleName() + ": the loaded class: " + cls.getCanonicalName() + " is not a type annotation.");
}
return null;
}
Class<? extends Annotation> annoClass = cls.asSubclass(Annotation.class);
// ElementType values
if (hasWellDefinedTargetMetaAnnotation(annoClass)) {
// If so, return the loaded annotation if it is supported by a checker
return isSupportedAnnotationClass(annoClass) ? annoClass : null;
} else if (issueError) {
// user expects these external annotations to be loaded.
throw new UserError(checker.getClass().getSimpleName() + ": the loaded annotation: " + annoClass.getCanonicalName() + " is not a type annotation." + " Check its @Target meta-annotation.");
} else {
// in such directories.
return null;
}
}
use of org.checkerframework.javacutil.UserError in project checker-framework by typetools.
the class InitializedFieldsAnnotatedTypeFactory method createTypeFactoryForProcessor.
/**
* Creates a new type factory for the given annotation processor, if it is a type-checker. This
* does NOT return an existing type factory.
*
* @param processorName the fully-qualified class name of an annotation processor
* @return the type factory for the given annotation processor, or null if it's not a checker
*/
GenericAnnotatedTypeFactory<?, ?, ?, ?> createTypeFactoryForProcessor(@BinaryName String processorName) {
try {
Class<?> checkerClass = Class.forName(processorName);
if (!BaseTypeChecker.class.isAssignableFrom(checkerClass)) {
return null;
}
@SuppressWarnings("unchecked") BaseTypeChecker c = ((Class<? extends BaseTypeChecker>) checkerClass).getDeclaredConstructor().newInstance();
c.init(processingEnv);
c.initChecker();
BaseTypeVisitor<?> v = c.createSourceVisitorPublic();
GenericAnnotatedTypeFactory<?, ?, ?, ?> atf = v.createTypeFactoryPublic();
if (atf == null) {
throw new UserError("Cannot find %s; check the classpath or processorpath", processorName);
}
return atf;
} catch (ClassNotFoundException | InstantiationException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
throw new UserError("Problem instantiating " + processorName, e);
}
}
use of org.checkerframework.javacutil.UserError in project checker-framework by typetools.
the class SubtypingAnnotatedTypeFactory method createSupportedTypeQualifiers.
@Override
protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
// Subtyping Checker doesn't have a qual directory, so we instantiate the loader here to
// load externally declared annotations
loader = createAnnotationClassLoader();
String qualNames = checker.getOption("quals");
String qualDirectories = checker.getOption("qualDirs");
if (qualNames == null && qualDirectories == null) {
throw new UserError("SubtypingChecker: missing required option. Use -Aquals or -AqualDirs.");
}
Set<Class<? extends Annotation>> qualSet = new LinkedHashSet<>();
// load individually named qualifiers
if (qualNames != null) {
for (String qualName : qualNames.split(",")) {
if (!Signatures.isBinaryName(qualName)) {
throw new UserError("Malformed qualifier \"%s\" in -Aquals=%s", qualName, qualNames);
}
Class<? extends Annotation> anno = loader.loadExternalAnnotationClass(qualName);
if (anno == null) {
throw new UserError("Qualifier specified in -Aquals not found: " + qualName);
}
qualSet.add(anno);
}
}
// load directories of qualifiers
if (qualDirectories != null) {
for (String dirName : qualDirectories.split(":")) {
Set<Class<? extends Annotation>> annos = loader.loadExternalAnnotationClassesFromDirectory(dirName);
if (annos.isEmpty()) {
throw new UserError("Directory specified in -AqualsDir contains no qualifiers: " + dirName);
}
qualSet.addAll(annos);
}
}
if (qualSet.isEmpty()) {
throw new UserError("SubtypingChecker: no qualifiers specified via -Aquals or -AqualDirs");
}
// check for subtype meta-annotation
for (Class<? extends Annotation> qual : qualSet) {
Annotation subtypeOfAnnotation = qual.getAnnotation(SubtypeOf.class);
if (subtypeOfAnnotation != null) {
for (Class<? extends Annotation> superqual : qual.getAnnotation(SubtypeOf.class).value()) {
if (!qualSet.contains(superqual)) {
throw new UserError("SubtypingChecker: qualifier " + qual + " was specified via -Aquals but its super-qualifier " + superqual + " was not");
}
}
}
}
return qualSet;
}
use of org.checkerframework.javacutil.UserError in project checker-framework by typetools.
the class SignaturePrinter method main.
public static void main(String[] args) {
if (!(args.length == 1 && !args[0].startsWith(CHECKER_ARG)) && !(args.length == 2 && args[0].startsWith(CHECKER_ARG))) {
printUsage();
return;
}
// process arguments
String checkerName = null;
if (args[0].startsWith(CHECKER_ARG)) {
checkerName = args[0].substring(CHECKER_ARG.length());
if (!Signatures.isBinaryName(checkerName)) {
throw new UserError("Bad checker name \"%s\"", checkerName);
}
}
// Setup compiler environment
Context context = new Context();
JavacProcessingEnvironment env = JavacProcessingEnvironment.instance(context);
SignaturePrinter printer = new SignaturePrinter();
printer.init(env, checkerName);
String className = args[args.length - 1];
TypeElement elem = env.getElementUtils().getTypeElement(className);
if (elem == null) {
System.err.println("Couldn't find class: " + className);
return;
}
printer.typeProcess(elem, null);
}
Aggregations