@SupportedOptions(value={"suppressWarnings","skipUses","onlyUses","skipDefs","onlyDefs","ignoreRawTypeArguments","assumeSideEffectFree","assumeAssertionsAreEnabled","assumeAssertionsAreDisabled","warns","checkPurityAnnotations","invariantArrays","checkCastElementType","useDefaultsForUncheckedCode","concurrentSemantics","conservativeUninferredTypeArguments","lint","suggestPureMethods","resolveReflection","infer","showSuppressWarningKeys","warnUnneededSuppressions","requirePrefixInWarningSuppressions","ignoreInvalidAnnotationLocations","stubs","stubWarnIfNotFound","stubWarnIfNotFoundIgnoresClasses","stubWarnIfOverwritesBytecode","stubWarnIfRedundantWithBytecode","printAllQualifiers","printVerboseGenerics","detailedmsgtext","noPrintErrorStack","nomsgtext","ignorejdkastub","nocheckjdk","stubDebug","filenames","showchecks","showInferenceSteps","cfgviz","flowdotdir","verbosecfg","resourceStats","atfCacheSize","atfDoNotCache"}) public abstract class SourceChecker extends AbstractTypeProcessor implements CFContext, OptionConfiguration
javac
's annotation processing
API, routines for error reporting via the JSR 199 compiler API, and an implementation for using a
SourceVisitor
to perform the type-checking.
Subclasses must implement the following methods: (TODO: update the list)
getMessages()
(for type-qualifier specific error messages)
createSourceVisitor()
(for a custom SourceVisitor
)
getSuppressWarningsKeys()
(for honoring @{link
SuppressWarnings} annotations)
BaseTypeChecker
, instead of this class.
Only checkers that require annotated types but not subtype checking (e.g. for testing purposes)
should extend this. Non-type checkers (e.g. for enforcing coding styles) may extend AbstractProcessor
(or even this class).Modifier and Type | Field and Description |
---|---|
protected com.sun.source.tree.CompilationUnitTree |
currentRoot
The source tree that is being scanned.
|
static java.lang.String |
DETAILS_SEPARATOR |
protected java.util.Set<javax.lang.model.element.Element> |
elementsWithSuppressedWarnings
Elements with a
@SuppressWarnings that actually suppressed a warning for this
checker. |
protected int |
errsOnLastExit
The number of errors at the last exit of the type processor.
|
protected javax.annotation.processing.Messager |
messager
Used to report error messages and warnings via the compiler.
|
protected java.util.Properties |
messages
Maps error keys to localized/custom error messages.
|
protected static java.lang.String |
MSGS_FILE
File name of the localized messages.
|
protected SourceChecker |
parentChecker
The checker that called this one, whether that be a BaseTypeChecker (used as a compound
checker) or an AggregateChecker.
|
static java.lang.String |
SUPPRESS_ALL_KEY
The @SuppressWarnings key that will suppress warnings for all checkers.
|
protected com.sun.source.util.Trees |
trees
Used as a helper for the
SourceVisitor . |
static @CompilerMessageKey java.lang.String |
UNNEEDED_SUPPRESSION_KEY
The @SuppressWarnings key emitted when an unused warning suppression is found.
|
protected java.util.List<java.lang.String> |
upstreamCheckerNames
List of upstream checker names.
|
protected SourceVisitor<?,?> |
visitor
The visitor to use.
|
Constructor and Description |
---|
SourceChecker() |
Modifier and Type | Method and Description |
---|---|
protected void |
addOptions(java.util.Map<java.lang.String,java.lang.String> moreopts)
Add additional active options.
|
protected abstract SourceVisitor<?,?> |
createSourceVisitor()
Provides the
SourceVisitor that the checker should use to scan input source trees. |
protected java.util.Set<java.lang.String> |
createSupportedLintOptions()
Compute the set of supported lint options.
|
protected java.util.Collection<java.lang.String> |
expandCFOptions(java.util.List<? extends java.lang.Class<?>> clazzPrefixes,
java.lang.String[] options)
Generate the possible command-line option names by prefixing each class name from
classPrefixes to options , separated by OPTION_SEPARATOR . |
protected java.lang.String |
formatStackTrace(java.lang.StackTraceElement[] stackTrace)
Format a list of
StackTraceElement s to be printed out as an error message. |
protected java.lang.String |
fullMessageOf(java.lang.String messageKey,
java.lang.String defValue)
Returns the localized long message corresponding for this key, and returns the defValue if no
localized message is found.
|
AnnotationProvider |
getAnnotationProvider() |
boolean |
getBooleanOption(java.lang.String name)
Determines the boolean value of the option with the given name.
|
boolean |
getBooleanOption(java.lang.String name,
boolean defaultValue)
Determines the boolean value of the option with the given name.
|
SourceChecker |
getChecker() |
CFContext |
getContext() |
javax.lang.model.util.Elements |
getElementUtils() |
boolean |
getLintOption(java.lang.String name)
Determines the value of the lint option with the given name.
|
boolean |
getLintOption(java.lang.String name,
boolean def)
Determines the value of the lint option with the given name.
|
java.util.Properties |
getMessages()
Provides a mapping of error keys to custom error messages.
|
java.lang.String |
getOption(java.lang.String name)
Determines the value of the option with the given name.
|
java.lang.String |
getOption(java.lang.String name,
java.lang.String defaultValue)
Determines the value of the lint option with the given name and returns the default value if
nothing is specified.
|
OptionConfiguration |
getOptionConfiguration() |
java.util.Map<java.lang.String,java.lang.String> |
getOptions()
Return all active options for this checker.
|
javax.annotation.processing.ProcessingEnvironment |
getProcessingEnvironment() |
protected java.util.Properties |
getProperties(java.lang.Class<?> cls,
java.lang.String filePath)
A helper function to parse a Properties file.
|
protected java.util.Collection<java.lang.String> |
getStandardSuppressWarningsKeys()
Determine the standard set of suppress warning keys usable for any checker.
|
java.util.Set<java.lang.String> |
getSupportedAnnotationTypes()
Overrides the default implementation to always return a singleton set containing only "*".
|
java.util.Set<java.lang.String> |
getSupportedLintOptions()
Returns the lint options recognized by this checker.
|
java.util.Set<java.lang.String> |
getSupportedOptions()
Map the Checker Framework version of
SupportedOptions to the standard annotation
provided version SupportedOptions . |
javax.lang.model.SourceVersion |
getSupportedSourceVersion() |
java.util.Collection<java.lang.String> |
getSuppressWarningsKeys() |
com.sun.source.util.Trees |
getTreeUtils() |
javax.lang.model.util.Types |
getTypeUtils() |
java.util.List<java.lang.String> |
getUpstreamCheckerNames()
Return a list containing this checker name and all checkers it is a part of (that is,
checkers that called it).
|
SourceVisitor<?,?> |
getVisitor() |
boolean |
hasOption(java.lang.String name)
Check whether the given option is provided.
|
void |
init(javax.annotation.processing.ProcessingEnvironment env) |
void |
initChecker()
Initialize the checker.
|
void |
message(javax.tools.Diagnostic.Kind kind,
java.lang.String msg,
java.lang.Object... args)
Print a non-localized message using the javac messager.
|
protected void |
printMessage(javax.tools.Diagnostic.Kind kind,
java.lang.String message,
com.sun.source.tree.Tree source,
com.sun.source.tree.CompilationUnitTree root)
Do not call this method directly.
|
protected void |
printStats()
Print resource usage statistics.
|
protected java.lang.Object |
processArg(java.lang.Object arg)
Process an argument to an error message before it is passed to String.format.
|
void |
report(Result r,
java.lang.Object src)
Reports a result.
|
protected void |
setLintOption(java.lang.String name,
boolean val)
Set the value of the lint option with the given name.
|
protected void |
setParentChecker(SourceChecker parentChecker)
Set the parent checker of the current checker.
|
protected void |
setProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment env)
Set the processing environment of the current checker.
|
protected void |
setRoot(com.sun.source.tree.CompilationUnitTree newRoot)
Invoked when the current compilation unit root changes.
|
protected void |
setSupportedLintOptions(java.util.Set<java.lang.String> newlints)
Set the supported lint options.
|
protected boolean |
shouldAddShutdownHook()
Return true to indicate that method
shutdownHook() should be added as a shutdownHook
of the JVM. |
boolean |
shouldSkipDefs(com.sun.source.tree.ClassTree node)
Tests whether the class definition should not be checked because it matches the
checker.skipDefs property. |
boolean |
shouldSkipDefs(com.sun.source.tree.ClassTree cls,
com.sun.source.tree.MethodTree meth)
Tests whether the method definition should not be checked because it matches the
checker.skipDefs property. |
boolean |
shouldSkipUses(javax.lang.model.element.Element element)
Tests whether the class owner of the passed element is an unannotated class and matches the
pattern specified in the
checker.skipUses property. |
boolean |
shouldSkipUses(java.lang.String typeName)
Tests whether the class owner of the passed type matches the pattern specified in the
checker.skipUses property. |
boolean |
shouldSuppressWarnings(@Nullable javax.lang.model.element.Element elt,
java.lang.String errKey)
Determines whether all the warnings pertaining to a given tree should be suppressed.
|
boolean |
shouldSuppressWarnings(com.sun.source.tree.Tree tree,
java.lang.String errKey)
Determines whether all the warnings pertaining to a given tree should be suppressed.
|
protected void |
shutdownHook()
Method that gets called exactly once at shutdown time of the JVM.
|
java.lang.String |
treeToFilePositionString(com.sun.source.tree.Tree tree,
com.sun.source.tree.CompilationUnitTree currentRoot,
javax.annotation.processing.ProcessingEnvironment processingEnv)
For the given tree, compute the source positions for that tree.
|
void |
typeProcess(javax.lang.model.element.TypeElement e,
com.sun.source.util.TreePath p)
Type-check the code with Java specifications and then runs the Checker Rule Checking visitor
on the processed source.
|
void |
typeProcessingStart()
A method to be called once before the first call to typeProcess.
|
boolean |
useUncheckedCodeDefault(java.lang.String kindOfCode)
Should unchecked code defaults be used for the kind of code indicated by the parameter.
|
protected void |
warnUnneededSuppressions()
Issues a warning about any
@SuppressWarnings that isn't used by this checker, but
contains a key that would suppress a warning from this checker. |
protected void |
warnUnneedSuppressions(java.util.Set<javax.lang.model.element.Element> elementsSuppress,
java.util.Set<java.lang.String> checkerKeys,
java.util.Set<java.lang.String> errorKeys)
Issues a warning about any
@SuppressWarnings that isn't used by this checker, but
contains a key that would suppress a warning from this checker. |
process, typeProcessingOver
public static final java.lang.String SUPPRESS_ALL_KEY
public static final @CompilerMessageKey java.lang.String UNNEEDED_SUPPRESSION_KEY
protected static final java.lang.String MSGS_FILE
protected java.util.Properties messages
protected javax.annotation.processing.Messager messager
protected com.sun.source.util.Trees trees
SourceVisitor
.protected com.sun.source.tree.CompilationUnitTree currentRoot
protected SourceVisitor<?,?> visitor
protected SourceChecker parentChecker
protected java.util.List<java.lang.String> upstreamCheckerNames
protected int errsOnLastExit
public static final java.lang.String DETAILS_SEPARATOR
protected final java.util.Set<javax.lang.model.element.Element> elementsWithSuppressedWarnings
@SuppressWarnings
that actually suppressed a warning for this
checker.public final void init(javax.annotation.processing.ProcessingEnvironment env)
AbstractTypeProcessor
Register a TaskListener that will get called after FLOW.
init
in interface javax.annotation.processing.Processor
init
in class AbstractTypeProcessor
public javax.annotation.processing.ProcessingEnvironment getProcessingEnvironment()
getProcessingEnvironment
in interface BaseContext
ProcessingEnvironment
that was supplied to this checkerprotected void setProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment env)
protected void setParentChecker(SourceChecker parentChecker)
protected void setRoot(com.sun.source.tree.CompilationUnitTree newRoot)
public java.util.List<java.lang.String> getUpstreamCheckerNames()
public SourceChecker getChecker()
getChecker
in interface CFContext
public OptionConfiguration getOptionConfiguration()
getOptionConfiguration
in interface BaseContext
public javax.lang.model.util.Elements getElementUtils()
getElementUtils
in interface BaseContext
public javax.lang.model.util.Types getTypeUtils()
getTypeUtils
in interface BaseContext
public com.sun.source.util.Trees getTreeUtils()
getTreeUtils
in interface BaseContext
public SourceVisitor<?,?> getVisitor()
getVisitor
in interface CFContext
protected abstract SourceVisitor<?,?> createSourceVisitor()
SourceVisitor
that the checker should use to scan input source trees.SourceVisitor
to use to scan source treespublic AnnotationProvider getAnnotationProvider()
getAnnotationProvider
in interface BaseContext
public java.util.Properties getMessages()
As a default, this implementation builds a Properties
out of file messages.properties
. It accumulates all the properties files in the Java class hierarchy
from the checker up to SourceChecker
. This permits subclasses to inherit default
messages while being able to override them.
Properties
that maps error keys to error message textpublic void typeProcessingStart()
Subclasses may override this method to do any initialization work.
Type-checkers are not supposed to override this. Instead use initChecker. This allows us to handle BugInCF only here and doesn't require all overriding implementations to be aware of BugInCF.
typeProcessingStart
in class AbstractTypeProcessor
AbstractProcessor.init(ProcessingEnvironment)
,
initChecker()
public void initChecker()
AbstractProcessor.init(ProcessingEnvironment)
protected boolean shouldAddShutdownHook()
shutdownHook()
should be added as a shutdownHook
of the JVM.protected void shutdownHook()
protected void printStats()
public void typeProcess(javax.lang.model.element.TypeElement e, com.sun.source.util.TreePath p)
typeProcess
in class AbstractTypeProcessor
e
- element of the analyzed classp
- the tree path to the element, with the leaf being a ClassTree
Processor.process(Set, RoundEnvironment)
protected void warnUnneededSuppressions()
@SuppressWarnings
that isn't used by this checker, but
contains a key that would suppress a warning from this checker.protected void warnUnneedSuppressions(java.util.Set<javax.lang.model.element.Element> elementsSuppress, java.util.Set<java.lang.String> checkerKeys, java.util.Set<java.lang.String> errorKeys)
@SuppressWarnings
that isn't used by this checker, but
contains a key that would suppress a warning from this checker.elementsSuppress
- elements with a @SuppressWarnings
that actually suppressed a
warningcheckerKeys
- suppress warning keys that suppress any warning from this checkererrorKeys
- error keys that can be issued by this checkerprotected java.lang.String formatStackTrace(java.lang.StackTraceElement[] stackTrace)
StackTraceElement
s to be printed out as an error message.protected java.lang.String fullMessageOf(java.lang.String messageKey, java.lang.String defValue)
protected void printMessage(javax.tools.Diagnostic.Kind kind, java.lang.String message, com.sun.source.tree.Tree source, com.sun.source.tree.CompilationUnitTree root)
report(Result, Object)
instead. (This method
exists so that the BaseTypeChecker can override it and treat messages from compound checkers
differently.)protected java.lang.Object processArg(java.lang.Object arg)
arg
- the argumentpublic void message(javax.tools.Diagnostic.Kind kind, java.lang.String msg, java.lang.Object... args)
report(Result,
Object)
.kind
- the kind of message to printmsg
- the message textargs
- optional arguments to substitute in the messagereport(Result, Object)
public java.lang.String treeToFilePositionString(com.sun.source.tree.Tree tree, com.sun.source.tree.CompilationUnitTree currentRoot, javax.annotation.processing.ProcessingEnvironment processingEnv)
tree
- tree to locate within the current compilation unitcurrentRoot
- the current compilation unitprocessingEnv
- the current processing environmentpublic boolean shouldSuppressWarnings(com.sun.source.tree.Tree tree, java.lang.String errKey)
getSuppressWarningsKeys()
method.tree
- the tree that might be a source of a warningerrKey
- the error key the checker is emittingpublic boolean useUncheckedCodeDefault(java.lang.String kindOfCode)
kindOfCode
- source or bytecodepublic boolean shouldSuppressWarnings(@Nullable javax.lang.model.element.Element elt, java.lang.String errKey)
getSuppressWarningsKeys()
method.elt
- the Element that might be a source of, or related to, a warningerrKey
- the error key the checker is emitting@SuppressWarnings
annotation; false
otherwisepublic void report(Result r, java.lang.Object src)
r
- the result to reportsrc
- the position object associated with the resultpublic final boolean getLintOption(java.lang.String name)
name
- the name of the lint option to check forjava.lang.IllegalArgumentException
- if the option name is not recognized via the SupportedLintOptions
annotation or the getSupportedLintOptions()
methodgetLintOption(String, boolean)
public final boolean getLintOption(java.lang.String name, boolean def)
name
- the name of the lint option to check fordef
- the default option value, returned if the option was not givendef
if it was not given at alljava.lang.IllegalArgumentException
- if the option name is not recognized via the SupportedLintOptions
annotation or the getSupportedLintOptions()
methodgetLintOption(String)
,
getOption(String)
protected final void setLintOption(java.lang.String name, boolean val)
name
- the name of the lint option to setval
- the option valuejava.lang.IllegalArgumentException
- if the option name is not recognized via the SupportedLintOptions
annotation or the getSupportedLintOptions()
methodgetLintOption(String)
,
getLintOption(String,boolean)
public java.util.Set<java.lang.String> getSupportedLintOptions()
getLintOption(java.lang.String)
.Set
of the lint options recognized by this checkerprotected java.util.Set<java.lang.String> createSupportedLintOptions()
protected void setSupportedLintOptions(java.util.Set<java.lang.String> newlints)
protected void addOptions(java.util.Map<java.lang.String,java.lang.String> moreopts)
public final boolean hasOption(java.lang.String name)
Note that getOption(String)
can still return null even if hasOption
returns true: this happens e.g. for -Amyopt
hasOption
in interface OptionConfiguration
name
- the name of the option to checkpublic final java.lang.String getOption(java.lang.String name)
getOption
in interface OptionConfiguration
name
- the name of the option to checkgetLintOption(String,boolean)
public final boolean getBooleanOption(java.lang.String name)
getBooleanOption
in interface OptionConfiguration
name
- the name of the option to checkgetLintOption(String,boolean)
public final boolean getBooleanOption(java.lang.String name, boolean defaultValue)
getBooleanOption
in interface OptionConfiguration
name
- the name of the option to checkdefaultValue
- the default value to use if the option is not setgetLintOption(String,boolean)
public java.util.Map<java.lang.String,java.lang.String> getOptions()
getOptions
in interface OptionConfiguration
public final java.lang.String getOption(java.lang.String name, java.lang.String defaultValue)
getOption
in interface OptionConfiguration
name
- the name of the option to checkdefaultValue
- the default value to use if the option is not setgetOption(String)
,
getLintOption(String)
public java.util.Set<java.lang.String> getSupportedOptions()
SupportedOptions
to the standard annotation
provided version SupportedOptions
.getSupportedOptions
in interface javax.annotation.processing.Processor
getSupportedOptions
in interface OptionConfiguration
getSupportedOptions
in class javax.annotation.processing.AbstractProcessor
protected java.util.Collection<java.lang.String> expandCFOptions(java.util.List<? extends java.lang.Class<?>> clazzPrefixes, java.lang.String[] options)
classPrefixes
to options
, separated by OPTION_SEPARATOR
.clazzPrefixes
- the classes to prefixoptions
- the option namespublic final java.util.Set<java.lang.String> getSupportedAnnotationTypes()
javac uses this list to determine which classes process; javac only runs an annotation
processor on classes that contain at least one of the mentioned annotations. Thus, the effect
of returning "*" is as if the checker were annotated by
@SupportedAnnotationTypes("*")
: javac runs the checker on every class mentioned on
the javac command line. This method also checks that subclasses do not contain a SupportedAnnotationTypes
annotation.
To specify the annotations that a checker recognizes as type qualifiers, see AnnotatedTypeFactory.createSupportedTypeQualifiers()
.
getSupportedAnnotationTypes
in interface javax.annotation.processing.Processor
getSupportedAnnotationTypes
in class javax.annotation.processing.AbstractProcessor
java.lang.Error
- if a subclass is annotated with SupportedAnnotationTypes
public java.util.Collection<java.lang.String> getSuppressWarningsKeys()
SuppressWarningsKeys
protected final java.util.Collection<java.lang.String> getStandardSuppressWarningsKeys()
getSuppressWarningsKeys()
public final boolean shouldSkipUses(javax.lang.model.element.Element element)
checker.skipUses
property.element
- an elementpublic boolean shouldSkipUses(java.lang.String typeName)
checker.skipUses
property. In contrast to shouldSkipUses(Element)
this version can
also be used from primitive types, which don't have an element.
Checkers that require their annotations not to be checked on certain JDK classes may
override this method to skip them. They shall call super.shouldSkipUses(typerName)
to
also skip the classes matching the pattern.
typeName
- the fully-qualified name of a typepublic final boolean shouldSkipDefs(com.sun.source.tree.ClassTree node)
checker.skipDefs
property.node
- class to potentially skippublic final boolean shouldSkipDefs(com.sun.source.tree.ClassTree cls, com.sun.source.tree.MethodTree meth)
checker.skipDefs
property.
TODO: currently only uses the class definition. Refine pattern. Same for skipUses.
cls
- class to potentially skipmeth
- method to potentially skipprotected java.util.Properties getProperties(java.lang.Class<?> cls, java.lang.String filePath)
cls
- the class whose location is the base of the file pathfilePath
- the name/path of the file to be readpublic final javax.lang.model.SourceVersion getSupportedSourceVersion()
getSupportedSourceVersion
in interface javax.annotation.processing.Processor
getSupportedSourceVersion
in class javax.annotation.processing.AbstractProcessor