Skip to content

Commit 43db447

Browse files
authored
Add a new method to handle annotations not on the classpath
1 parent 3bca5e2 commit 43db447

File tree

2 files changed

+50
-24
lines changed

2 files changed

+50
-24
lines changed

dataflow/src/main/java/org/checkerframework/dataflow/cfg/builder/CFGTranslationPhaseOne.java

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -383,15 +383,6 @@ public class CFGTranslationPhaseOne extends TreeScanner<Node, Void> {
383383
*/
384384
protected final Set<TypeMirror> newArrayExceptionTypes;
385385

386-
/** The AssertMethod.value argument/element. */
387-
protected final ExecutableElement assertMethodValueElement;
388-
389-
/** The AssertMethod.parameter argument/element. */
390-
protected final ExecutableElement assertMethodParameterElement;
391-
392-
/** The {@link AssertMethod#isAssertFalse()} argument/element. */
393-
protected final ExecutableElement assertMethodIsAssertFalseElement;
394-
395386
/**
396387
* Creates {@link CFGTranslationPhaseOne}.
397388
*
@@ -458,11 +449,6 @@ public CFGTranslationPhaseOne(
458449
if (outOfMemoryErrorType != null) {
459450
newArrayExceptionTypes.add(outOfMemoryErrorType);
460451
}
461-
462-
assertMethodValueElement = TreeUtils.getMethod(AssertMethod.class, "value", 0, env);
463-
assertMethodParameterElement = TreeUtils.getMethod(AssertMethod.class, "parameter", 0, env);
464-
assertMethodIsAssertFalseElement =
465-
TreeUtils.getMethod(AssertMethod.class, "isAssertFalse", 0, env);
466452
}
467453

468454
/**
@@ -1406,19 +1392,20 @@ protected AssertMethodTuple getAssertMethodTuple(ExecutableElement method) {
14061392
return AssertMethodTuple.NONE;
14071393
}
14081394

1395+
// Dataflow does not require checker-qual.jar to be on the users classpath, so
1396+
// AnnotationUtils.getElementValue(...) cannot be used.
1397+
14091398
int booleanParam =
1410-
AnnotationUtils.getElementValue(
1411-
assertMethodAnno, assertMethodParameterElement, Integer.class, 1)
1399+
AnnotationUtils.getElementValueNotOnClasspath(
1400+
assertMethodAnno, "parameter", Integer.class, 1)
14121401
- 1;
1402+
14131403
TypeMirror exceptionType =
1414-
AnnotationUtils.getElementValue(
1415-
assertMethodAnno,
1416-
assertMethodValueElement,
1417-
Type.ClassType.class,
1418-
(Type.ClassType) assertionErrorType);
1404+
AnnotationUtils.getElementValueNotOnClasspath(
1405+
assertMethodAnno, "value", Type.ClassType.class, (Type.ClassType) assertionErrorType);
14191406
boolean isAssertFalse =
1420-
AnnotationUtils.getElementValue(
1421-
assertMethodAnno, assertMethodIsAssertFalseElement, Boolean.class, false);
1407+
AnnotationUtils.getElementValueNotOnClasspath(
1408+
assertMethodAnno, "isAssertFalse", Boolean.class, false);
14221409
return new AssertMethodTuple(booleanParam, exceptionType, isAssertFalse);
14231410
}
14241411

javacutil/src/main/java/org/checkerframework/javacutil/AnnotationUtils.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,45 @@ public static EnumSet<ElementKind> getElementKindsForElementType(ElementType ele
553553
// Annotation values: inefficient extractors that take an element name
554554
// **********************************************************************
555555

556+
/**
557+
* Get the element with the name {@code elementName} of the annotation {@code anno}. The result
558+
* has type {@code expectedType}. If there is no value for {@code elementName}, {@code
559+
* defaultValue} is returned
560+
*
561+
* <p>This method is intended only for use when the class of the annotation is not on the user's
562+
* classpath. This is for users of the Dataflow Framework that do not use the rest of the Checker
563+
* Framework. Type-checkers can assume that checker-qual.jar is on the classpath and should use
564+
* {@link #getElementValue(AnnotationMirror, ExecutableElement, Class)} or {@link
565+
* #getElementValue(AnnotationMirror, ExecutableElement, Class, Object)}.
566+
*
567+
* @param anno the annotation whose element to access
568+
* @param elementName the name of the element to access
569+
* @param expectedType the type of the element and the return value
570+
* @param defaultValue the value to return if the element is not present
571+
* @param <T> the class of the type
572+
* @return the value of the element with the given name
573+
*/
574+
public static <T> T getElementValueNotOnClasspath(
575+
AnnotationMirror anno, CharSequence elementName, Class<T> expectedType, T defaultValue) {
576+
Map<? extends ExecutableElement, ? extends AnnotationValue> valmap = anno.getElementValues();
577+
578+
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
579+
valmap.entrySet()) {
580+
ExecutableElement elem = entry.getKey();
581+
if (elem.getSimpleName().contentEquals(elementName)) {
582+
AnnotationValue val = entry.getValue();
583+
try {
584+
return expectedType.cast(val.getValue());
585+
} catch (ClassCastException e) {
586+
throw new BugInCF(
587+
"getElementValueNotOnClasspath(%s, %s, %s): val=%s, val.getValue()=%s [%s]",
588+
anno, elementName, expectedType, val, val.getValue(), val.getValue().getClass());
589+
}
590+
}
591+
}
592+
return defaultValue;
593+
}
594+
556595
/**
557596
* Returns the values of an annotation's elements, including defaults. The method with the same
558597
* name in JavacElements cannot be used directly, because it includes a cast to
@@ -604,7 +643,7 @@ public static EnumSet<ElementKind> getElementKindsForElementType(ElementType ele
604643
* @deprecated use {@link #getElementValue(AnnotationMirror, ExecutableElement, Class)} or {@link
605644
* #getElementValue(AnnotationMirror, ExecutableElement, Class, Object)}
606645
*/
607-
@Deprecated // for use only by the framework
646+
@Deprecated // for use only by the framework, not by clients
608647
public static <T> T getElementValue(
609648
AnnotationMirror anno, CharSequence elementName, Class<T> expectedType, boolean useDefaults) {
610649
Map<? extends ExecutableElement, ? extends AnnotationValue> valmap;

0 commit comments

Comments
 (0)