private static Scope getDeepestCommonScope(Symbol symbol, Usage declaration) { Set<Usage> usages = new HashSet<>(symbol.usages()); if (!declaration.isWrite()) { usages.remove(declaration); } Map<Scope, Integer> scopeDepthMap = new HashMap<>(); for (Usage usage : usages) { Scope scope = usage.identifierTree().scope(); scopeDepthMap.put(scope, getScopeDepth(scope)); } int minDepth = Collections.min(scopeDepthMap.values()); Set<Scope> sameDepthScopes = new HashSet<>(); for (Entry<Scope, Integer> entry : scopeDepthMap.entrySet()) { sameDepthScopes.add(getAncestorScope(entry.getKey(), entry.getValue() - minDepth)); } while (sameDepthScopes.size() != 1) { sameDepthScopes = outerScopes(sameDepthScopes); } return sameDepthScopes.iterator().next(); }
private void visitSymbol(Symbol symbol) { Usage declaration = getOnlyDeclaration(symbol); if (declaration != null && symbol.usages().size() > 1) { Scope deepestCommonScope = getDeepestCommonScope(symbol, declaration); Scope declarationScope = declaration.identifierTree().scope(); if (!deepestCommonScope.equals(declarationScope) && !isFunctionException(deepestCommonScope, declarationScope) && deadVariableInScope(symbol, deepestCommonScope, declarationScope, declaration.identifierTree())) { String message = String.format(MESSAGE, symbol.name(), deepestCommonScope.tree().firstToken().line() + 1); addIssue(declaration.identifierTree(), message); } } }
@Override public void visitCallExpression(CallExpressionTree tree) { if (tree.callee().is(Kind.IDENTIFIER_REFERENCE)) { IdentifierTree callee = (IdentifierTree) tree.callee(); if (callee.scope().isGlobal()) { String name = callee.name(); SeparatedList<ExpressionTree> parameters = tree.argumentClause().arguments(); if (isAmdImport(name, parameters) || isCommonJsImport(name, parameters)) { addIssue(tree.callee(), String.format(MESSAGE, name)); } } } }