use of com.sun.source.util.TreePath in project checker-framework by typetools.
the class CFAbstractTransfer method addInformationFromPreconditions.
/**
* Add the information from all the preconditions of the method {@code method} with
* corresponding tree {@code methodTree} to the store {@code info}.
*/
protected void addInformationFromPreconditions(S info, AnnotatedTypeFactory factory, CFGMethod method, MethodTree methodTree, ExecutableElement methodElement) {
ContractsUtils contracts = ContractsUtils.getInstance(analysis.atypeFactory);
FlowExpressionContext flowExprContext = null;
Set<Precondition> preconditions = contracts.getPreconditions(methodElement);
for (Precondition p : preconditions) {
String expression = p.expression;
AnnotationMirror annotation = p.annotation;
if (flowExprContext == null) {
flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, method.getClassTree(), analysis.checker.getContext());
}
TreePath localScope = analysis.atypeFactory.getPath(methodTree);
annotation = standardizeAnnotationFromContract(annotation, flowExprContext, localScope);
try {
// TODO: currently, these expressions are parsed at the
// declaration (i.e. here) and for every use. this could
// be optimized to store the result the first time.
// (same for other annotations)
FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, localScope, false);
info.insertValue(expr, annotation);
} catch (FlowExpressionParseException e) {
// Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration()
}
}
}
use of com.sun.source.util.TreePath in project checker-framework by typetools.
the class CFAbstractTransfer method initialStore.
/**
* The initial store maps method formal parameters to their currently most refined type.
*/
@Override
public S initialStore(UnderlyingAST underlyingAST, @Nullable List<LocalVariableNode> parameters) {
if (fixedInitialStore != null && underlyingAST.getKind() != Kind.LAMBDA && underlyingAST.getKind() != Kind.METHOD) {
return fixedInitialStore;
}
S info = analysis.createEmptyStore(sequentialSemantics);
if (underlyingAST.getKind() == Kind.METHOD) {
if (fixedInitialStore != null) {
// copy knowledge
info = analysis.createCopiedStore(fixedInitialStore);
}
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
// add properties known through precondition
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodTree = method.getMethod();
ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodTree);
addInformationFromPreconditions(info, factory, method, methodTree, methodElem);
final ClassTree classTree = method.getClassTree();
addFieldValues(info, factory, classTree, methodTree);
addFinalLocalValues(info, methodElem);
if (shouldPerformWholeProgramInference(methodTree, methodElem)) {
Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(analysis.atypeFactory.getElementUtils(), analysis.atypeFactory, methodElem);
for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(analysis.atypeFactory.getProcessingEnv().getTypeUtils(), analysis.atypeFactory, pair.getKey(), pair.getValue());
// Infers parameter and receiver types of the method based
// on the overridden method.
analysis.atypeFactory.getWholeProgramInference().updateInferredMethodParameterTypes(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
analysis.atypeFactory.getWholeProgramInference().updateInferredMethodReceiverType(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
}
}
return info;
} else if (underlyingAST.getKind() == Kind.LAMBDA) {
// Create a copy and keep only the field values (nothing else applies).
info = analysis.createCopiedStore(fixedInitialStore);
info.localVariableValues.clear();
info.classValues.clear();
info.arrayValues.clear();
info.methodValues.clear();
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
CFGLambda lambda = (CFGLambda) underlyingAST;
Tree enclosingTree = TreeUtils.enclosingOfKind(factory.getPath(lambda.getLambdaTree()), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, // Tree.Kind for which TreeUtils.isClassTree is true
Tree.Kind.CLASS, Tree.Kind.INTERFACE, Tree.Kind.ANNOTATION_TYPE, Tree.Kind.ENUM)));
Element enclosingElement = null;
if (enclosingTree.getKind() == Tree.Kind.METHOD) {
// If it is in an initializer, we need to use locals from the initializer.
enclosingElement = TreeUtils.elementFromTree(enclosingTree);
} else if (TreeUtils.isClassTree(enclosingTree)) {
// Try to find an enclosing initializer block
// Would love to know if there was a better way
// Find any enclosing element of the lambda (using trees)
// Then go up the elements to find an initializer element (which can't be found with
// the tree).
TreePath loopTree = factory.getPath(lambda.getLambdaTree()).getParentPath();
Element anEnclosingElement = null;
while (loopTree.getLeaf() != enclosingTree) {
Element sym = TreeUtils.elementFromTree(loopTree.getLeaf());
if (sym != null) {
anEnclosingElement = sym;
break;
}
loopTree = loopTree.getParentPath();
}
while (anEnclosingElement != null && !anEnclosingElement.equals(TreeUtils.elementFromTree(enclosingTree))) {
if (anEnclosingElement.getKind() == ElementKind.INSTANCE_INIT || anEnclosingElement.getKind() == ElementKind.STATIC_INIT) {
enclosingElement = anEnclosingElement;
break;
}
anEnclosingElement = anEnclosingElement.getEnclosingElement();
}
}
if (enclosingElement != null) {
addFinalLocalValues(info, enclosingElement);
}
// We want the initialization stuff, but need to throw out any refinements.
Map<FieldAccess, V> fieldValuesClone = new HashMap<>(info.fieldValues);
for (Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
info.fieldValues.put(fieldValue.getKey(), lubbedValue);
}
}
return info;
}
use of com.sun.source.util.TreePath in project checker-framework by typetools.
the class SourceChecker method shouldSuppressWarnings.
/**
* Determines whether all the warnings pertaining to a given tree should be suppressed. Returns
* true if the tree is within the scope of a @SuppressWarnings annotation, one of whose values
* suppresses the checker's warnings. The list of keys that suppress a checker's warnings is
* provided by the {@link SourceChecker#getSuppressWarningsKeys} method.
*
* @param tree the tree that might be a source of a warning
* @param errKey the error key the checker is emitting
* @return true if no warning should be emitted for the given tree because it is contained by a
* declaration with an appropriately-valued {@literal @}SuppressWarnings annotation; false
* otherwise
*/
// Public so it can be called from a few places in
// org.checkerframework.framework.flow.CFAbstractTransfer
public boolean shouldSuppressWarnings(Tree tree, String errKey) {
// Don't suppress warnings if this checker provides no key to do so.
Collection<String> checkerKeys = this.getSuppressWarningsKeys();
if (checkerKeys.isEmpty()) {
return false;
}
// trees.getPath might be slow, but this is only used in error reporting
// TODO: #1586 this might return null within a cloned finally block and
// then a warning that should be suppressed isn't. Fix this when fixing #1586.
@Nullable TreePath path = trees.getPath(this.currentRoot, tree);
if (path == null) {
return false;
}
@Nullable VariableTree var = TreeUtils.enclosingVariable(path);
if (var != null && shouldSuppressWarnings(TreeUtils.elementFromTree(var), errKey)) {
return true;
}
@Nullable MethodTree method = TreeUtils.enclosingMethod(path);
if (method != null) {
@Nullable Element elt = TreeUtils.elementFromTree(method);
if (shouldSuppressWarnings(elt, errKey)) {
return true;
}
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
// @AnnotatedFor.
return false;
}
}
@Nullable ClassTree cls = TreeUtils.enclosingClass(path);
if (cls != null) {
@Nullable Element elt = TreeUtils.elementFromTree(cls);
if (shouldSuppressWarnings(elt, errKey)) {
return true;
}
if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
// @AnnotatedFor.
return false;
}
}
if (useUncheckedCodeDefault("source")) {
// false, we DO suppress the warning.
return true;
}
return false;
}
use of com.sun.source.util.TreePath in project checker-framework by typetools.
the class QualifierDefaults method getTypeVarBoundType.
/**
* @return the boundType (UPPER or UNBOUNDED) of the declaration of typeParamElem
*/
// Results are cached in {@link elementToBoundType}.
private static BoundType getTypeVarBoundType(final TypeParameterElement typeParamElem, final AnnotatedTypeFactory typeFactory) {
final BoundType prev = elementToBoundType.get(typeParamElem);
if (prev != null) {
return prev;
}
TreePath declaredTypeVarEle = typeFactory.getTreeUtils().getPath(typeParamElem);
Tree typeParamDecl = declaredTypeVarEle == null ? null : declaredTypeVarEle.getLeaf();
final BoundType boundType;
if (typeParamDecl == null) {
// when the compilation unit is no-longer available.
if (typeParamElem.getBounds().size() == 1 && TypesUtils.isObject(typeParamElem.getBounds().get(0))) {
// If the bound was Object, then it may or may not have been explicitly written.
// Assume that it was not.
boundType = BoundType.UNBOUNDED;
} else {
// The bound is not Object, so it must have been explicitly written and thus the
// type variable has an upper bound.
boundType = BoundType.UPPER;
}
} else {
if (typeParamDecl.getKind() == Tree.Kind.TYPE_PARAMETER) {
final TypeParameterTree tptree = (TypeParameterTree) typeParamDecl;
List<? extends Tree> bnds = tptree.getBounds();
if (bnds != null && !bnds.isEmpty()) {
boundType = BoundType.UPPER;
} else {
boundType = BoundType.UNBOUNDED;
}
} else {
ErrorReporter.errorAbort("Unexpected tree type for typeVar Element:\n" + "typeParamElem=" + typeParamElem + "\n" + typeParamDecl);
// dead code
boundType = null;
}
}
elementToBoundType.put(typeParamElem, boundType);
return boundType;
}
use of com.sun.source.util.TreePath in project checker-framework by typetools.
the class DefaultTypeArgumentInference method inferTypeArgs.
@Override
public Map<TypeVariable, AnnotatedTypeMirror> inferTypeArgs(AnnotatedTypeFactory typeFactory, ExpressionTree expressionTree, ExecutableElement methodElem, AnnotatedExecutableType methodType) {
final List<AnnotatedTypeMirror> argTypes = TypeArgInferenceUtil.getArgumentTypes(expressionTree, typeFactory);
final TreePath pathToExpression = typeFactory.getPath(expressionTree);
assert pathToExpression != null;
final AnnotatedTypeMirror assignedTo = TypeArgInferenceUtil.assignedTo(typeFactory, pathToExpression);
SourceChecker checker = typeFactory.getContext().getChecker();
if (showInferenceSteps) {
checker.message(Kind.NOTE, "DTAI: expression: %s\n argTypes: %s\n assignedTo: %s\n", expressionTree.toString().replace("\n", " "), argTypes, assignedTo);
}
final Set<TypeVariable> targets = TypeArgInferenceUtil.methodTypeToTargets(methodType);
if (assignedTo == null && TreeUtils.getAssignmentContext(pathToExpression) != null) {
// If the type of the assignment context isn't found, but the expression is assigned,
// then don't attempt to infere type arguments, because the Java type inferred will be
// incorrect. The assignment type is null when it includes uninferred type arguments.
// For example:
// <T> T outMethod()
// <U> void inMethod(U u);
// inMethod(outMethod())
// would require solving the constraints for both type argument inferences
// simultaneously
Map<TypeVariable, AnnotatedTypeMirror> inferredArgs = new LinkedHashMap<>();
handleUninferredTypeVariables(typeFactory, methodType, targets, inferredArgs);
return inferredArgs;
}
Map<TypeVariable, AnnotatedTypeMirror> inferredArgs;
try {
inferredArgs = infer(typeFactory, argTypes, assignedTo, methodElem, methodType, targets, true);
if (showInferenceSteps) {
checker.message(Kind.NOTE, " after infer: %s\n", inferredArgs);
}
handleNullTypeArguments(typeFactory, methodElem, methodType, argTypes, assignedTo, targets, inferredArgs);
if (showInferenceSteps) {
checker.message(Kind.NOTE, " after handleNull: %s\n", inferredArgs);
}
} catch (Exception ex) {
// Catch any errors thrown by inference.
inferredArgs = new LinkedHashMap<>();
if (showInferenceSteps) {
checker.message(Kind.NOTE, " exception: %s\n", ex.getLocalizedMessage());
}
}
handleUninferredTypeVariables(typeFactory, methodType, targets, inferredArgs);
if (showInferenceSteps) {
checker.message(Kind.NOTE, " results: %s\n", inferredArgs);
}
return inferredArgs;
}
Aggregations