private static List<? extends TypeMirror> computeReturn(Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { ReturnTree rt = (ReturnTree) parent.getLeaf(); if (rt.getExpression() == error) { TreePath method = findMethod(parent); if (method == null) { return null; } Element el = info.getTrees().getElement(method); if (el == null || el.getKind() != ElementKind.METHOD) { return null; } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(((ExecutableElement) el).getReturnType()); } return null; }
private MethodTree createGetter(ModifiersTree mods, TypeMirror valueType) { StringBuilder getterName = GeneratorUtils.getCapitalizedName(config.getName()); getterName.insert(0, valueType.getKind() == TypeKind.BOOLEAN ? "is" : "get"); ReturnTree returnTree = make.Return(make.MethodInvocation(Collections.EMPTY_LIST, make.MemberSelect(make.Identifier(config.getName()), hasGet ? "get" : "getValue"), Collections.EMPTY_LIST)); BlockTree getterBody = make.Block(Collections.singletonList(returnTree), false); Tree valueTree; if (valueType.getKind() == TypeKind.DECLARED) { valueTree = make.QualIdent(((DeclaredType) valueType).asElement()); } else if (valueType.getKind().isPrimitive()) { valueTree = make.PrimitiveType(valueType.getKind()); } else { valueTree = make.Identifier(valueType.toString()); } MethodTree getter = make.Method(mods, getterName, valueTree, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, getterBody, null); return getter; }
@Override protected void performRewrite(TransformationContext ctx) throws Exception { TreePath retPath = ctx.getPath(); if (retPath.getLeaf().getKind() != Tree.Kind.RETURN) { return; } ReturnTree rtt = (ReturnTree)retPath.getLeaf(); if (rtt.getExpression() == null) { return; } WorkingCopy wc = ctx.getWorkingCopy(); ExpressionToStatement st = new ExpressionToStatement(wc.getTreeMaker(), wc); st.scan(new TreePath(retPath, rtt.getExpression()), null); if (st.remove || st.statements.isEmpty()) { // error, but I don't have an utility to properly remove the statement // from its parent now. return; } Utilities.replaceStatement(wc, retPath, st.statements); }
public void performRewriteToMemberReference() { MethodTree methodTree = getMethodFromFunctionalInterface(newClassTree); if (methodTree.getBody() == null || methodTree.getBody().getStatements().size() != 1) return; Tree tree = methodTree.getBody().getStatements().get(0); if (tree.getKind() == Tree.Kind.EXPRESSION_STATEMENT) { tree = ((ExpressionStatementTree)tree).getExpression(); } else if (tree.getKind() == Tree.Kind.RETURN) { tree = ((ReturnTree)tree).getExpression(); } else { return; } Tree changed = null; if (tree.getKind() == Tree.Kind.METHOD_INVOCATION) { changed = methodInvocationToMemberReference(copy, tree, pathToNewClassTree, methodTree.getParameters(), preconditionChecker.needsCastToExpectedType()); } else if (tree.getKind() == Tree.Kind.NEW_CLASS) { changed = newClassToConstructorReference(copy, tree, pathToNewClassTree, methodTree.getParameters(), preconditionChecker.needsCastToExpectedType()); } if (changed != null) { copy.rewrite(newClassTree, changed); } }
public Boolean visitReturn(ReturnTree node, ConstructorData p) { super.visitReturn(node, p); variable2State = new HashMap< Element, State>(variable2State); if (pendingFinally.isEmpty()) { //performance: limit amount of held variables and their mapping: for ( Element ve : currentMethodVariables) { variable2State.remove(ve); } } resumeAfter(nearestMethod, variable2State); removeAllDefinitions(); return null; }
/** * Replaces former exit points by returns and/or adds a return with value at the end of the method */ private void makeReturnsFromExtractedMethod(List<StatementTree> methodStatements) { if (returnSingleValue) { return; } if (resolvedExits != null) { for (TreePath resolved : resolvedExits) { ReturnTree r = makeExtractedReturn(true); GeneratorUtilities.get(copy).copyComments(resolved.getLeaf(), r, false); GeneratorUtilities.get(copy).copyComments(resolved.getLeaf(), r, true); copy.rewrite(resolved.getLeaf(), r); } // the default exit path, should return false if (outcomeVariable == null && !exitsFromAllBranches) { methodStatements.add(make.Return(make.Literal(false))); } } else { ReturnTree ret = makeExtractedReturn(false); if (ret != null) { methodStatements.add(ret); } } }
@Override public List<? extends TypeMirror> visitReturn(ReturnTree node, Object p) { if (node.getExpression() == null) { return null; } if (theExpression == null) { initExpression(node.getExpression()); } TreePath parents = getCurrentPath(); while (parents != null && parents.getLeaf().getKind() != Tree.Kind.METHOD) { parents = parents.getParentPath(); } if (parents != null) { Tree returnTypeTree = ((MethodTree) parents.getLeaf()).getReturnType(); if (returnTypeTree != null) { return Collections.singletonList(info.getTrees().getTypeMirror(new TreePath(parents, returnTypeTree))); } } return null; }
@Override public Void visitReturn(ReturnTree node, Void p) { if (isMethodCode() /*&& phase == PHASE_INSIDE_SELECTION*/) { hasReturns = true; Element retExpElem = info.getTrees().getElement(new TreePath(getCurrentPath(), node.getExpression())); //.asType().toString(); if (retExpElem != null) { returnTypes.add(getElementType(retExpElem)); } else { // Unresolved element TypeElement object = info.getElements().getTypeElement("java.lang.Object"); if (object != null) { returnTypes.add(object.asType()); } } } return super.visitReturn(node, p); }
@Override public Mirror visitReturn(ReturnTree arg0, EvaluationContext evaluationContext) { ExpressionTree exprTree = arg0.getExpression(); Mirror result; if (exprTree == null) { VirtualMachine vm = evaluationContext.getDebugger().getVirtualMachine(); if (vm == null) { return null; } // vm.mirrorOfVoid(); [TODO] result = null; } else { result = exprTree.accept(this, evaluationContext); } return new Return(result); }
public ReturnToInstrumentInfo(@NotNull CompilationUnitProcessingContext context, @Nullable String notNullAnnotation, @Nullable String notNullByDefaultAnnotationDescription, @NotNull ReturnTree returnExpression, @NotNull JCTree.JCExpression returnType, @NotNull String tmpVariableName, @NotNull Tree parent, @Nullable String qualifiedMethodName) { if (notNullAnnotation == null && notNullByDefaultAnnotationDescription == null) { throw new IllegalArgumentException(String.format( "Detected an invalid attempt to instrument a method return - either NotNull annotation or " + "NotNullByDefault annotations are undefined. Method: %s()", qualifiedMethodName)); } this.context = context; this.notNullAnnotation = notNullAnnotation; this.notNullByDefaultAnnotationDescription = notNullByDefaultAnnotationDescription; this.returnExpression = returnExpression; this.returnType = returnType; this.tmpVariableName = tmpVariableName; this.parent = parent; this.qualifiedMethodName = qualifiedMethodName; }
@Override public void onMatchReturn(NullAway analysis, ReturnTree tree, VisitorState state) { // Figure out the enclosing method node TreePath enclosingMethodOrLambda = NullabilityUtil.findEnclosingMethodOrLambdaOrInitializer(state.getPath()); if (enclosingMethodOrLambda == null) { throw new RuntimeException("no enclosing method, lambda or initializer!"); } if (!(enclosingMethodOrLambda.getLeaf() instanceof MethodTree || enclosingMethodOrLambda.getLeaf() instanceof LambdaExpressionTree)) { throw new RuntimeException( "return statement outside of a method or lambda! (e.g. in an initializer block)"); } Tree leaf = enclosingMethodOrLambda.getLeaf(); if (filterMethodOrLambdaSet.contains(leaf)) { returnToEnclosingMethodOrLambda.put(tree, leaf); // We need to manually trigger the dataflow analysis to run on the filter method, // this ensures onDataflowVisitReturn(...) gets called for all return statements in this // method before // onDataflowInitialStore(...) is called for all successor methods in the observable chain. // Caching should prevent us from re-analyzing any given method. AccessPathNullnessAnalysis nullnessAnalysis = analysis.getNullnessAnalysis(state); nullnessAnalysis.forceRunOnMethod(new TreePath(state.getPath(), leaf), state.context); } }
@Override public void onDataflowVisitReturn( ReturnTree tree, NullnessStore<Nullness> thenStore, NullnessStore<Nullness> elseStore) { if (returnToEnclosingMethodOrLambda.containsKey(tree)) { Tree filterTree = returnToEnclosingMethodOrLambda.get(tree); assert (filterTree instanceof MethodTree || filterTree instanceof LambdaExpressionTree); ExpressionTree retExpression = tree.getExpression(); if (canBooleanExpressionEvalToTrue(retExpression)) { if (filterToNSMap.containsKey(filterTree)) { filterToNSMap.put(filterTree, filterToNSMap.get(filterTree).leastUpperBound(thenStore)); } else { filterToNSMap.put(filterTree, thenStore); } } } }
@Override public final Description matchReturn(ReturnTree tree, VisitorState state) { if (tree.getExpression() == null || tree.getExpression().getKind() != NULL_LITERAL) { return NO_MATCH; } TreePath path = state.getPath(); while (path != null && path.getLeaf() instanceof StatementTree) { path = path.getParentPath(); } if (path == null || !(path.getLeaf() instanceof MethodTree)) { return NO_MATCH; } if (!implementsAsyncTypeMethod.matches((MethodTree) path.getLeaf(), state)) { return NO_MATCH; } return describeMatch( tree, SuggestedFix.builder() .replace(tree.getExpression(), "immediateFuture(null)") .addStaticImport(Futures.class.getName() + ".immediateFuture") .build()); }
@Override public Description matchReturn(ReturnTree tree, VisitorState state) { if (tree.getExpression() == null) { return NO_MATCH; } Type type = null; outer: for (Tree parent : state.getPath()) { switch (parent.getKind()) { case METHOD: type = ASTHelpers.getType(((MethodTree) parent).getReturnType()); break outer; case LAMBDA_EXPRESSION: type = state.getTypes().findDescriptorType(ASTHelpers.getType(parent)).getReturnType(); break outer; default: // fall out } } if (type == null) { return NO_MATCH; } return check(type, tree.getExpression()); }
private static ImmutableSet<ClassType> getMethodReturnTypes(MethodTree methodTree) { ImmutableSet.Builder<ClassType> returnTypes = ImmutableSet.builder(); methodTree.accept( new TreeScanner<Void, Void>() { @Override public Void visitReturn(ReturnTree node, Void unused) { Type type = ASTHelpers.getType(node.getExpression()); if (type instanceof ClassType) { returnTypes.add((ClassType) type); } return null; } }, null /* unused */); return returnTypes.build(); }
@Override public boolean matches(MethodTree method, VisitorState state) { List<? extends VariableTree> parameters = method.getParameters(); if (!parameters.isEmpty()) { return false; } BlockTree body = method.getBody(); if (body == null) { return false; } List<? extends StatementTree> statements = body.getStatements(); if (statements.size() != 1) { return false; } StatementTree onlyStatement = Iterables.getOnlyElement(statements); if (!onlyStatement.getKind().equals(RETURN)) { return false; } return EMPTY_SET.matches(((ReturnTree) onlyStatement).getExpression(), state); }
@Test public void testGetTypeOnParameterizedType() { writeFile( "Pair.java", "public class Pair<A, B> { ", " public A first;", " public B second;", "}"); writeFile( "Test.java", "public class Test {", " public Integer doSomething(Pair<Integer, String> pair) {", " return pair.first;", " }", "}"); TestScanner scanner = new TestScanner() { @Override public Void visitReturn(ReturnTree tree, VisitorState state) { setAssertionsComplete(); assertThat(ASTHelpers.getType(tree.getExpression()).toString()) .isEqualTo("java.lang.Integer"); return super.visitReturn(tree, state); } }; tests.add(scanner); assertCompiles(scanner); }
private boolean isTerminating(StatementTree tree) { StatementTree first = firstStatement(tree); if (first instanceof ThrowTree) return true; if (first instanceof ReturnTree) return true; if (first instanceof IfTree) { IfTree ifTree = (IfTree)first; if (ifTree.getElseStatement() != null && isTerminating(ifTree.getThenStatement()) && isTerminating(ifTree.getElseStatement())) return true; } return false; }
/** * Checks that the type of the return expression is a subtype of the * enclosing method required return type. If not, it issues a * "return.type.incompatible" error. */ @Override public Void visitReturn(ReturnTree node, Void p) { // Don't try to check return expressions for void methods. if (node.getExpression() == null) return super.visitReturn(node, p); Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext(); try { MethodTree enclosingMethod = TreeUtils.enclosingMethod(getCurrentPath()); boolean valid = validateTypeOf(enclosingMethod); if (valid) { AnnotatedTypeMirror ret = atypeFactory.getMethodReturnType(enclosingMethod, node); visitorState.setAssignmentContext(Pair.of((Tree) node, ret)); commonAssignmentCheck(ret, node.getExpression(), "return.type.incompatible", false); } return super.visitReturn(node, p); } finally { visitorState.setAssignmentContext(preAssCtxt); } }
@Override public Tree visitReturn(ReturnTree tree, Void p) { ReturnTree n = make.Return(tree.getExpression()); model.setType(n, model.getType(tree)); comments.copyComments(tree, n); model.setPos(n, model.getPos(tree)); return n; }
public Boolean visitReturn(ReturnTree node, TreePath p) { if (p == null) { super.visitReturn(node, p); return false; } ReturnTree at = (ReturnTree) p.getLeaf(); return scan(node.getExpression(), at.getExpression(), p); }
public void testLambdaFullBody2Expression() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " ChangeListener l = (e) -> {return 1;};\n" + " }\n" + "}\n" ); String golden = "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " ChangeListener l = (e) -> 1;\n" + " }\n" + "}\n"; JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws IOException { workingCopy.toPhase(Phase.RESOLVED); final TreeMaker make = workingCopy.getTreeMaker(); new ErrorAwareTreeScanner<Void, Void>() { @Override public Void visitLambdaExpression(LambdaExpressionTree node, Void p) { ReturnTree t = (ReturnTree) ((BlockTree) node.getBody()).getStatements().get(0); workingCopy.rewrite(node, make.setLambdaBody(node, t.getExpression())); return super.visitLambdaExpression(node, p); } }.scan(workingCopy.getCompilationUnit(), null); } }; src.runModificationTask(task).commit(); String res = TestUtilities.copyFileToString(testFile); System.err.println(res); assertEquals(golden, res); }
@Override public Boolean visitReturn(ReturnTree tree, Stack<Tree> d) { if (exceptions == null) { if (doExitPoints) { addHighlightFor(tree); } } super.visitReturn(tree, d); return Boolean.TRUE; }
@Override public Void visitReturn(ReturnTree tree, EnumSet<UseTypes> d) { if (tree.getExpression() instanceof IdentifierTree) { handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ)); } super.visitReturn(tree, EnumSet.of(UseTypes.READ)); return null; }
@Override public Object visitReturn(ReturnTree node, Object p) { TreePath path = getCurrentPath(); TreePath parentPath = path.getParentPath(); if (suppress) { return super.visitReturn(node, p); } if (ignoreGuards && parentPath != null) { Tree parentTree = parentPath.getLeaf(); TreePath branchPath = path; while (parentTree.getKind() == Tree.Kind.BLOCK) { branchPath = parentPath; parentPath = parentPath.getParentPath(); parentTree = parentPath.getLeaf(); } if (parentTree.getKind() == Tree.Kind.IF) { IfTree ifTree = (IfTree)parentTree; StatementTree trueTree = ifTree.getThenStatement() == branchPath.getLeaf() ? ifTree.getThenStatement() : ifTree.getElseStatement(); if (trueTree == node) { return super.visitReturn(node, p); } if (trueTree.getKind() == Tree.Kind.BLOCK) { BlockTree bt = (BlockTree)trueTree; if (bt.getStatements().size() == 1) { return super.visitReturn(node, p); } } } } returnCount++; return super.visitReturn(node, p); }
private MethodTree createProperty(ModifiersTree mods, DeclaredType selectedType, ExecutableElement wrapperMethod) { String getterName = config.getName() + "Property"; ExpressionTree expression; if (wrapperMethod == null) { expression = make.Identifier(config.getName()); } else { expression = make.MethodInvocation(Collections.EMPTY_LIST, make.MemberSelect(make.Identifier(config.getName()), wrapperMethod.getSimpleName()), Collections.EMPTY_LIST); } ReturnTree returnTree = make.Return(expression); BlockTree getterBody = make.Block(Collections.singletonList(returnTree), false); MethodTree getter = make.Method(mods, getterName, selectedType == null ? make.Identifier(config.getPropertyType()) : make.QualIdent(selectedType.asElement()), Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, getterBody, null); return getter; }
@Override public Void visitReturn(ReturnTree tree, List<Node> d) { List<Node> below = new ArrayList<Node>(); addCorrespondingType(below); addCorrespondingComments(below); super.visitReturn(tree, below); d.add(new TreeNode(info, getCurrentPath(), below)); return null; }
private StatementTree propagateReturn( ProspectiveOperation lastOperation, MethodInvocationTree mi, TreeMaker treeMaker) { ReturnTree returnExpre = null; ExpressionTree pred = null; if ("anyMatch".equals(lastOperation.getSuitableMethod())) { pred = mi; returnExpre = treeMaker.Return(treeMaker.Literal(true)); } else if ("noneMatch".equals(lastOperation.getSuitableMethod())) { pred = treeMaker.Unary(Tree.Kind.LOGICAL_COMPLEMENT, mi); returnExpre = treeMaker.Return(treeMaker.Literal(false)); } return treeMaker.If(pred, returnExpre, null); }
private List<ProspectiveOperation> getIfListRepresentation( StatementTree tree, boolean last) { IfTree ifTree = (IfTree) tree; List<ProspectiveOperation> ls = new ArrayList<ProspectiveOperation>(); if (ifTree.getElseStatement() == null) { StatementTree then = ifTree.getThenStatement(); if (isOneStatementBlock(then)) { then = ((BlockTree) then).getStatements().get(0); } if (then.getKind() == Tree.Kind.RETURN) { ReturnTree returnTree = (ReturnTree) then; ExpressionTree returnExpression = returnTree.getExpression(); if (returnExpression.getKind() == Tree.Kind.BOOLEAN_LITERAL && ((LiteralTree) returnExpression).getValue().equals(true)) { ls.addAll(ProspectiveOperation.createOperator(ifTree, ProspectiveOperation.OperationType.ANYMATCH, this.preconditionsChecker, this.workingCopy)); } else if (returnExpression.getKind() == Tree.Kind.BOOLEAN_LITERAL && ((LiteralTree) returnExpression).getValue().equals(false)) { ls.addAll(ProspectiveOperation.createOperator(ifTree, ProspectiveOperation.OperationType.NONEMATCH, this.preconditionsChecker, this.workingCopy)); } } else { ls.addAll(ProspectiveOperation.createOperator(ifTree, ProspectiveOperation.OperationType.FILTER, this.preconditionsChecker, this.workingCopy)); ls.addAll(getListRepresentation(ifTree.getThenStatement(), last)); } } else { ls.addAll(ProspectiveOperation.createOperator(ifTree, ProspectiveOperation.OperationType.MAP, this.preconditionsChecker, this.workingCopy)); } return ls; }
@Override public Tree visitReturn(ReturnTree that, Trees trees) { ExpressionTree thatExpression = that.getExpression(); if (!this.hasMatcherReturn && thatExpression != null && thatExpression.getKind() == Tree.Kind.BOOLEAN_LITERAL && thisIsMatcherReturn(that, this.getCurrentPath())) { this.hasMatcherReturn = true; } else { this.hasReturns = true; } return super.visitReturn(that, trees); }
@Override public State visitReturn(ReturnTree node, Void p) { State s; if (returnIfRecurse(s = scan(node.getExpression(), p))) { return s; } return knownResult = State.RETURN; }
@Override public Void visitReturn(ReturnTree node, Collection<TreePath> trees) { if (!analyzeThrows) { trees.add(getCurrentPath()); } return null; }
@Override public Boolean visitReturn(ReturnTree node, Void p) { if (scan(node.getExpression(), p) == Boolean.TRUE) { returned = true; } return false; }
/** * Creates a return statement tree from the extracted method, depending on return type and/or branching */ private ReturnTree makeExtractedReturn(boolean forceReturn) { if (outcomeVariable != null) { return make.Return(make.Identifier(outcomeVariable.getSimpleName())); } else if (forceReturn) { return make.Return(exitsFromAllBranches ? null : make.Literal(true)); } else { return null; } }
@Override public Void visitReturn(ReturnTree node, Void p) { if (isMethodCode() && phase == PHASE_INSIDE_SELECTION) { selectionExits.add(getCurrentPath()); hasReturns = true; } return super.visitReturn(node, p); }
@Override protected void performRewrite(TransformationContext ctx) throws Exception { final WorkingCopy copy = ctx.getWorkingCopy(); TypeMirror samType = copy.getTrees().getTypeMirror(ctx.getPath()); if (samType == null || samType.getKind() != TypeKind.DECLARED) { // FIXME: report return ; } LambdaExpressionTree lambda = (LambdaExpressionTree) ctx.getPath().getLeaf(); Tree tree = lambda.getBody(); if (tree.getKind() == Tree.Kind.BLOCK) { if (((BlockTree)tree).getStatements().size() == 1) { tree = ((BlockTree)tree).getStatements().get(0); if (tree.getKind() == Tree.Kind.EXPRESSION_STATEMENT) { tree = ((ExpressionStatementTree)tree).getExpression(); } else if (tree.getKind() == Tree.Kind.RETURN) { tree = ((ReturnTree)tree).getExpression(); } else { return; } } else { return; } } Tree changed = null; if (tree.getKind() == Tree.Kind.METHOD_INVOCATION) { changed = ConvertToLambdaConverter.methodInvocationToMemberReference(copy, tree, ctx.getPath(), lambda.getParameters(), false); } else if (tree.getKind() == Tree.Kind.NEW_CLASS) { changed = ConvertToLambdaConverter.newClassToConstructorReference(copy, tree, ctx.getPath(), lambda.getParameters(), false); } if (changed != null) { copy.rewrite(lambda, changed); } }
private void prepareStandardTest(String className, String methodName) throws Exception { if (methodName == null) { methodName = getName(); methodName = Character.toLowerCase(methodName.charAt(4)) + methodName.substring(5); } prepareFileTest(false, "Test.java", "Base.java"); String pn = getMyPackageName(); TypeElement tel = info.getElements().getTypeElement(pn + "." + className); for (ExecutableElement e : ElementFilter.methodsIn(tel.getEnclosedElements())) { if (e.getSimpleName().contentEquals(methodName)) { testMethod = e; MethodTree mt = (MethodTree)info.getTrees().getTree(testMethod); testMethodTree = mt; List<? extends StatementTree> stmts = mt.getBody().getStatements(); Tree t = stmts.get(0); if (t.getKind() == Tree.Kind.RETURN) { t = ((ReturnTree)t).getExpression(); } else if (stmts.size() > 1) { t = mt.getBody(); } this.expressionTree = t; return; } } fail("Testcase method source not found"); }
@Override public List<Tree> visitReturn(ReturnTree node, ExpressionsInfo p) { if (acceptsTree(node)) { return scan(node.getExpression(), p); } else { return null; } }