Skip to content

Commit eb741f4

Browse files
committed
Reapply code changes with profile
1 parent 055a4f3 commit eb741f4

8 files changed

Lines changed: 106 additions & 90 deletions

File tree

framework/src/main/java/org/checkerframework/common/basetype/BaseTypeChecker.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Set;
2626

2727
import javax.lang.model.element.AnnotationMirror;
28+
import javax.lang.model.element.Element;
2829

2930
/**
3031
* An abstract {@link SourceChecker} that provides a simple {@link
@@ -313,4 +314,21 @@ public BaseTypeChecker getUltimateParentChecker() {
313314
causeMessage);
314315
}
315316
}
317+
318+
/**
319+
* Return true if the element has an {@code @AnnotatedFor} annotation, for this checker or an
320+
* upstream checker that called this one.
321+
*
322+
* @param elt the source code element to check, or null
323+
* @return true if the element is annotated for this checker or an upstream checker
324+
*/
325+
@Override
326+
public boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(Element elt) {
327+
// The implementation of this method is at AnnotatedTypeFactory because postinit() is called
328+
// in the constructor of ATFs and use the same method before the ATF is fully initialized.
329+
// Implement it here and call this method by atf.getChecker() would fail as it will call
330+
// getTypeFactory() in the body and would result type system error as the visitor is not
331+
// initialized yet.
332+
return getTypeFactory().isElementAnnotatedForThisCheckerOrUpstreamChecker(elt);
333+
}
316334
}

framework/src/main/java/org/checkerframework/common/util/count/AnnotationStatistics.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.checkerframework.framework.source.SourceVisitor;
2424
import org.checkerframework.framework.source.SupportedOptions;
2525
import org.checkerframework.javacutil.AnnotationProvider;
26+
import org.checkerframework.javacutil.BugInCF;
2627

2728
import java.util.HashMap;
2829
import java.util.Map;
@@ -31,6 +32,7 @@
3132

3233
import javax.annotation.processing.SupportedSourceVersion;
3334
import javax.lang.model.SourceVersion;
35+
import javax.lang.model.element.Element;
3436
import javax.lang.model.element.Name;
3537
import javax.tools.Diagnostic;
3638

@@ -326,4 +328,9 @@ public AnnotationProvider getAnnotationProvider() {
326328
throw new UnsupportedOperationException(
327329
"getAnnotationProvider is not implemented for this class.");
328330
}
331+
332+
@Override
333+
protected boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(Element elt) {
334+
throw new BugInCF("Unexpected call to determine whether this checker is annotated");
335+
}
329336
}

framework/src/main/java/org/checkerframework/common/util/count/JavaCodeStatistics.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
import org.checkerframework.framework.source.SourceVisitor;
1818
import org.checkerframework.javacutil.AnnotationProvider;
1919
import org.checkerframework.javacutil.AnnotationUtils;
20+
import org.checkerframework.javacutil.BugInCF;
2021
import org.checkerframework.javacutil.TreeUtils;
2122

2223
import java.util.List;
2324

2425
import javax.annotation.processing.SupportedSourceVersion;
2526
import javax.lang.model.SourceVersion;
2627
import javax.lang.model.element.AnnotationMirror;
28+
import javax.lang.model.element.Element;
2729
import javax.lang.model.element.ExecutableElement;
2830

