use of com.sun.source.tree.TryTree in project st-js by st-js.
the class TryWriter method visit.
@Override
public JS visit(WriterVisitor<JS> visitor, TryTree tree, GenerationContext<JS> context) {
JS tryBlock = visitor.scan(tree.getBlock(), context);
List<JS> catchClauses = new ArrayList<JS>();
for (Tree c : tree.getCatches()) {
catchClauses.add(visitor.scan(c, context));
}
JS finallyBlock = null;
if (tree.getFinallyBlock() != null) {
finallyBlock = visitor.scan(tree.getFinallyBlock(), context);
}
return context.withPosition(tree, context.js().tryStatement(tryBlock, catchClauses, finallyBlock));
}
use of com.sun.source.tree.TryTree in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitTry.
@Override
public Node visitTry(TryTree tree, Void p) {
List<? extends CatchTree> catches = tree.getCatches();
BlockTree finallyBlock = tree.getFinallyBlock();
extendWithNode(new MarkerNode(tree, "start of try statement #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
List<Pair<TypeMirror, Label>> catchLabels = CollectionsPlume.mapList((CatchTree c) -> {
return Pair.of(TreeUtils.typeOf(c.getParameter().getType()), new Label());
}, catches);
// Store return/break/continue labels, just in case we need them for a finally block.
TryFinallyScopeCell oldReturnTargetL = returnTargetL;
TryFinallyScopeCell oldBreakTargetL = breakTargetL;
Map<Name, Label> oldBreakLabels = breakLabels;
TryFinallyScopeCell oldContinueTargetL = continueTargetL;
Map<Name, Label> oldContinueLabels = continueLabels;
Label finallyLabel = null;
Label exceptionalFinallyLabel = null;
if (finallyBlock != null) {
finallyLabel = new Label();
exceptionalFinallyLabel = new Label();
tryStack.pushFrame(new TryFinallyFrame(exceptionalFinallyLabel));
returnTargetL = new TryFinallyScopeCell();
breakTargetL = new TryFinallyScopeCell();
breakLabels = new TryFinallyScopeMap();
continueTargetL = new TryFinallyScopeCell();
continueLabels = new TryFinallyScopeMap();
}
Label doneLabel = new Label();
tryStack.pushFrame(new TryCatchFrame(types, catchLabels));
// Must scan the resources *after* we push frame to tryStack. Otherwise we can lose catch
// blocks.
// TODO: Should we handle try-with-resources blocks by also generating code for automatically
// closing the resources?
List<? extends Tree> resources = tree.getResources();
for (Tree resource : resources) {
scan(resource, p);
}
extendWithNode(new MarkerNode(tree, "start of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(tree.getBlock(), p);
extendWithNode(new MarkerNode(tree, "end of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
tryStack.popFrame();
int catchIndex = 0;
for (CatchTree c : catches) {
addLabelForNextNode(catchLabels.get(catchIndex).second);
extendWithNode(new MarkerNode(tree, "start of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(c, p);
extendWithNode(new MarkerNode(tree, "end of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
catchIndex++;
extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
}
if (finallyLabel != null) {
// Reset values before analyzing the finally block!
tryStack.popFrame();
{
// Scan 'finallyBlock' for only 'finallyLabel' (a successful path)
addLabelForNextNode(finallyLabel);
extendWithNode(new MarkerNode(tree, "start of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(doneLabel));
}
if (hasExceptionalPath(exceptionalFinallyLabel)) {
// If an exceptional path exists, scan 'finallyBlock' for 'exceptionalFinallyLabel', and
// scan copied 'finallyBlock' for 'finallyLabel' (a successful path). If there is no
// successful path, it will be removed in later phase.
// TODO: Don't we need a separate finally block for each kind of exception?
addLabelForNextNode(exceptionalFinallyLabel);
extendWithNode(new MarkerNode(tree, "start of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
NodeWithExceptionsHolder throwing = extendWithNodeWithException(new MarkerNode(tree, "end of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()), throwableType);
throwing.setTerminatesExecution(true);
}
if (returnTargetL.wasAccessed()) {
addLabelForNextNode(returnTargetL.peekLabel());
returnTargetL = oldReturnTargetL;
extendWithNode(new MarkerNode(tree, "start of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(returnTargetL.accessLabel()));
} else {
returnTargetL = oldReturnTargetL;
}
if (breakTargetL.wasAccessed()) {
addLabelForNextNode(breakTargetL.peekLabel());
breakTargetL = oldBreakTargetL;
extendWithNode(new MarkerNode(tree, "start of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(breakTargetL.accessLabel()));
} else {
breakTargetL = oldBreakTargetL;
}
Map<Name, Label> accessedBreakLabels = ((TryFinallyScopeMap) breakLabels).getAccessedNames();
if (!accessedBreakLabels.isEmpty()) {
breakLabels = oldBreakLabels;
for (Map.Entry<Name, Label> access : accessedBreakLabels.entrySet()) {
addLabelForNextNode(access.getValue());
extendWithNode(new MarkerNode(tree, "start of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(breakLabels.get(access.getKey())));
}
} else {
breakLabels = oldBreakLabels;
}
if (continueTargetL.wasAccessed()) {
addLabelForNextNode(continueTargetL.peekLabel());
continueTargetL = oldContinueTargetL;
extendWithNode(new MarkerNode(tree, "start of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(continueTargetL.accessLabel()));
} else {
continueTargetL = oldContinueTargetL;
}
Map<Name, Label> accessedContinueLabels = ((TryFinallyScopeMap) continueLabels).getAccessedNames();
if (!accessedContinueLabels.isEmpty()) {
continueLabels = oldContinueLabels;
for (Map.Entry<Name, Label> access : accessedContinueLabels.entrySet()) {
addLabelForNextNode(access.getValue());
extendWithNode(new MarkerNode(tree, "start of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
scan(finallyBlock, p);
extendWithNode(new MarkerNode(tree, "end of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
extendWithExtendedNode(new UnconditionalJump(continueLabels.get(access.getKey())));
}
} else {
continueLabels = oldContinueLabels;
}
}
addLabelForNextNode(doneLabel);
return null;
}
use of com.sun.source.tree.TryTree in project error-prone by google.
the class FindIdentifiers method findAllIdents.
/**
* Finds the set of all bare variable identifiers in scope at the current location. Identifiers
* are ordered by ascending distance/scope count from the current location to match shadowing
* rules. That is, if two variables with the same simple names appear in the set, the one that
* appears first in iteration order is the one you get if you use the bare name in the source
* code.
*
* <p>We do not report variables that would require a qualfied access. We also do not handle
* wildcard imports.
*/
public static LinkedHashSet<VarSymbol> findAllIdents(VisitorState state) {
ImmutableSet.Builder<VarSymbol> result = new ImmutableSet.Builder<>();
Tree prev = state.getPath().getLeaf();
for (Tree curr : state.getPath().getParentPath()) {
switch(curr.getKind()) {
case BLOCK:
for (StatementTree stmt : ((BlockTree) curr).getStatements()) {
if (stmt.equals(prev)) {
break;
}
addIfVariable(stmt, result);
}
break;
case METHOD:
for (VariableTree param : ((MethodTree) curr).getParameters()) {
result.add(ASTHelpers.getSymbol(param));
}
break;
case CATCH:
result.add(ASTHelpers.getSymbol(((CatchTree) curr).getParameter()));
break;
case CLASS:
case INTERFACE:
case ENUM:
case ANNOTATION_TYPE:
// field is referred to by qualified name, but we don't support that.
for (Tree member : ((ClassTree) curr).getMembers()) {
if (member.equals(prev)) {
break;
}
addIfVariable(member, result);
}
// Collect inherited fields.
Type classType = ASTHelpers.getType(curr);
List<Type> classTypeClosure = state.getTypes().closure(classType);
List<Type> superTypes = classTypeClosure.size() <= 1 ? Collections.emptyList() : classTypeClosure.subList(1, classTypeClosure.size());
for (Type type : superTypes) {
Scope scope = type.tsym.members();
ImmutableList.Builder<VarSymbol> varsList = ImmutableList.builder();
for (Symbol var : scope.getSymbols(VarSymbol.class::isInstance)) {
varsList.add((VarSymbol) var);
}
result.addAll(varsList.build().reverse());
}
break;
case FOR_LOOP:
addAllIfVariable(((ForLoopTree) curr).getInitializer(), result);
break;
case ENHANCED_FOR_LOOP:
result.add(ASTHelpers.getSymbol(((EnhancedForLoopTree) curr).getVariable()));
break;
case TRY:
TryTree tryTree = (TryTree) curr;
boolean inResources = false;
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
inResources = true;
break;
}
}
if (inResources) {
// Case 1: we're in one of the resource declarations
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
break;
}
addIfVariable(resource, result);
}
} else if (tryTree.getBlock().equals(prev)) {
// Case 2: We're in the block (not a catch or finally)
addAllIfVariable(tryTree.getResources(), result);
}
break;
case COMPILATION_UNIT:
for (ImportTree importTree : ((CompilationUnitTree) curr).getImports()) {
if (importTree.isStatic() && importTree.getQualifiedIdentifier().getKind() == Kind.MEMBER_SELECT) {
MemberSelectTree memberSelectTree = (MemberSelectTree) importTree.getQualifiedIdentifier();
Scope scope = state.getTypes().membersClosure(ASTHelpers.getType(memberSelectTree.getExpression()), /* skipInterface= */
false);
for (Symbol var : scope.getSymbols(sym -> sym instanceof VarSymbol && sym.getSimpleName().equals(memberSelectTree.getIdentifier()))) {
result.add((VarSymbol) var);
}
}
}
break;
default:
// other node types don't introduce variables
break;
}
prev = curr;
}
// TODO(eaftan): switch out collector for ImmutableSet.toImmutableSet()
return result.build().stream().filter(var -> isVisible(var, state.getPath())).collect(Collectors.toCollection(LinkedHashSet::new));
}
use of com.sun.source.tree.TryTree in project error-prone by google.
the class WakelockReleasedDangerously method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
// Match on calls to any override of WakeLock.release().
if (!RELEASE.matches(tree, state)) {
return NO_MATCH;
}
// Ok if surrounded in try/catch block that catches RuntimeException.
TryTree enclosingTry = findEnclosingNode(state.getPath(), TryTree.class);
if (enclosingTry != null && tryCatchesException(enclosingTry, state.getSymtab().runtimeExceptionType, state)) {
return NO_MATCH;
}
// Ok if WakeLock not in danger of unexpected exception.
// Also, can't perform analysis if WakeLock symbol not found.
Symbol wakelockSymbol = getSymbol(getReceiver(tree));
if (wakelockSymbol == null || !wakelockMayThrow(wakelockSymbol, state)) {
return NO_MATCH;
}
Tree releaseStatement = state.getPath().getParentPath().getLeaf();
return describeMatch(releaseStatement, getFix(releaseStatement, wakelockSymbol, state));
}
use of com.sun.source.tree.TryTree in project error-prone by google.
the class ThreadJoinLoop method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState visitorState) {
String threadString;
if (methodInvocationTree.getMethodSelect() instanceof MemberSelectTree) {
threadString = ((MemberSelectTree) methodInvocationTree.getMethodSelect()).getExpression().toString();
} else {
threadString = "this";
}
// with calculating time with declared variables)
if (!methodInvocationTree.getArguments().isEmpty()) {
return Description.NO_MATCH;
}
if (MATCH_THREAD_JOIN.matches(methodInvocationTree, visitorState)) {
TreePath treePath = ASTHelpers.findPathFromEnclosingNodeToTopLevel(visitorState.getPath(), TryTree.class);
if (treePath == null) {
return Description.NO_MATCH;
}
TreePath pathToLoop = ASTHelpers.findPathFromEnclosingNodeToTopLevel(treePath, WhileLoopTree.class);
// checks to make sure that if there is a while loop with only one statement (the try catch
// block)
boolean hasWhileLoopOneStatement = false;
if (pathToLoop != null) {
Tree statements = ((WhileLoopTree) pathToLoop.getLeaf()).getStatement();
if (statements instanceof BlockTree) {
if (((BlockTree) statements).getStatements().size() == 1) {
hasWhileLoopOneStatement = true;
}
}
}
Type interruptedType = visitorState.getSymtab().interruptedExceptionType;
Type exceptionType = visitorState.getSymtab().exceptionType;
TryTree tryTree = (TryTree) treePath.getLeaf();
// scans the try tree block for any other actions so that we do not accidentally delete
// important actions when replacing
TreeScannerMethodInvocations treeScanner = new TreeScannerMethodInvocations();
treeScanner.scan(tryTree.getBlock(), methodInvocationTree.toString());
if (treeScanner.count > 0) {
return Description.NO_MATCH;
}
if (tryTree.getFinallyBlock() != null) {
return Description.NO_MATCH;
}
List<? extends CatchTree> catches = tryTree.getCatches();
for (CatchTree tree : catches) {
Type typeSym = ASTHelpers.getType(tree.getParameter().getType());
if (Objects.equals(interruptedType, typeSym) || Objects.equals(exceptionType, typeSym)) {
List<? extends StatementTree> statementTrees = tree.getBlock().getStatements();
// replaces the while loop with the try block or replaces just the try block
if (statementTrees.isEmpty() || (statementTrees.size() == 1 && statementTrees.get(0).toString().equals(";"))) {
SuggestedFix.Builder builder = SuggestedFix.builder();
builder.replace(hasWhileLoopOneStatement ? pathToLoop.getLeaf() : tryTree, "Uninterruptibles.joinUninterruptibly(" + threadString + ");");
builder.addImport("com.google.common.util.concurrent.Uninterruptibles");
return describeMatch(methodInvocationTree, builder.build());
}
}
}
}
return Description.NO_MATCH;
}
Aggregations