diff --git a/checker/src/main/java/org/checkerframework/checker/index/lowerbound/LowerBoundAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/index/lowerbound/LowerBoundAnnotatedTypeFactory.java index add0f7f2250..b799608322d 100644 --- a/checker/src/main/java/org/checkerframework/checker/index/lowerbound/LowerBoundAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/index/lowerbound/LowerBoundAnnotatedTypeFactory.java @@ -190,8 +190,8 @@ public void addComputedTypeAnnotations(Element element, AnnotatedTypeMirror type /** Handles cases 1, 2, and 3. */ @Override - public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) { - super.addComputedTypeAnnotations(tree, type, iUseFlow); + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { + super.addComputedTypeAnnotations(tree, type); // If dataflow shouldn't be used to compute this type, then do not use the result from // the Value Checker, because dataflow is used to compute that type. (Without this, // "int i = 1; --i;" fails.) @@ -203,7 +203,7 @@ public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, bool // checker's type factory is parsing. && !ajavaTypes.isParsing() && TreeUtils.isExpressionTree(tree) - && (iUseFlow || tree instanceof LiteralTree)) { + && (getUseFlow() || tree instanceof LiteralTree)) { AnnotatedTypeMirror valueType = getValueAnnotatedTypeFactory().getAnnotatedType(tree); addLowerBoundTypeFromValueType(valueType, type); } diff --git a/checker/src/main/java/org/checkerframework/checker/index/upperbound/UpperBoundAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/index/upperbound/UpperBoundAnnotatedTypeFactory.java index ed90a94a4d4..5eaba43cee8 100644 --- a/checker/src/main/java/org/checkerframework/checker/index/upperbound/UpperBoundAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/index/upperbound/UpperBoundAnnotatedTypeFactory.java @@ -255,12 +255,12 @@ public void addComputedTypeAnnotations(Element element, AnnotatedTypeMirror type } @Override - public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) { - super.addComputedTypeAnnotations(tree, type, iUseFlow); + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { + super.addComputedTypeAnnotations(tree, type); // If dataflow shouldn't be used to compute this type, then do not use the result from // the Value Checker, because dataflow is used to compute that type. (Without this, // "int i = 1; --i;" fails.) - if (iUseFlow + if (getUseFlow() && tree != null && !ajavaTypes.isParsing() && TreeUtils.isExpressionTree(tree)) { diff --git a/checker/src/main/java/org/checkerframework/checker/lock/LockAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/lock/LockAnnotatedTypeFactory.java index c855abfce41..43c8882a3ed 100644 --- a/checker/src/main/java/org/checkerframework/checker/lock/LockAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/lock/LockAnnotatedTypeFactory.java @@ -699,13 +699,13 @@ public void addComputedTypeAnnotations(Element elt, AnnotatedTypeMirror type) { } @Override - public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean useFlow) { + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { if (tree.getKind() == Tree.Kind.VARIABLE) { translateJcipAndJavaxAnnotations( TreeUtils.elementFromDeclaration((VariableTree) tree), type); } - super.addComputedTypeAnnotations(tree, type, useFlow); + super.addComputedTypeAnnotations(tree, type); } /** diff --git a/checker/src/main/java/org/checkerframework/checker/signedness/SignednessAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/signedness/SignednessAnnotatedTypeFactory.java index 71f29f5183d..b3b189cc238 100644 --- a/checker/src/main/java/org/checkerframework/checker/signedness/SignednessAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/signedness/SignednessAnnotatedTypeFactory.java @@ -119,8 +119,7 @@ public SignednessAnnotatedTypeFactory(BaseTypeChecker checker) { } @Override - protected void addComputedTypeAnnotations( - Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) { + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { Tree.Kind treeKind = tree.getKind(); if (treeKind == Tree.Kind.INT_LITERAL) { int literalValue = (int) ((LiteralTree) tree).getValue(); @@ -139,8 +138,7 @@ protected void addComputedTypeAnnotations( } else if (!isComputingAnnotatedTypeMirrorOfLhs()) { addSignedPositiveAnnotation(tree, type); } - - super.addComputedTypeAnnotations(tree, type, iUseFlow); + super.addComputedTypeAnnotations(tree, type); } /** diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index bc91e7f2d35..901a2274279 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -5,6 +5,11 @@ Version 3.42.0-eisop4 (April ?, 2024) **Implementation details:** +New method `GenericAnnotatedTypeFactory#addComputedTypeAnnotationsWithoutFlow(Tree, AnnotatedTypeMirror)` that sets +`useFlow` to `false` before calling `addComputedTypeAnnotations`. Subclasses should override method +`GenericAnnotatedTypeFactory#addComputedTypeAnnotations(Tree, AnnotatedTypeMirror)` instead. +Deprecated the `GenericAnnotatedTypeFactory#addComputedTypeAnnotations(Tree, AnnotatedTypeMirror, boolean)` overload. + Improvements in `framework-test` to more consistently handle tests that do not use `-Anomsgtext`. diff --git a/docs/manual/creating-a-checker.tex b/docs/manual/creating-a-checker.tex index 6378a255ddc..ad0e067cddd 100644 --- a/docs/manual/creating-a-checker.tex +++ b/docs/manual/creating-a-checker.tex @@ -1356,9 +1356,8 @@ Create a subclass of \refclass{framework/type}{AnnotatedTypeFactory} and override two \ methods: \refmethodanchortext{framework/type}{AnnotatedTypeFactory}{addComputedTypeAnnotations}{(com.sun.source.tree.Tree,org.checkerframework.framework.type.AnnotatedTypeMirror)}{addComputedTypeAnnotations(Tree,AnnotatedTypeMirror)} - (or - \refmethodanchortext{framework/type}{GenericAnnotatedTypeFactory}{addComputedTypeAnnotations}{(com.sun.source.tree.Tree,org.checkerframework.framework.type.AnnotatedTypeMirror,boolean)}{addComputedTypeAnnotations(Tree,AnnotatedTypeMirror,boolean)} - if extending \code{GenericAnnotatedTypeFactory}) + (use \refmethodanchortext{framework/type}{GenericAnnotatedTypeFactory}{addComputedTypeAnnotationsWithoutFlow}{(com.sun.source.tree.Tree,org.checkerframework.framework.type.AnnotatedTypeMirror)}{addComputedTypeAnnotationsWithoutFlow(Tree,AnnotatedTypeMirror)} + in subclasses of \code{GenericAnnotatedTypeFactory} if you want to add computed type annotations to a type without using flow information.) and \refmethodanchortext{framework/type}{AnnotatedTypeFactory}{addComputedTypeAnnotations}{(javax.lang.model.element.Element,org.checkerframework.framework.type.AnnotatedTypeMirror)}{addComputedTypeAnnotations(Element,AnnotatedTypeMirror)}. The methods can make arbitrary changes to the annotations on a type. diff --git a/framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java b/framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java index dfe1f490c04..228df9f8942 100644 --- a/framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java +++ b/framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java @@ -1901,10 +1901,6 @@ private AnnotatedTypeMirror fromExpression(ExpressionTree tree) { *

Subclasses that override this method should also override {@link * #addComputedTypeAnnotations(Element, AnnotatedTypeMirror)}. * - *

In classes that extend {@link GenericAnnotatedTypeFactory}, override {@link - * GenericAnnotatedTypeFactory#addComputedTypeAnnotations(Tree, AnnotatedTypeMirror, boolean)} - * instead of this method. - * * @param tree an AST node * @param type the type obtained from {@code tree} */ diff --git a/framework/src/main/java/org/checkerframework/framework/type/GenericAnnotatedTypeFactory.java b/framework/src/main/java/org/checkerframework/framework/type/GenericAnnotatedTypeFactory.java index 2cc4b440dac..30a1b59ed29 100644 --- a/framework/src/main/java/org/checkerframework/framework/type/GenericAnnotatedTypeFactory.java +++ b/framework/src/main/java/org/checkerframework/framework/type/GenericAnnotatedTypeFactory.java @@ -399,6 +399,16 @@ protected GenericAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFlow) // all other initialization is finished. } + /** + * Determines whether flow-sensitive type refinement should be used or not. + * + * @return whether flow-sensitive type refinement should be used or not + * @see #useFlow + */ + protected boolean getUseFlow() { + return useFlow; + } + @Override protected void postInit( @UnderInitialization(GenericAnnotatedTypeFactory.class) GenericAnnotatedTypeFactory @@ -1981,17 +1991,6 @@ public void addDefaultAnnotations(AnnotatedTypeMirror type) { defaults.annotate((Element) null, type); } - /** - * This method is final; override {@link #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror, - * boolean)} instead. - * - *

{@inheritDoc} - */ - @Override - protected final void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { - addComputedTypeAnnotations(tree, type, this.useFlow); - } - /** * Removes all primary annotations on a copy of the type and calculates the default annotations * that apply to the copied type, without type refinements. @@ -2003,7 +2002,7 @@ protected final void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror t public AnnotatedTypeMirror getDefaultAnnotations(Tree tree, AnnotatedTypeMirror type) { AnnotatedTypeMirror copy = type.deepCopy(); copy.removeAnnotations(type.getAnnotations()); - addComputedTypeAnnotations(tree, copy, false); + addComputedTypeAnnotationsWithoutFlow(tree, copy); return copy; } @@ -2014,9 +2013,44 @@ public AnnotatedTypeMirror getDefaultAnnotations(Tree tree, AnnotatedTypeMirror * @param tree an AST node * @param type the type obtained from tree * @param iUseFlow whether to use information from dataflow analysis + * @deprecated use {@link #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror)} or {@link + * #addComputedTypeAnnotationsWithoutFlow(Tree, AnnotatedTypeMirror)} if you want to add + * computed type annotations without using flow information */ + @Deprecated // 2024-07-07 + @SuppressWarnings("unused") protected void addComputedTypeAnnotations( Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) { + addComputedTypeAnnotationsWithoutFlow(tree, type); + } + + /** + * A helper method to add computed type annotations to a type without using flow information. + * + *

This method is final; override {@link #addComputedTypeAnnotations(Tree, + * AnnotatedTypeMirror)} instead. + * + * @param tree an AST node + * @param type the type obtained from tree + * @see #addComputedTypeAnnotations(Tree, AnnotatedTypeMirror) + */ + protected final void addComputedTypeAnnotationsWithoutFlow( + Tree tree, AnnotatedTypeMirror type) { + boolean oldUseflow = useFlow; + useFlow = false; + addComputedTypeAnnotations(tree, type); + useFlow = oldUseflow; + } + + /** + * {@inheritDoc} + * + *

This method adds defaults and flow-sensitive type refinements. + * + * @see #addComputedTypeAnnotationsWithoutFlow(Tree, AnnotatedTypeMirror) + */ + @Override + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { if (this.getRoot() == null && ajavaTypes.isParsing()) { return; } @@ -2038,7 +2072,7 @@ protected void addComputedTypeAnnotations( } log( "%s GATF.addComputedTypeAnnotations#1(%s, %s, %s)%n", - thisClass, treeString, type, iUseFlow); + thisClass, treeString, type, this.useFlow); if (!TreeUtils.isExpressionTree(tree)) { // Don't apply defaults to expressions. Their types may be computed from subexpressions // in treeAnnotator. @@ -2063,7 +2097,7 @@ protected void addComputedTypeAnnotations( defaults.annotate(tree, type); log("%s GATF.addComputedTypeAnnotations#7(%s, %s)%n", thisClass, treeString, type); - if (iUseFlow) { + if (this.useFlow) { Value inferred = getInferredValueFor(tree); if (inferred != null) { applyInferredAnnotations(type, inferred); @@ -2074,7 +2108,7 @@ protected void addComputedTypeAnnotations( } log( "%s GATF.addComputedTypeAnnotations#9(%s, %s, %s) done%n", - thisClass, treeString, type, iUseFlow); + thisClass, treeString, type, this.useFlow); } /** @@ -2745,7 +2779,7 @@ public AnnotatedTypeMirror getDefaultValueAnnotatedType(TypeMirror typeMirror) { TypeMirror defaultValueTM = TreeUtils.typeOf(defaultValueTree); AnnotatedTypeMirror defaultValueATM = AnnotatedTypeMirror.createType(defaultValueTM, this, false); - addComputedTypeAnnotations(defaultValueTree, defaultValueATM, false); + addComputedTypeAnnotationsWithoutFlow(defaultValueTree, defaultValueATM); return defaultValueATM; } diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java index 3d0580b04f8..8f33b5378dd 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java @@ -58,9 +58,8 @@ protected Set> createSupportedTypeQualifiers() { } @Override - protected void addComputedTypeAnnotations( - Tree tree, AnnotatedTypeMirror type, boolean iUseFlow) { - super.addComputedTypeAnnotations(tree, type, iUseFlow); + protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type) { + super.addComputedTypeAnnotations(tree, type); if (tree.getKind() == Tree.Kind.VARIABLE && ((VariableTree) tree).getName().toString().contains("addH1S2")) { type.replaceAnnotation(H1S2);