2931
/**
@@ -203,4 +205,9 @@ public AnnotationProvider getAnnotationProvider() {
203205
throw new UnsupportedOperationException(
204206
"getAnnotationProvider is not implemented for this class.");
205207
}
208+
209+
@Override
210+
protected boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(Element elt) {
211+
throw new BugInCF("Unexpected call to determine whether this checker is annotated");
212+
}
206213
}

framework/src/main/java/org/checkerframework/common/util/debug/SignaturePrinter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
1616
import org.checkerframework.javacutil.AbstractTypeProcessor;
1717
import org.checkerframework.javacutil.AnnotationProvider;
18+
import org.checkerframework.javacutil.BugInCF;
1819
import org.checkerframework.javacutil.ElementUtils;
1920
import org.checkerframework.javacutil.UserError;
2021
import org.plumelib.reflection.Signatures;
@@ -100,6 +101,13 @@ private void init(ProcessingEnvironment env, @Nullable @BinaryName String checke
100101
checker =
101102
new SourceChecker() {
102103

104+
@Override
105+
protected boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(
106+
Element elt) {
107+
throw new BugInCF(
108+
"Unexpected call to determine whether this checker is annotated");
109+
}
110+
103111
@Override
104112
protected SourceVisitor<?, ?> createSourceVisitor() {
105113
return null;

framework/src/main/java/org/checkerframework/framework/source/AggregateChecker.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.LinkedHashSet;
88
import java.util.Set;
99

10+
import javax.lang.model.element.Element;
1011
import javax.tools.Diagnostic;
1112

1213
/**
@@ -52,4 +53,14 @@ protected final Set<Class<? extends SourceChecker>> getImmediateSubcheckerClasse
5253
// the checkers in the aggregate checker do.
5354
};
5455
}
56+
57+
/**
58+
* Return false, determine whether an aggregatechecker is annotated for depends on its
59+
* subcheckers. For checkers that have upstream checker and want to handle annotatedfor in both
60+
* this and upstream checker, see InitializationChecker#getUpstreamCheckerNames().
61+
*/
62+
@Override
63+
protected boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(Element elt) {
64+
return false;
65+
}
5566
}

framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@
3232
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
3333
import org.checkerframework.common.basetype.BaseTypeChecker;
3434
import org.checkerframework.common.reflection.MethodValChecker;
35-
import org.checkerframework.framework.qual.AnnotatedFor;
3635
import org.checkerframework.framework.type.AnnotatedTypeFactory;
37-
import org.checkerframework.framework.util.CheckerMain;
3836
import org.checkerframework.framework.util.OptionConfiguration;
3937
import org.checkerframework.framework.util.TreePathCacher;
4038
import org.checkerframework.javacutil.AbstractTypeProcessor;
@@ -153,7 +151,7 @@
153151
// only issue errors for code inside the scope of `@NullMarked` annotations.
154152
// See
155153
// https://github.com/uber/NullAway/wiki/Configuration#only-nullmarked-version-0123-and-after.
156-
// org.checkerframework.framework.source.SourceChecker.isAnnotatedForThisCheckerOrUpstreamChecker
154+
// org.checkerframework.framework.source.SourceChecker.isElementAnnotatedForThisCheckerOrUpstreamChecker
157155
"onlyAnnotatedFor",
158156

159157
// Unsoundly assume all methods have no side effects, are deterministic, or both.
@@ -2778,9 +2776,7 @@ public boolean shouldSuppressWarnings(@Nullable TreePath path, String errKey) {
27782776
return true;
27792777
}
27802778

