use of com.sun.source.tree.VariableTree in project checker-framework by typetools.
the class CFAbstractTransfer method addFieldValues.
private void addFieldValues(S info, AnnotatedTypeFactory factory, ClassTree classTree, MethodTree methodTree) {
// Add knowledge about final fields, or values of non-final fields
// if we are inside a constructor (information about initializers)
TypeMirror classType = TreeUtils.typeOf(classTree);
List<Pair<VariableElement, V>> fieldValues = analysis.getFieldValues();
for (Pair<VariableElement, V> p : fieldValues) {
VariableElement element = p.first;
V value = p.second;
if (ElementUtils.isFinal(element) || TreeUtils.isConstructor(methodTree)) {
Receiver receiver;
if (ElementUtils.isStatic(element)) {
receiver = new ClassName(classType);
} else {
receiver = new ThisReference(classType);
}
TypeMirror fieldType = ElementUtils.getType(element);
Receiver field = new FieldAccess(receiver, fieldType, element);
info.insertValue(field, value);
}
}
// add properties about fields (static information from type)
boolean isNotFullyInitializedReceiver = isNotFullyInitializedReceiver(methodTree);
if (isNotFullyInitializedReceiver && !TreeUtils.isConstructor(methodTree)) {
// and the method isn't a constructor
return;
}
for (Tree member : classTree.getMembers()) {
if (member instanceof VariableTree) {
VariableTree vt = (VariableTree) member;
final VariableElement element = TreeUtils.elementFromDeclaration(vt);
AnnotatedTypeMirror type = ((GenericAnnotatedTypeFactory<?, ?, ?, ?>) factory).getAnnotatedTypeLhs(vt);
TypeMirror fieldType = ElementUtils.getType(element);
Receiver receiver;
if (ElementUtils.isStatic(element)) {
receiver = new ClassName(classType);
} else {
receiver = new ThisReference(classType);
}
V value = analysis.createAbstractValue(type);
if (value == null)
continue;
if (TreeUtils.isConstructor(methodTree)) {
// if we are in a constructor,
// then we can still use the static type, but only
// if there is also an initializer that already does
// some initialization.
boolean found = false;
for (Pair<VariableElement, V> fieldValue : fieldValues) {
if (fieldValue.first.equals(element)) {
value = value.leastUpperBound(fieldValue.second);
found = true;
break;
}
}
if (!found) {
// no initializer found, cannot use static type
continue;
}
}
Receiver field = new FieldAccess(receiver, fieldType, element);
info.insertValue(field, value);
}
}
}
use of com.sun.source.tree.VariableTree 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.tree.VariableTree in project checker-framework by typetools.
the class DependentTypesHelper method checkType.
/**
* Checks all expression in the given annotated type to see if the expression string is an error
* string as specified by {@link DependentTypesError#isExpressionError}. If the annotated type
* has any errors, a flowexpr.parse.error is issued at the errorTree.
*
* @param atm annotated type to check for expression errors
* @param errorTree the tree at which to report any found errors
*/
public void checkType(AnnotatedTypeMirror atm, Tree errorTree) {
List<DependentTypesError> errors = new ExpressionErrorChecker().visit(atm);
if (errors == null || errors.isEmpty()) {
return;
}
if (errorTree.getKind() == Kind.VARIABLE) {
ModifiersTree modifiers = ((VariableTree) errorTree).getModifiers();
errorTree = ((VariableTree) errorTree).getType();
for (AnnotationTree annoTree : modifiers.getAnnotations()) {
for (Class<?> annoClazz : annoToElements.keySet()) {
if (annoTree.toString().contains(annoClazz.getSimpleName())) {
errorTree = annoTree;
break;
}
}
}
}
reportErrors(errorTree, errors);
}
use of com.sun.source.tree.VariableTree in project checker-framework by typetools.
the class TypesIntoElements method store.
/**
* The entry point.
*
* @param processingEnv the environment
* @param atypeFactory the type factory
* @param tree the ClassTree to process
*/
public static void store(ProcessingEnvironment processingEnv, AnnotatedTypeFactory atypeFactory, ClassTree tree) {
Symbol.ClassSymbol csym = (Symbol.ClassSymbol) TreeUtils.elementFromDeclaration(tree);
Types types = processingEnv.getTypeUtils();
storeTypeParameters(processingEnv, types, atypeFactory, tree.getTypeParameters(), csym);
for (Tree mem : tree.getMembers()) {
if (mem.getKind() == Tree.Kind.METHOD) {
storeMethod(processingEnv, types, atypeFactory, (MethodTree) mem);
} else if (mem.getKind() == Tree.Kind.VARIABLE) {
storeVariable(processingEnv, types, atypeFactory, (VariableTree) mem);
} else {
// System.out.println("Unhandled member tree: " + mem);
}
}
}
use of com.sun.source.tree.VariableTree in project checker-framework by typetools.
the class BaseTypeVisitor method visitMethod.
/**
* Performs pseudo-assignment check: checks that the method obeys override and subtype rules to
* all overridden methods.
*
* <p>The override rule specifies that a method, m1, may override a method m2 only if:
*
* <ul>
* <li>m1 return type is a subtype of m2
* <li>m1 receiver type is a supertype of m2
* <li>m1 parameters are supertypes of corresponding m2 parameters
* </ul>
*
* Also, it issues a "missing.this" error for static method annotated receivers.
*/
@Override
public Void visitMethod(MethodTree node, Void p) {
// We copy the result from getAnnotatedType to ensure that
// circular types (e.g. K extends Comparable<K>) are represented
// by circular AnnotatedTypeMirrors, which avoids problems with
// later checks.
// TODO: Find a cleaner way to ensure circular AnnotatedTypeMirrors.
AnnotatedExecutableType methodType = atypeFactory.getAnnotatedType(node).deepCopy();
AnnotatedDeclaredType preMRT = visitorState.getMethodReceiver();
MethodTree preMT = visitorState.getMethodTree();
visitorState.setMethodReceiver(methodType.getReceiverType());
visitorState.setMethodTree(node);
ExecutableElement methodElement = TreeUtils.elementFromDeclaration(node);
try {
if (TreeUtils.isAnonymousConstructor(node)) {
// We shouldn't dig deeper
return null;
}
// check method purity if needed
{
boolean anyPurityAnnotation = PurityUtils.hasPurityAnnotation(atypeFactory, node);
boolean checkPurityAlways = checker.hasOption("suggestPureMethods");
boolean checkPurityAnnotations = checker.hasOption("checkPurityAnnotations");
if (checkPurityAnnotations && (anyPurityAnnotation || checkPurityAlways)) {
// check "no" purity
List<Pure.Kind> kinds = PurityUtils.getPurityKinds(atypeFactory, node);
// @Deterministic makes no sense for a void method or constructor
boolean isDeterministic = kinds.contains(Pure.Kind.DETERMINISTIC);
if (isDeterministic) {
if (TreeUtils.isConstructor(node)) {
checker.report(Result.warning("purity.deterministic.constructor"), node);
} else if (TreeUtils.typeOf(node.getReturnType()).getKind() == TypeKind.VOID) {
checker.report(Result.warning("purity.deterministic.void.method"), node);
}
}
// Report errors if necessary.
PurityResult r = PurityChecker.checkPurity(atypeFactory.getPath(node.getBody()), atypeFactory, checker.hasOption("assumeSideEffectFree"));
if (!r.isPure(kinds)) {
reportPurityErrors(r, node, kinds);
}
// as such (if the feature is activated).
if (checkPurityAlways) {
Collection<Pure.Kind> additionalKinds = new HashSet<>(r.getTypes());
additionalKinds.removeAll(kinds);
if (TreeUtils.isConstructor(node)) {
additionalKinds.remove(Pure.Kind.DETERMINISTIC);
}
if (!additionalKinds.isEmpty()) {
if (additionalKinds.size() == 2) {
checker.report(Result.warning("purity.more.pure", node.getName()), node);
} else if (additionalKinds.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
checker.report(Result.warning("purity.more.sideeffectfree", node.getName()), node);
} else if (additionalKinds.contains(Pure.Kind.DETERMINISTIC)) {
checker.report(Result.warning("purity.more.deterministic", node.getName()), node);
} else {
assert false : "BaseTypeVisitor reached undesirable state";
}
}
}
}
}
// Passing the whole method/constructor validates the return type
validateTypeOf(node);
// Validate types in throws clauses
for (ExpressionTree thr : node.getThrows()) {
validateTypeOf(thr);
}
if (atypeFactory.getDependentTypesHelper() != null) {
atypeFactory.getDependentTypesHelper().checkMethod(node, methodType);
}
AnnotatedDeclaredType enclosingType = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(methodElement.getEnclosingElement());
// Find which method this overrides!
Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(elements, atypeFactory, methodElement);
for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
AnnotatedDeclaredType overriddenType = pair.getKey();
AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(types, atypeFactory, overriddenType, pair.getValue());
if (!checkOverride(node, enclosingType, overriddenMethod, overriddenType)) {
// the same method, not adding any value. See Issue 373.
break;
}
}
return super.visitMethod(node, p);
} finally {
boolean abstractMethod = methodElement.getModifiers().contains(Modifier.ABSTRACT) || methodElement.getModifiers().contains(Modifier.NATIVE);
// check well-formedness of pre/postcondition
List<String> formalParamNames = new ArrayList<>();
for (VariableTree param : node.getParameters()) {
formalParamNames.add(param.getName().toString());
}
checkContractsAtMethodDeclaration(node, methodElement, formalParamNames, abstractMethod);
visitorState.setMethodReceiver(preMRT);
visitorState.setMethodTree(preMT);
}
}
Aggregations