use of com.sun.tools.javac.tree.JCTree.JCTry in project lombok by rzwitserloot.
the class HandleNonNull method handle.
@Override
public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
if (annotationNode.up().getKind() == Kind.FIELD) {
try {
if (isPrimitive(((JCVariableDecl) annotationNode.up().get()).vartype)) {
annotationNode.addWarning("@NonNull is meaningless on a primitive.");
}
} catch (Exception ignore) {
}
return;
}
if (annotationNode.up().getKind() != Kind.ARGUMENT)
return;
JCMethodDecl declaration;
try {
declaration = (JCMethodDecl) annotationNode.up().up().get();
} catch (Exception e) {
return;
}
if (declaration.body == null) {
// This used to be a warning, but as @NonNull also has a documentary purpose, better to not warn about this. Since 1.16.7
return;
}
// Possibly, if 'declaration instanceof ConstructorDeclaration', fetch declaration.constructorCall, search it for any references to our parameter,
// and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and
// wrap all references to it in the super/this to a call to this method.
JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), annotationNode.up(), annotationNode), ast, annotationNode.getContext());
if (nullCheck == null) {
// @NonNull applied to a primitive. Kinda pointless. Let's generate a warning.
annotationNode.addWarning("@NonNull is meaningless on a primitive.");
return;
}
List<JCStatement> statements = declaration.body.stats;
String expectedName = annotationNode.up().getName();
/* Abort if the null check is already there, delving into try and synchronized statements */
{
List<JCStatement> stats = statements;
int idx = 0;
while (stats.size() > idx) {
JCStatement stat = stats.get(idx++);
if (JavacHandlerUtil.isConstructorCall(stat))
continue;
if (stat instanceof JCTry) {
stats = ((JCTry) stat).body.stats;
idx = 0;
continue;
}
if (stat instanceof JCSynchronized) {
stats = ((JCSynchronized) stat).body.stats;
idx = 0;
continue;
}
String varNameOfNullCheck = returnVarNameIfNullCheck(stat);
if (varNameOfNullCheck == null)
break;
if (varNameOfNullCheck.equals(expectedName))
return;
}
}
List<JCStatement> tail = statements;
List<JCStatement> head = List.nil();
for (JCStatement stat : statements) {
if (JavacHandlerUtil.isConstructorCall(stat) || (JavacHandlerUtil.isGenerated(stat) && isNullCheck(stat))) {
tail = tail.tail;
head = head.prepend(stat);
continue;
}
break;
}
List<JCStatement> newList = tail.prepend(nullCheck);
for (JCStatement stat : head) newList = newList.prepend(stat);
declaration.body.stats = newList;
annotationNode.getAst().setChanged();
}
use of com.sun.tools.javac.tree.JCTree.JCTry in project lombok by rzwitserloot.
the class HandleSneakyThrows method buildTryCatchBlock.
public JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JCTree source) {
JavacTreeMaker maker = node.getTreeMaker();
Context context = node.getContext();
JCBlock tryBlock = setGeneratedBy(maker.Block(0, contents), source, context);
JCExpression varType = chainDots(node, exception.split("\\."));
JCVariableDecl catchParam = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), node.toName("$ex"), varType, null);
JCExpression lombokLombokSneakyThrowNameRef = chainDots(node, "lombok", "Lombok", "sneakyThrow");
JCBlock catchBody = maker.Block(0, List.<JCStatement>of(maker.Throw(maker.Apply(List.<JCExpression>nil(), lombokLombokSneakyThrowNameRef, List.<JCExpression>of(maker.Ident(node.toName("$ex")))))));
JCTry tryStatement = maker.Try(tryBlock, List.of(recursiveSetGeneratedBy(maker.Catch(catchParam, catchBody), source, context)), null);
if (JavacHandlerUtil.inNetbeansEditor(node)) {
// set span (start and end position) of the try statement and the main block
// this allows NetBeans to dive into the statement correctly:
JCCompilationUnit top = (JCCompilationUnit) node.top().get();
int startPos = contents.head.pos;
int endPos = Javac.getEndPosition(contents.last().pos(), top);
tryBlock.pos = startPos;
tryStatement.pos = startPos;
Javac.storeEnd(tryBlock, endPos, top);
Javac.storeEnd(tryStatement, endPos, top);
}
return setGeneratedBy(tryStatement, source, context);
}
use of com.sun.tools.javac.tree.JCTree.JCTry in project error-prone by google.
the class AssertionFailureIgnored method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!ASSERTION.matches(tree, state)) {
return NO_MATCH;
}
JCTry tryStatement = enclosingTry(state);
if (tryStatement == null) {
return NO_MATCH;
}
Optional<JCCatch> maybeCatchTree = catchesType(tryStatement, state.getSymtab().assertionErrorType, state);
if (!maybeCatchTree.isPresent()) {
return NO_MATCH;
}
JCCatch catchTree = maybeCatchTree.get();
VarSymbol parameter = ASTHelpers.getSymbol(catchTree.getParameter());
boolean rethrows = firstNonNull(new TreeScanner<Boolean, Void>() {
@Override
public Boolean visitThrow(ThrowTree tree, Void unused) {
if (Objects.equals(parameter, ASTHelpers.getSymbol(tree.getExpression()))) {
return true;
}
if (NEW_THROWABLE.matches(tree.getExpression(), state) && ((NewClassTree) tree.getExpression()).getArguments().stream().anyMatch(arg -> Objects.equals(parameter, ASTHelpers.getSymbol(arg)))) {
return true;
}
return super.visitThrow(tree, null);
}
@Override
public Boolean reduce(Boolean a, Boolean b) {
return firstNonNull(a, false) || firstNonNull(b, false);
}
}.scan(catchTree.getBlock(), null), false);
if (rethrows) {
return NO_MATCH;
}
Description.Builder description = buildDescription(tree);
buildFix(tryStatement, tree, state).ifPresent(description::addFix);
return description.build();
}
use of com.sun.tools.javac.tree.JCTree.JCTry in project ceylon-compiler by ceylon.
the class StatementTransformer method transform.
public JCStatement transform(Tree.TryCatchStatement t) {
Tree.TryClause tryClause = t.getTryClause();
at(tryClause);
JCBlock tryBlock = transform(tryClause.getBlock());
Tree.ResourceList resList = tryClause.getResourceList();
if (resList != null) {
ArrayList<Tree.Resource> resources = new ArrayList<Tree.Resource>(resList.getResources());
Collections.reverse(resources);
for (Tree.Resource res : resources) {
List<JCStatement> stats = List.nil();
Tree.Expression resExpr;
String resVarName;
if (res.getExpression() != null) {
resExpr = res.getExpression();
resVarName = naming.newTemp("try");
} else if (res.getVariable() != null) {
Tree.Variable var = res.getVariable();
resExpr = var.getSpecifierExpression().getExpression();
resVarName = var.getIdentifier().getText();
} else {
throw new BugException(res, "missing resource expression");
}
boolean isDestroyable = typeFact().getDestroyableType().isSupertypeOf(resExpr.getTypeModel());
Type resVarType = resExpr.getTypeModel();
Type resVarExpectedType = isDestroyable ? typeFact().getDestroyableType() : typeFact().getObtainableType();
// CloseableType $var = resource-expression
JCExpression expr = expressionGen().transformExpression(resExpr);
JCExpression javaType = makeJavaType(resVarType);
JCVariableDecl var = makeVar(FINAL, resVarName, javaType, expr);
stats = stats.append(var);
if (!isDestroyable) {
JCExpression resVar0 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation openCall = make().Apply(null, makeQualIdent(resVar0, "obtain"), List.<JCExpression>nil());
stats = stats.append(make().Exec(openCall));
}
// Exception $tpmex = null;
String innerExTmpVarName = naming.newTemp("ex");
JCExpression innerExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl innerExTmpVar = makeVar(innerExTmpVarName, innerExType, makeNull());
stats = stats.append(innerExTmpVar);
// $tmpex = ex;
List<JCStatement> innerCatchStats = List.nil();
Name innerCatchVarName = naming.tempName("ex");
JCAssign exTmpAssign = make().Assign(makeUnquotedIdent(innerExTmpVarName), make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(make().Exec(exTmpAssign));
// throw ex;
JCThrow innerCatchThrow = make().Throw(make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(innerCatchThrow);
JCBlock innerCatchBlock = make().Block(0, innerCatchStats);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar1 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall = make().Apply(null, makeQualIdent(resVar1, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg));
JCBlock closeTryBlock = make().Block(0, List.<JCStatement>of(make().Exec(closeCall)));
// try { $var.close() } catch (Exception closex) { $tmpex.addSuppressed(closex); }
Name closeCatchVarName = naming.tempName("closex");
JCExpression closeCatchExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl closeCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), closeCatchVarName, closeCatchExType, null);
JCExpression addarg = make().Ident(closeCatchVarName);
JCMethodInvocation addSuppressedCall = make().Apply(null, makeQualIdent(makeUnquotedIdent(innerExTmpVarName), "addSuppressed"), List.<JCExpression>of(addarg));
JCCatch closeCatch = make().Catch(closeCatchVar, make().Block(0, List.<JCStatement>of(make().Exec(addSuppressedCall))));
JCTry closeTry = at(res).Try(closeTryBlock, List.<JCCatch>of(closeCatch), null);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg2 = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar2 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall2 = make().Apply(null, makeQualIdent(resVar2, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg2));
// if ($tmpex != null) { ... } else { ... }
JCBinary closeCatchCond = make().Binary(JCTree.NE, makeUnquotedIdent(innerExTmpVarName), makeNull());
JCIf closeCatchIf = make().If(closeCatchCond, closeTry, make().Exec(closeCall2));
// try { .... } catch (Exception ex) { $tmpex=ex; throw ex; }
// finally { try { $var.close() } catch (Exception closex) { } }
JCExpression innerCatchExType = makeJavaType(typeFact().getThrowableType(), JT_CATCH);
JCVariableDecl innerCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), innerCatchVarName, innerCatchExType, null);
JCCatch innerCatch = make().Catch(innerCatchVar, innerCatchBlock);
JCBlock innerFinallyBlock = make().Block(0, List.<JCStatement>of(closeCatchIf));
JCTry innerTry = at(res).Try(tryBlock, List.<JCCatch>of(innerCatch), innerFinallyBlock);
stats = stats.append(innerTry);
tryBlock = at(res).Block(0, stats);
}
}
final List<JCCatch> catches;
if (usePolymorphicCatches(t.getCatchClauses())) {
catches = transformCatchesPolymorphic(t.getCatchClauses());
} else {
catches = transformCatchesIfElseIf(t.getCatchClauses());
}
final JCBlock finallyBlock;
Tree.FinallyClause finallyClause = t.getFinallyClause();
if (finallyClause != null) {
at(finallyClause);
finallyBlock = transform(finallyClause.getBlock());
} else {
finallyBlock = null;
}
if (!catches.isEmpty() || finallyBlock != null) {
return at(t).Try(tryBlock, catches, finallyBlock);
} else {
return tryBlock;
}
}
use of com.sun.tools.javac.tree.JCTree.JCTry in project error-prone by google.
the class Template method pretty.
protected static Pretty pretty(Context context, final Writer writer) {
final JCCompilationUnit unit = context.get(JCCompilationUnit.class);
try {
final String unitContents = unit.getSourceFile().getCharContent(false).toString();
return new Pretty(writer, true) {
{
// Work-around for b/22196513
width = 0;
}
@Override
public void visitAnnotation(JCAnnotation anno) {
if (anno.getArguments().isEmpty()) {
try {
print("@");
printExpr(anno.annotationType);
} catch (IOException e) {
// the supertype swallows exceptions too
throw new RuntimeException(e);
}
} else {
super.visitAnnotation(anno);
}
}
@Override
public void printExpr(JCTree tree, int prec) throws IOException {
EndPosTable endPositions = unit.endPositions;
/*
* Modifiers, and specifically flags like final, appear to just need weird special
* handling.
*
* Note: we can't use {@code TreeInfo.getEndPos()} or {@code JCTree.getEndPosition()}
* here, because they will return the end position of an enclosing AST node for trees
* whose real end positions aren't stored.
*/
int endPos = endPositions.getEndPos(tree);
boolean hasRealEndPosition = endPos != Position.NOPOS;
if (tree.getKind() != Kind.MODIFIERS && hasRealEndPosition) {
writer.append(unitContents.substring(tree.getStartPosition(), endPos));
} else {
super.printExpr(tree, prec);
}
}
@Override
public void visitApply(JCMethodInvocation tree) {
JCExpression select = tree.getMethodSelect();
if (select != null && select.toString().equals("Refaster.emitCommentBefore")) {
String commentLiteral = (String) ((JCLiteral) tree.getArguments().get(0)).getValue();
JCExpression expr = tree.getArguments().get(1);
try {
print("/* " + commentLiteral + " */ ");
} catch (IOException e) {
throw new RuntimeException(e);
}
expr.accept(this);
} else {
super.visitApply(tree);
}
}
@Override
public void printStat(JCTree tree) throws IOException {
if (tree instanceof JCExpressionStatement && ((JCExpressionStatement) tree).getExpression() instanceof JCMethodInvocation) {
JCMethodInvocation invocation = (JCMethodInvocation) ((JCExpressionStatement) tree).getExpression();
JCExpression select = invocation.getMethodSelect();
if (select != null && select.toString().equals("Refaster.emitComment")) {
String commentLiteral = (String) ((JCLiteral) invocation.getArguments().get(0)).getValue();
print("// " + commentLiteral);
return;
}
}
super.printStat(tree);
}
@Override
public void visitTry(JCTry tree) {
if (tree.getResources().isEmpty()) {
super.visitTry(tree);
return;
}
try {
print("try (");
boolean first = true;
for (JCTree resource : tree.getResources()) {
if (!first) {
print(";");
println();
}
printExpr(resource);
first = false;
}
print(")");
printStat(tree.body);
for (JCCatch catchStmt : tree.getCatches()) {
printStat(catchStmt);
}
if (tree.getFinallyBlock() != null) {
print(" finally ");
printStat(tree.getFinallyBlock());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Aggregations