2781-
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
2782-
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
2783-
// elements as the closest AnnotatedFor is already found.
2779+
if (isElementAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
27842780
return false;
27852781
}
27862782
} else if (TreeUtils.classTreeKinds().contains(decl.getKind())) {
@@ -2790,19 +2786,16 @@ public boolean shouldSuppressWarnings(@Nullable TreePath path, String errKey) {
27902786
return true;
27912787
}
27922788

2793-
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
2794-
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
2795-
// elements as the closest AnnotatedFor is already found.
2789+
if (isElementAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
27962790
return false;
27972791
}
27982792
Element packageElement = elt.getEnclosingElement();
27992793
if (packageElement != null && packageElement.getKind() == ElementKind.PACKAGE) {
28002794
if (shouldSuppressWarnings(packageElement, errKey)) {
28012795
return true;
28022796
}
2803-
if (isAnnotatedForThisCheckerOrUpstreamChecker(packageElement)) {
2804-
// Return false immediately. Do NOT check for AnnotatedFor in the enclosing
2805-
// elements as the closest AnnotatedFor is already found.
2797+
2798+
if (isElementAnnotatedForThisCheckerOrUpstreamChecker(packageElement)) {
28062799
return false;
28072800
}
28082801
}
@@ -2880,11 +2873,6 @@ public boolean shouldSuppressWarnings(@Nullable Element elt, String errKey) {
28802873
return true;
28812874
}
28822875
}
2883-
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
2884-
// Return false immediately. Do NOT check for AnnotatedFor in the
2885-
// enclosing elements, because they may not have an @AnnotatedFor.
2886-
return false;
2887-
}
28882876
}
28892877
return false;
28902878
}
@@ -3016,33 +3004,7 @@ protected boolean messageKeyMatches(
30163004
* @param elt the source code element to check, or null
30173005
* @return true if the element is annotated for this checker or an upstream checker
30183006
*/
3019-
private boolean isAnnotatedForThisCheckerOrUpstreamChecker(@Nullable Element elt) {
3020-
// Return false if elt is null, or if neither useConservativeDefaultsSource nor
3021-
// issueErrorsForOnlyAnnotatedForScope is set, since the @AnnotatedFor status is irrelevant
3022-
// in that case.
3023-
// TODO: Refactor SourceChecker and QualifierDefaults to use a cache for determining if an
3024-
// element is annotated for.
3025-
if (elt == null || (!useConservativeDefaultsSource && !onlyAnnotatedFor)) {
3026-
return false;
3027-
}
3028-
3029-
AnnotatedFor anno = elt.getAnnotation(AnnotatedFor.class);
3030-
3031-
String[] userAnnotatedFors = (anno == null ? null : anno.value());
3032-
3033-
if (userAnnotatedFors != null) {
3034-
List<@FullyQualifiedName String> upstreamCheckerNames = getUpstreamCheckerNames();
3035-
3036-
for (String userAnnotatedFor : userAnnotatedFors) {
3037-
if (CheckerMain.matchesCheckerOrSubcheckerFromList(
3038-
userAnnotatedFor, upstreamCheckerNames)) {
3039-
return true;
3040-
}
3041-
}
3042-
}
3043-
3044-
return false;
3045-
}
3007+
protected abstract boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(Element elt);
30463008

30473009
/**
30483010
* Returns a modifiable set of lower-case strings that are prefixes for SuppressWarnings

framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,9 @@ void checkRep(String aliasName) {
537537
/** Mapping from a Tree to its TreePath. Shared between all instances. */
538538
private final TreePathCacher treePathCache;
539539

540+
/** A mapping of Element &rarr; Whether or not that element is AnnotatedFor this type system. */
541+
private final IdentityHashMap<Element, Boolean> elementAnnotatedFors = new IdentityHashMap<>();
542+
540543
/** Whether to ignore type arguments from raw types. */
541544
public final boolean ignoreRawTypeArguments;
542545

@@ -6035,6 +6038,49 @@ public boolean doesAnnotatedForApplyToThisChecker(AnnotationMirror annotatedForA
60356038
return false;
60366039
}
60376040

6041+
/**
6042+
* Return true if the element has an {@code @AnnotatedFor} annotation, for this checker or an
6043+
* upstream checker that called this one.
6044+
*
6045+
* @param elt the source code element to check, or null
6046+
* @return true if the element is annotated for this checker or an upstream checker
6047+
*/
6048+
public boolean isElementAnnotatedForThisCheckerOrUpstreamChecker(@Nullable Element elt) {
6049+
boolean elementAnnotatedForThisChecker = false;
6050+
6051+
if (elt == null) {
6052+
throw new BugInCF(
6053+
"Call of QualifierDefaults.isElementAnnotatedForThisChecker with null");
6054+
}
6055+
6056+
if (elementAnnotatedFors.containsKey(elt)) {
6057+
return elementAnnotatedFors.get(elt);
6058+
}
6059+
6060+
AnnotationMirror annotatedFor = getDeclAnnotation(elt, AnnotatedFor.class);
6061+
6062+
if (annotatedFor != null) {
6063+
elementAnnotatedForThisChecker = doesAnnotatedForApplyToThisChecker(annotatedFor);
6064+
}
6065+
6066+
if (!elementAnnotatedForThisChecker) {
6067+
Element parent;
6068+
if (elt.getKind() == ElementKind.PACKAGE) {
6069+
parent = ElementUtils.parentPackage((PackageElement) elt, elements);
6070+
} else {
6071+
parent = elt.getEnclosingElement();
6072+
}
6073+
6074+
if (parent != null && isElementAnnotatedForThisCheckerOrUpstreamChecker(parent)) {
6075+
elementAnnotatedForThisChecker = true;
6076+
}
6077+
}
6078+
6079+
elementAnnotatedFors.put(elt, elementAnnotatedForThisChecker);
6080+
6081+
return elementAnnotatedForThisChecker;
6082+
}
6083+
60386084
/**
60396085
* Get the {@code expression} field/element of the given contract annotation.
60406086
*

framework/src/main/java/org/checkerframework/framework/util/defaults/QualifierDefaults.java

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import org.checkerframework.checker.interning.qual.FindDistinct;
1616
import org.checkerframework.checker.nullness.qual.Nullable;
17-
import org.checkerframework.framework.qual.AnnotatedFor;
1817
import org.checkerframework.framework.qual.DefaultQualifier;
1918
import org.checkerframework.framework.qual.TypeUseLocation;
2019
import org.checkerframework.framework.type.AnnotatedTypeFactory;
@@ -121,9 +120,6 @@ public class QualifierDefaults {
121120
*/
122121
private final IdentityHashMap<Element, DefaultSet> elementDefaults = new IdentityHashMap<>();
123122

124-
/** A mapping of Element &rarr; Whether or not that element is AnnotatedFor this type system. */
125-
private final IdentityHashMap<Element, Boolean> elementAnnotatedFors = new IdentityHashMap<>();
126-
127123
/** CLIMB locations whose standard default is top for a given type system. */
128124
public static final List<TypeUseLocation> STANDARD_CLIMB_DEFAULTS_TOP =
129125
Collections.unmodifiableList(
@@ -642,46 +638,6 @@ private void applyDefaults(Tree tree, AnnotatedTypeMirror type) {
642638
}
643639
}
644640

645-
private boolean isElementAnnotatedForThisChecker(Element elt) {
646-
boolean elementAnnotatedForThisChecker = false;
647-
648-
if (elt == null) {
649-
throw new BugInCF(
650-
"Call of QualifierDefaults.isElementAnnotatedForThisChecker with null");
651-
}
652-
653-
if (elementAnnotatedFors.containsKey(elt)) {
654-
return elementAnnotatedFors.get(elt);
655-
}
656-
657-
AnnotationMirror annotatedFor = atypeFactory.getDeclAnnotation(elt, AnnotatedFor.class);
658-
659-
if (annotatedFor != null) {
660-
elementAnnotatedForThisChecker =
661-
atypeFactory.doesAnnotatedForApplyToThisChecker(annotatedFor);
662-
}
663-
664-
if (!elementAnnotatedForThisChecker) {
665-
Element parent;
666-
if (elt.getKind() == ElementKind.PACKAGE) {
667-
// TODO: should AnnotatedFor apply to subpackages??
668-
// elt.getEnclosingElement() on a package is null; therefore,
669-
// use the dedicated method.
670-
parent = ElementUtils.parentPackage((PackageElement) elt, elements);
671-
} else {
672-
parent = elt.getEnclosingElement();
673-
}
674-
675-
if (parent != null && isElementAnnotatedForThisChecker(parent)) {
676-
elementAnnotatedForThisChecker = true;
677-
}
678-
}
679-
680-
elementAnnotatedFors.put(elt, elementAnnotatedForThisChecker);
681-
682-
return elementAnnotatedForThisChecker;
683-
}
684-
685641
/**
686642
* Returns the defaults that apply to the given Element, considering defaults from enclosing
687643
* Elements.
@@ -810,7 +766,8 @@ public boolean applyConservativeDefaults(Element annotationScope) {
810766
&& !isFromStubFile;
811767
if (isBytecode) {
812768
return useConservativeDefaultsBytecode
813-
&& !isElementAnnotatedForThisChecker(annotationScope);
769+
&& !atypeFactory.isElementAnnotatedForThisCheckerOrUpstreamChecker(
770+
annotationScope);
814771
} else if (isFromStubFile) {
815772
// TODO: Types in stub files not annotated for a particular checker should be
816773
// treated as unchecked bytecode. For now, all types in stub files are treated as
@@ -819,7 +776,7 @@ public boolean applyConservativeDefaults(Element annotationScope) {
819776
// be treated like unchecked code except for methods in the scope of an @AnnotatedFor.
820777
return false;
821778
} else if (useConservativeDefaultsSource) {
822-
return !isElementAnnotatedForThisChecker(annotationScope);
779+
return !atypeFactory.isElementAnnotatedForThisCheckerOrUpstreamChecker(annotationScope);
823780
}
824781
return false;
825782
}

0 commit comments

Comments
 (0)