use of com.sun.source.tree.AssignmentTree in project checker-framework by typetools.
the class BaseTypeVisitor method isAccessAllowed.
protected boolean isAccessAllowed(Element field, AnnotatedTypeMirror receiver, ExpressionTree accessTree) {
AnnotationMirror unused = atypeFactory.getDeclAnnotation(field, Unused.class);
if (unused == null) {
return true;
}
String when = AnnotationUtils.getElementValueClassName(unused, "when", false).toString();
if (!AnnotationUtils.containsSameByName(receiver.getAnnotations(), when)) {
return true;
}
Tree tree = this.enclosingStatement(accessTree);
// assigning unused to null is OK
return (tree != null && tree.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) tree).getVariable() == accessTree && ((AssignmentTree) tree).getExpression().getKind() == Tree.Kind.NULL_LITERAL);
}
use of com.sun.source.tree.AssignmentTree in project error-prone by google.
the class StringSplitter method buildFix.
public Optional<Fix> buildFix(MethodInvocationTree tree, VisitorState state) {
Tree arg = getOnlyElement(tree.getArguments());
String value = ASTHelpers.constValue(arg, String.class);
boolean maybeRegex = false;
if (value != null) {
Optional<String> regexAsLiteral = convertRegexToLiteral(value);
if (regexAsLiteral.isPresent()) {
value = SourceCodeEscapers.javaCharEscaper().escape(regexAsLiteral.get());
if (value.length() == 1) {
value = String.format("'%s'", value.charAt(0));
} else {
value = String.format("\"%s\"", value);
}
} else {
maybeRegex = true;
value = state.getSourceForNode(arg);
}
} else {
value = state.getSourceForNode(arg);
}
Tree parent = state.getPath().getParentPath().getLeaf();
if (parent instanceof EnhancedForLoopTree && ((EnhancedForLoopTree) parent).getExpression().equals(tree)) {
// fix for `for (... : s.split(...)) {}` -> `for (... : Splitter.on(...).split(s)) {}`
return Optional.of(replaceWithSplitter(SuggestedFix.builder(), tree, value, state, "split", maybeRegex, /* mutableList= */
false).build());
}
if (parent instanceof ArrayAccessTree) {
ArrayAccessTree arrayAccessTree = (ArrayAccessTree) parent;
if (!arrayAccessTree.getExpression().equals(tree)) {
return Optional.empty();
}
SuggestedFix.Builder fix = SuggestedFix.builder().addImport("com.google.common.collect.Iterables").replace(((JCTree) arrayAccessTree).getStartPosition(), ((JCTree) arrayAccessTree).getStartPosition(), "Iterables.get(").replace(/* startPos= */
state.getEndPosition(arrayAccessTree.getExpression()), /* endPos= */
((JCTree) arrayAccessTree.getIndex()).getStartPosition(), String.format(", ")).replace(state.getEndPosition(arrayAccessTree.getIndex()), state.getEndPosition(arrayAccessTree), ")");
return Optional.of(replaceWithSplitter(fix, tree, value, state, "split", maybeRegex, /* mutableList= */
false).build());
}
// enclosing method. If we don't know how to fix any of them, bail out.
if (!(parent instanceof VariableTree)) {
return Optional.empty();
}
VariableTree varTree = (VariableTree) parent;
if (!varTree.getInitializer().equals(tree)) {
return Optional.empty();
}
VarSymbol sym = ASTHelpers.getSymbol(varTree);
TreePath enclosing = findEnclosing(state);
if (enclosing == null) {
return Optional.empty();
}
// find all uses of the variable in the enclosing method
List<TreePath> uses = new ArrayList<>();
new TreePathScanner<Void, Void>() {
@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
if (Objects.equals(sym, ASTHelpers.getSymbol(tree))) {
uses.add(getCurrentPath());
}
return super.visitIdentifier(tree, null);
}
}.scan(enclosing, null);
SuggestedFix.Builder fix = SuggestedFix.builder();
// a mutable boolean to track whether we want split or splitToList
boolean[] needsList = { false };
boolean[] needsMutableList = { false };
// try to fix all uses of the variable
for (TreePath path : uses) {
class UseFixer extends TreePathScanner<Boolean, Void> {
@Override
public Boolean visitEnhancedForLoop(EnhancedForLoopTree tree, Void unused) {
// fix here.
return sym.equals(ASTHelpers.getSymbol(tree.getExpression()));
}
@Override
public Boolean visitArrayAccess(ArrayAccessTree tree, Void unused) {
// replace `pieces[N]` with `pieces.get(N)`
ExpressionTree expression = tree.getExpression();
ExpressionTree index = tree.getIndex();
if (!sym.equals(ASTHelpers.getSymbol(expression))) {
return false;
}
Tree parent = getCurrentPath().getParentPath().getLeaf();
if (parent instanceof AssignmentTree && ((AssignmentTree) parent).getVariable() == tree) {
AssignmentTree assignmentTree = (AssignmentTree) parent;
fix.replace(/* startPos= */
state.getEndPosition(expression), /* endPos= */
((JCTree) index).getStartPosition(), ".set(").replace(/* startPos= */
state.getEndPosition(index), /* endPos= */
((JCTree) assignmentTree.getExpression()).getStartPosition(), ", ").postfixWith(assignmentTree, ")");
needsMutableList[0] = true;
} else {
fix.replace(/* startPos= */
state.getEndPosition(expression), /* endPos= */
((JCTree) index).getStartPosition(), ".get(").replace(state.getEndPosition(index), state.getEndPosition(tree), ")");
}
// we want a list for indexing
needsList[0] = true;
return true;
}
@Override
public Boolean visitMemberSelect(MemberSelectTree tree, Void aVoid) {
// replace `pieces.length` with `pieces.size`
if (sym.equals(ASTHelpers.getSymbol(tree.getExpression())) && tree.getIdentifier().contentEquals("length")) {
fix.replace(state.getEndPosition(tree.getExpression()), state.getEndPosition(tree), ".size()");
needsList[0] = true;
return true;
}
return false;
}
}
if (!firstNonNull(new UseFixer().scan(path.getParentPath(), null), false)) {
return Optional.empty();
}
}
if (needsList[0]) {
fix.replace((varTree).getType(), "List<String>").addImport("java.util.List");
replaceWithSplitter(fix, tree, value, state, "splitToList", maybeRegex, needsMutableList[0]);
} else {
fix.replace((varTree).getType(), "Iterable<String>");
replaceWithSplitter(fix, tree, value, state, "split", maybeRegex, needsMutableList[0]);
}
return Optional.of(fix.build());
}
use of com.sun.source.tree.AssignmentTree in project error-prone by google.
the class SelfAssignment method describeForAssignment.
/**
* We expect that the lhs is a field and the rhs is an identifier, specifically a parameter to the
* method. We base our suggested fixes on this expectation.
*
* <p>Case 1: If lhs is a field and rhs is an identifier, find a method parameter of the same type
* and similar name and suggest it as the rhs. (Guess that they have misspelled the identifier.)
*
* <p>Case 2: If lhs is a field and rhs is not an identifier, find a method parameter of the same
* type and similar name and suggest it as the rhs.
*
* <p>Case 3: If lhs is not a field and rhs is an identifier, find a class field of the same type
* and similar name and suggest it as the lhs.
*
* <p>Case 4: Otherwise suggest deleting the assignment.
*/
public Description describeForAssignment(AssignmentTree assignmentTree, VisitorState state) {
// the statement that is the parent of the self-assignment expression
Tree parent = state.getPath().getParentPath().getLeaf();
// default fix is to delete assignment
Fix fix = SuggestedFix.delete(parent);
ExpressionTree lhs = assignmentTree.getVariable();
ExpressionTree rhs = assignmentTree.getExpression();
// if this is a method invocation, they must be calling checkNotNull()
if (assignmentTree.getExpression().getKind() == METHOD_INVOCATION) {
// change the default fix to be "checkNotNull(x)" instead of "x = checkNotNull(x)"
fix = SuggestedFix.replace(assignmentTree, rhs.toString());
// new rhs is first argument to checkNotNull()
rhs = stripNullCheck(rhs, state);
}
ImmutableList<Fix> exploratoryFieldFixes = ImmutableList.of();
if (lhs.getKind() == MEMBER_SELECT) {
// find a method parameter of the same type and similar name and suggest it
// as the rhs
// rhs should be either identifier or field access
Preconditions.checkState(rhs.getKind() == IDENTIFIER || rhs.getKind() == MEMBER_SELECT);
Type rhsType = ASTHelpers.getType(rhs);
exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithMethodParameter(rhs, varDecl -> ASTHelpers.isSameType(rhsType, varDecl.type, state), state);
} else if (rhs.getKind() == IDENTIFIER) {
// find a field of the same type and similar name and suggest it as the lhs
// lhs should be identifier
Preconditions.checkState(lhs.getKind() == IDENTIFIER);
Type lhsType = ASTHelpers.getType(lhs);
exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithLocallyDeclaredField(lhs, var -> !Flags.isStatic(var.sym) && (var.sym.flags() & Flags.FINAL) == 0 && ASTHelpers.isSameType(lhsType, var.type, state), state);
}
if (exploratoryFieldFixes.isEmpty()) {
return describeMatch(assignmentTree, fix);
}
return buildDescription(assignmentTree).addAllFixes(exploratoryFieldFixes).build();
}
use of com.sun.source.tree.AssignmentTree in project error-prone by google.
the class ConstructorLeaksThis method traverse.
@Override
protected void traverse(Tree tree, VisitorState state) {
ClassSymbol thisClass = ASTHelpers.getSymbol(state.findEnclosing(ClassTree.class));
tree.accept(new TreeScanner<Void, Void>() {
@Override
public Void visitIdentifier(IdentifierTree node, Void unused) {
checkForThis(node, node.getName(), thisClass, state);
return super.visitIdentifier(node, null);
}
@Override
public Void visitMemberSelect(MemberSelectTree node, Void unused) {
checkForThis(node, node.getIdentifier(), thisClass, state);
// Don't examine this.foo or MyClass.this.foo
ExpressionTree left = node.getExpression();
if ((left instanceof IdentifierTree && ((IdentifierTree) left).getName().contentEquals("this")) || (left instanceof MemberSelectTree && ((MemberSelectTree) left).getIdentifier().contentEquals("this"))) {
return null;
}
return super.visitMemberSelect(node, unused);
}
@Override
public Void visitAssignment(AssignmentTree node, Void unused) {
scan(node.getExpression(), null);
// ignore references to 'this' in the LHS of assignments
return null;
}
}, null);
}
use of com.sun.source.tree.AssignmentTree in project j2objc by google.
the class TreeConverter method convertAnnotation.
private TreeNode convertAnnotation(AnnotationTree node, TreePath parent) {
List<? extends ExpressionTree> args = node.getArguments();
String annotationName = node.getAnnotationType().toString();
AnnotationMirror annotationMirror = ((JCAnnotation) node).attribute;
boolean isPropertyAnnotation = annotationName.equals(Property.class.getSimpleName()) || annotationName.equals(Property.class.getName());
Annotation newNode;
TreePath path = getTreePath(parent, node);
if (isPropertyAnnotation) {
newNode = new PropertyAnnotation().setAnnotationMirror(annotationMirror);
if (!args.isEmpty()) {
for (String attr : ElementUtil.parsePropertyAttribute(annotationMirror)) {
((PropertyAnnotation) newNode).addAttribute(attr);
}
}
} else if (args.isEmpty()) {
newNode = new MarkerAnnotation().setAnnotationMirror(annotationMirror);
} else if (args.size() == 1) {
AssignmentTree assign = (AssignmentTree) args.get(0);
ExpressionTree expression = assign.getExpression();
newNode = new SingleMemberAnnotation().setValue((Expression) convert(expression, getTreePath(path, assign)));
} else {
NormalAnnotation normalAnn = new NormalAnnotation();
for (ExpressionTree obj : node.getArguments()) {
AssignmentTree assign = (AssignmentTree) obj;
ExpressionTree variable = assign.getVariable();
ExpressionTree expression = assign.getExpression();
TreePath assignPath = getTreePath(path, assign);
TreePath variablePath = getTreePath(assignPath, variable);
SimpleName name = convertSimpleName(getElement(variablePath), getTypeMirror(variablePath), getPosition(variable));
MemberValuePair memberPair = new MemberValuePair().setName(name).setValue((Expression) convert(expression, assignPath));
normalAnn.addValue(memberPair);
}
newNode = normalAnn;
}
return newNode.setAnnotationMirror(annotationMirror).setTypeName((Name) convert(node.getAnnotationType(), path));
}
Aggregations