use of com.sun.source.tree.AnnotationTree in project error-prone by google.
the class NullableVoid method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
MethodSymbol sym = ASTHelpers.getSymbol(tree);
if (sym == null) {
return NO_MATCH;
}
if (sym.getReturnType().getKind() != TypeKind.VOID) {
return NO_MATCH;
}
AnnotationTree annotation = ASTHelpers.getAnnotationWithSimpleName(tree.getModifiers().getAnnotations(), "Nullable");
if (annotation == null) {
return NO_MATCH;
}
return describeMatch(annotation, SuggestedFix.delete(annotation));
}
use of com.sun.source.tree.AnnotationTree in project checker-framework by typetools.
the class BaseTypeVisitor method warnAboutTypeAnnotationsTooEarly.
/**
* Warn if a type annotation is written before a modifier such as "public" or before a declaration
* annotation.
*
* @param node a VariableTree or a MethodTree
* @param modifiersTree the modifiers sub-tree of node
*/
private void warnAboutTypeAnnotationsTooEarly(Tree node, ModifiersTree modifiersTree) {
// the effort to do so.
if (node.getKind() == Tree.Kind.VARIABLE) {
ElementKind varKind = TreeUtils.elementFromDeclaration((VariableTree) node).getKind();
switch(varKind) {
case ENUM_CONSTANT:
// appears to be before "public".
return;
case RESOURCE_VARIABLE:
// appears to be before "final".
return;
default:
if (TreeUtils.isAutoGeneratedRecordMember(node)) {
// a warning about those.
return;
}
}
}
Set<Modifier> modifierSet = modifiersTree.getFlags();
List<? extends AnnotationTree> annotations = modifiersTree.getAnnotations();
if (annotations.isEmpty()) {
return;
}
// Warn about type annotations written before modifiers such as "public". javac retains no
// information about modifier locations. So, this is a very partial check: Issue a warning if
// a type annotation is at the very beginning of the VariableTree, and a modifier follows it.
// Check if a type annotation precedes a declaration annotation.
int lastDeclAnnoIndex = -1;
for (int i = annotations.size() - 1; i > 0; i--) {
// no need to check index 0
if (!isTypeAnnotation(annotations.get(i))) {
lastDeclAnnoIndex = i;
break;
}
}
if (lastDeclAnnoIndex != -1) {
List<AnnotationTree> badTypeAnnos = new ArrayList<>();
for (int i = 0; i < lastDeclAnnoIndex; i++) {
AnnotationTree anno = annotations.get(i);
if (isTypeAnnotation(anno)) {
badTypeAnnos.add(anno);
}
}
if (!badTypeAnnos.isEmpty()) {
checker.reportWarning(node, "type.anno.before.decl.anno", badTypeAnnos, annotations.get(lastDeclAnnoIndex));
}
}
// Determine the length of the text that ought to precede the first type annotation.
// If the type annotation appears before that text could appear, then warn that a
// modifier appears after the type annotation.
// TODO: in the future, account for the lengths of declaration annotations. Length of toString
// of the annotation isn't useful, as it might be different length than original input. Can use
// JCTree.getEndPosition(EndPosTable) and com.sun.tools.javac.tree.EndPosTable, but it requires
// -Xjcov.
AnnotationTree firstAnno = annotations.get(0);
if (!modifierSet.isEmpty() && isTypeAnnotation(firstAnno)) {
int precedingTextLength = 0;
for (Modifier m : modifierSet) {
// +1 for the space
precedingTextLength += m.toString().length() + 1;
}
int annoStartPos = ((JCTree) firstAnno).getStartPosition();
int varStartPos = ((JCTree) node).getStartPosition();
if (annoStartPos < varStartPos + precedingTextLength) {
checker.reportWarning(node, "type.anno.before.modifier", firstAnno, modifierSet);
}
}
}
use of com.sun.source.tree.AnnotationTree in project checker-framework by typetools.
the class NullnessVisitor method processClassTree.
@Override
public void processClassTree(ClassTree classTree) {
Tree extendsClause = classTree.getExtendsClause();
if (extendsClause != null) {
reportErrorIfSupertypeContainsNullnessAnnotation(extendsClause);
}
for (Tree implementsClause : classTree.getImplementsClause()) {
reportErrorIfSupertypeContainsNullnessAnnotation(implementsClause);
}
if (classTree.getKind() == Tree.Kind.ENUM) {
for (Tree member : classTree.getMembers()) {
if (member.getKind() == Tree.Kind.VARIABLE && TreeUtils.elementFromDeclaration((VariableTree) member).getKind() == ElementKind.ENUM_CONSTANT) {
VariableTree varDecl = (VariableTree) member;
List<? extends AnnotationTree> annoTrees = varDecl.getModifiers().getAnnotations();
Tree type = varDecl.getType();
if (atypeFactory.containsNullnessAnnotation(annoTrees, type)) {
checker.reportError(member, "nullness.on.enum");
}
}
}
}
super.processClassTree(classTree);
}
use of com.sun.source.tree.AnnotationTree in project checker-framework by typetools.
the class NullnessVisitor method checkExceptionParameter.
@Override
protected void checkExceptionParameter(CatchTree node) {
VariableTree param = node.getParameter();
List<? extends AnnotationTree> annoTrees = param.getModifiers().getAnnotations();
Tree paramType = param.getType();
if (atypeFactory.containsNullnessAnnotation(annoTrees, paramType)) {
// This is a warning rather than an error because writing `@Nullable` could make sense
// if the catch block re-assigns the variable to null. (That would be bad style.)
checker.reportWarning(param, "nullness.on.exception.parameter");
}
// Don't call super.
// BasetypeVisitor forces annotations on exception parameters to be top, but because exceptions
// can never be null, the Nullness Checker does not require this check.
}
use of com.sun.source.tree.AnnotationTree in project checker-framework by typetools.
the class AnnotatedTypeFactory method fromNewClass.
/**
* Creates an AnnotatedDeclaredType for a NewClassTree. Only adds explicit annotations, unless
* newClassTree has a diamond operator. In that case, the annotations on the type arguments are
* inferred using the assignment context and contain defaults.
*
* <p>Also, fully annotates the enclosing type of the returned declared type.
*
* <p>(Subclass beside {@link GenericAnnotatedTypeFactory} should not override this method.)
*
* @param newClassTree NewClassTree
* @return AnnotatedDeclaredType
*/
public AnnotatedDeclaredType fromNewClass(NewClassTree newClassTree) {
AnnotatedDeclaredType enclosingType = (AnnotatedDeclaredType) getReceiverType(newClassTree);
// Diamond trees that are not anonymous classes.
if (TreeUtils.isDiamondTree(newClassTree) && newClassTree.getClassBody() == null) {
AnnotatedDeclaredType type = (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
if (((com.sun.tools.javac.code.Type) type.underlyingType).tsym.getTypeParameters().nonEmpty()) {
TreePath p = getPath(newClassTree);
AnnotatedTypeMirror ctxtype = TypeArgInferenceUtil.assignedTo(this, p);
if (ctxtype != null) {
fromNewClassContextHelper(type, ctxtype);
} else {
// give up trying and set to raw.
type.setIsUnderlyingTypeRaw();
}
}
AnnotatedDeclaredType fromTypeTree = (AnnotatedDeclaredType) TypeFromTree.fromTypeTree(this, newClassTree.getIdentifier());
type.replaceAnnotations(fromTypeTree.getAnnotations());
type.setEnclosingType(enclosingType);
return type;
} else if (newClassTree.getClassBody() != null) {
AnnotatedDeclaredType type = (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
// In Java 11 and lower, if newClassTree creates an anonymous class, then annotations in this
// location:
// new @HERE Class() {}
// are on not on the identifier newClassTree, but rather on the modifier newClassTree.
List<? extends AnnotationTree> annos = newClassTree.getClassBody().getModifiers().getAnnotations();
type.addAnnotations(TreeUtils.annotationsFromTypeAnnotationTrees(annos));
// In Java 17+, the annotations are on the identifier, so copy them.
AnnotatedDeclaredType identifierType = (AnnotatedDeclaredType) TypeFromTree.fromTypeTree(this, newClassTree.getIdentifier());
type.addAnnotations(identifierType.getAnnotations());
type.setEnclosingType(enclosingType);
return type;
} else {
// If newClassTree does not create an anonymous class (or if this is Java 17+),
// newClassTree.getIdentifier includes the explicit annotations in this location:
// new @HERE Class()
AnnotatedDeclaredType type = (AnnotatedDeclaredType) TypeFromTree.fromTypeTree(this, newClassTree.getIdentifier());
type.setEnclosingType(enclosingType);
return type;
}
}
Aggregations