@NotThreadSafe public abstract class ConfigurationBuilder extends Object
Configuration
for customising Mutability Detector's analysis.
The most significant feature of ConfigurationBuilder
is to allow
defining hardcoded results for particular classes, which should be respected
during analysis. For more details, see MutabilityAssert
.
Users should subclass ConfigurationBuilder
and override the
configure()
method, which should then be used to construct a
MutabilityAsserter instance.
For example:
MutabilityAsserter myAsserter = MutabilityAsserter.configured(new ConfigurationBuilder() {
@Override public void configure() {
hardcodeAsDefinitelyImmutable(SomeClass.class);
setExceptionPolicy(ExceptionPolicy.CARRY_ON);
mergeHardcodedResultsFrom(ConfigurationBuilder.DEFAULT_CONFIGURATION);
}
});
This class also provides an out-of-the-box configuration with hardcoded
results for common JDK classes. This includes classes where Mutability
Detector's analysis is incorrect, for example, java.lang.String,
java.lang.Integer (and other primitive wrapper types) and
java.math.BigDecimal.Configurations.JDK_CONFIGURATION
Constructor and Description |
---|
ConfigurationBuilder() |
Modifier and Type | Method and Description |
---|---|
Configuration |
build() |
abstract void |
configure()
Subclasses should override this method to configure analysis.
|
com.google.common.collect.Multimap<String,CopyMethod> |
getCopyMethodsAllowed() |
protected Set<AnalysisResult> |
getCurrentlyHardcodedResults()
Returns an immutable snapshot of the hardcoded results as at time of calling.
|
protected void |
hardcodeAsDefinitelyImmutable(Class<?> immutableClass)
Hardcodes a result indicating the given class is Immutable.
|
protected void |
hardcodeAsDefinitelyImmutable(String immutableClassName)
Hardcodes a result indicating the given class is Immutable.
|
protected void |
hardcodeAsImmutableContainerType(Class<?> immutableContainerClass)
Configures a generic container type as immutable.
|
protected void |
hardcodeAsImmutableContainerType(String immutableContainerClassName) |
protected void |
hardcodeResult(AnalysisResult result)
Add a predefined result used during analysis.
|
protected void |
hardcodeResults(AnalysisResult... result)
Adds all the given AnalysisResults, as if hardcodeResult was called for
each element in the var args parameter.
|
protected void |
hardcodeResults(Iterable<AnalysisResult> result)
Adds all the given AnalysisResults, as if hardcodeResult was called for
each element in the iterable.
|
protected void |
hardcodeValidCopyMethod(Class<?> fieldType,
CopyMethod copyMethod) |
protected void |
hardcodeValidCopyMethod(Class<?> fieldType,
String fullyQualifiedMethodName,
Class<?> argType)
Hardcode a copy method as being valid.
|
protected void |
merge(Configuration otherConfiguration)
Merges configuration from another configuration with this one.
|
protected void |
mergeHardcodedResultsFrom(Configuration otherConfiguration)
Merges the hardcoded results of this Configuration with the given
Configuration.
|
protected void |
mergeImmutableContainerTypesFrom(Configuration otherConfiguration)
Merges the immutable container types of this Configuration with the given
Configuration.
|
protected void |
mergeValidCopyMethodsFrom(Configuration otherConfiguration)
Merge valid copy methods from another configuration.
|
protected void |
setClassloadingPolicy(AsmVerifierFactory.ClassloadingOption classloadingOption)
Configures whether Mutability Detector loads classes or not during analysis.
|
protected void |
setExceptionPolicy(CheckerRunner.ExceptionPolicy exceptionPolicy)
Configures how Mutability Detector's analysis should respond to
exceptions during analysis.
|
protected void |
setHowToUseHardcodedResults(HardcodedResultsUsage usage)
Specifies how hardcoded results should be used.
|
protected void |
useAdvancedReassignedFieldAlgorithm() |
public abstract void configure()
It is recommended that any custom Configuration
's merge with the
Configurations.OUT_OF_THE_BOX_CONFIGURATION
in order to remain consistent with
MutabilityAssert
, and the command line settings. For example:
MutabilityAsserter myAsserter = MutabilityAsserter.configured(new ConfigurationBuilder() {
@Override public void configure() {
mergeHardcodedResultsFrom(ConfigurationBuilder.OUT_OF_THE_BOX_CONFIGURATION);
}
});
Similarly for DefaultCachingAnalysisSession.createWithCurrentClassPath(Configuration)
The available configuration methods are listed below.
hardcodeResult(AnalysisResult)
,
hardcodeResults(AnalysisResult...)
,
hardcodeResults(Iterable)
,
hardcodeAsDefinitelyImmutable(Class)
,
hardcodeAsDefinitelyImmutable(String)
,
setHowToUseHardcodedResults(HardcodedResultsUsage)
,
mergeHardcodedResultsFrom(Configuration)
,
#setExceptionPolicy(ExceptionPolicy)
,
Configurations.OUT_OF_THE_BOX_CONFIGURATION
public final Configuration build()
protected final void setExceptionPolicy(CheckerRunner.ExceptionPolicy exceptionPolicy)
During analysis, an exception may occur which is recoverable. That is, Mutability Detector is able to continue it's analysis, and may produce valid results.
The default behaviour is to use CheckerRunner.ExceptionPolicy.FAIL_FAST
,
meaning any unhandled exceptions will propogate up past the assertion,
and cause a failing test.
Setting this configuration flag to CheckerRunner.ExceptionPolicy.CARRY_ON
may
allow unit tests to function where exceptions don't necessarily preclude
a useful output. For example, consider a class which you wish to make
immutable; a test for that class fails with an unhandled exception. If
that test has, say 10 reasons for mutability, and 1 of those causes the
test to abort with an exception, you have just lost out on 90% of the
required information. CheckerRunner.ExceptionPolicy.CARRY_ON
will allow the
test to report 9 out of 10 reasons. The test may be useful, although it
won't be comprehensive.
If you are unlucky enough to have a test which results in an exception, please report it to the Mutability Detector project, at the project homepage.
exceptionPolicy
- - how to respond to exceptions during analysis. Defaults to
CheckerRunner.ExceptionPolicy.FAIL_FAST
Configuration.exceptionPolicy()
protected final void setClassloadingPolicy(AsmVerifierFactory.ClassloadingOption classloadingOption)
Mutability Detector often needs to analyse classes other than the one
specified in order to gain a more accurate result. The default behaviour
is to load these classes from the current classpath. Setting this flag to
AsmVerifierFactory.ClassloadingOption.DISABLED
will instruct Mutability Detector not to
attempt to load classes, and instead use a method of analysing
all classes, which guarantees not to load classes. This can save on heap requirements
as Mutability Detector's non classloading approach requires less data than class loading.
For the moment, this option is recommended if you find classloading takes up too much heap, and the classes loaded for analysis won't be loaded anyway.
classloadingOption
- - whether to allow class loading for analysis or notConfiguration.classloadingOption()
protected final void hardcodeResult(AnalysisResult result)
Hardcoding a result means that information queried about a class will
honour the result you have set. For example, if during analysis,
Mutability Detector has to discover whether a field type is mutable or
not. However, requesting the AnalysisResult
of the class in
question directly will return the real result from the actual analysis.
This holds for unit tests, command line runs, and runtime analysis. As
such, calling this method will have no effect when querying an
AnalysisResult directly.
protected final void hardcodeResults(Iterable<AnalysisResult> result)
AnalysisResult
,
hardcodeResult(AnalysisResult)
protected final void hardcodeResults(AnalysisResult... result)
AnalysisResult
,
hardcodeResult(AnalysisResult)
protected final void hardcodeAsDefinitelyImmutable(Class<?> immutableClass)
protected final void hardcodeAsDefinitelyImmutable(String immutableClassName)
protected final void setHowToUseHardcodedResults(HardcodedResultsUsage usage)
HardcodedResultsUsage.LOOKUP_WHEN_REFERENCED
which was the implicit behaviour in
Mutability Detector prior to the introduction of this configuration setting.protected final Set<AnalysisResult> getCurrentlyHardcodedResults()
protected final void hardcodeAsImmutableContainerType(Class<?> immutableContainerClass)
private final ImmutableContainer<java.util.Date> // considered mutable
private final ImmutableContainer<GENERIC_TYPE_VARIABLE> // considered mutable
private final ImmutableContainer<?> // considered mutable
private final ImmutableContainer<String> // considered immutable
A good example of an immutable container type is JDK 8's java.util.Optional. It has a single, final field, and
cannot be subclassed. However, the generic parameter allows an instance of Optional to contain a mutable type,
which can be modified by any code with a reference. However, if a class has an Optional field containing an
immutable type, e.g. Optional<String>
then it should not cause the class to be considered
mutable.
Be default java.util.Optional is considered an immutable container class.immutableContainerClass
- class that is immutable as long as contained elements are immutableMutabilityReason.COLLECTION_FIELD_WITH_MUTABLE_ELEMENT_TYPE
protected final void hardcodeAsImmutableContainerType(String immutableContainerClassName)
protected void mergeHardcodedResultsFrom(Configuration otherConfiguration)
mergeHardcodedResultsFrom(Configuration)
.otherConfiguration
- - Configuration to merge hardcoded results with.protected void mergeImmutableContainerTypesFrom(Configuration otherConfiguration)
mergeImmutableContainerTypesFrom(Configuration)
.otherConfiguration
- - Configuration to merge immutable container types with.protected void mergeValidCopyMethodsFrom(Configuration otherConfiguration)
otherConfiguration
- - configuration to merge harcoded copy methods from.protected void merge(Configuration otherConfiguration)
other
will be applied.
Merging applies only to the configuration applied to certain classes, such as hardcoded results. It does not
change this Configuration
's setting for e.g. @{link #setExceptionPolicy}.
otherConfiguration
- configuration to merge frommergeHardcodedResultsFrom(Configuration)
,
mergeImmutableContainerTypesFrom(Configuration)
,
mergeValidCopyMethodsFrom(Configuration)
protected void useAdvancedReassignedFieldAlgorithm()
protected final void hardcodeValidCopyMethod(Class<?> fieldType, String fullyQualifiedMethodName, Class<?> argType)
fieldType
- - the type of the field to which the result of the copy is assignedfullyQualifiedMethodName
- - the fully qualified method nameargType
- - the type of the argument passed to the copy methodMutabilityAnalysisException
- - if the specified class or method does not existIllegalArgumentException
- - if any of the arguments are nullprotected void hardcodeValidCopyMethod(Class<?> fieldType, CopyMethod copyMethod)
public com.google.common.collect.Multimap<String,CopyMethod> getCopyMethodsAllowed()
Copyright © 2008–2020 Graham Allan. All rights reserved.