private void checkName(Tree tree) { if (tree instanceof IdentifierTree) { String name = ((IdentifierTree) tree).name(); if (!pattern.matcher(name).matches()) { addIssue(tree, String.format(MESSAGE, name, format)); } } } }
private static Token getToken(IdentifierTree identifierTree) { return ((InternalSyntaxToken) (identifierTree).identifierToken()).getToken(); } }
@Override public void visitIdentifier(IdentifierTree identifier) { if (identifier.is(Kind.IDENTIFIER_REFERENCE) && !identifier.symbol().isPresent() && !"undefined".equals(identifier.name()) && !excludedNames.contains(identifier.name())) { undeclaredIdentifiersByName.put(identifier.name(), identifier); } super.visitIdentifier(identifier); }
private static Set<Usage> getExcludedProperties(Usage usage) { Set<Usage> excludedProperties = new HashSet<>(); Tree parent = usage.identifierTree().parent(); if (parent.is(Kind.OBJECT_BINDING_PATTERN) && hasUsedRestElement((ObjectBindingPatternTree) parent)) { ((ObjectBindingPatternTree) parent).elements().stream() .filter(element -> element.is(Kind.BINDING_IDENTIFIER)) .forEach(element -> ((IdentifierTree) element).symbolUsage().ifPresent(excludedProperties::add)); } return excludedProperties; }
private void checkExpression(DotMemberExpressionTree expression) { if (!expression.object().is(Kind.IDENTIFIER_REFERENCE) || !expression.property().is(Kind.PROPERTY_IDENTIFIER)) { return; } String object = ((IdentifierTree) expression.object()).name(); String property = (expression.property()).name(); if (ARGUMENTS.equals(object)) { checkArgumentsProperty(expression, property); } else if (scope.contains(object)) { checkFunctionsProperty(expression, object, property); } }
@Override public void visitFunctionDeclaration(FunctionDeclarationTree tree) { Preconditions.checkState(tree.name().symbol() != null, String.format("Symbol has not been created for this function %s declared at line %s", tree.name().name(), ((JavaScriptTree) tree).getLine())); super.visitFunctionDeclaration(tree); tree.name().symbol().addType(FunctionType.create(tree)); }
private static boolean sameSymbol(Symbol objectSymbol, IdentifierTree lastIdentifier) { Optional<Symbol> bindingSymbol = lastIdentifier.symbol(); return bindingSymbol.map(symbol -> symbol.equals(objectSymbol)).orElse(false); }
@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)); } } } }
@Override public void visitIdentifier(IdentifierTree tree) { if (tree.is(Kind.IDENTIFIER_REFERENCE)) { identifier = tree; } }
/** * Returns the ClassTree, if any, where the specified symbol has been declared. * If the symbol has been declared more that once, returns any of these declarations. */ private static Optional<ClassTree> getDeclarationTree(Symbol symbol) { Optional<Usage> tree = symbol.usages().stream() .filter(Usage::isDeclaration) .findFirst(); if (tree.isPresent()) { IdentifierTree id = tree.get().identifierTree(); Tree parent = id.parent(); if (parent.is(Kind.CLASS_DECLARATION, Kind.CLASS_EXPRESSION)) { return Optional.of((ClassTree) parent); } } return Optional.empty(); }
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 static int getColumn(Symbol symbol) { return getDeclarationUsage(symbol).identifierTree().firstToken().column(); }
@Override public void visitNode(Tree tree) { if (tree.is(Kind.DEFAULT_EXPORT_DECLARATION)) { Tree exported = ((DefaultExportDeclarationTree) tree).object(); if (exported.is(Kind.IDENTIFIER_REFERENCE)) { Optional<Symbol> symbol = ((IdentifierTree) exported).symbol(); if (symbol.isPresent() && CONSIDERED_KINDS.contains(symbol.get().kind())) { nameOfExported = symbol.get().name(); } } else if (exported.is(Kind.CLASS_DECLARATION)) { nameOfExported = ((ClassTree) exported).name().name(); } else if (exported.is(Kind.FUNCTION_DECLARATION)) { nameOfExported = ((FunctionDeclarationTree) exported).name().name(); } } else { isOnlyExport = false; } }
private void checkExpression(DotMemberExpressionTree expression) { if (!expression.object().is(Kind.IDENTIFIER_REFERENCE) || !expression.property().is(Kind.IDENTIFIER_NAME)) { return; } String object = ((IdentifierTree) expression.object()).name(); String property = (expression.property()).name(); if (ARGUMENTS.equals(object)) { checkArgumentsProperty(expression, property); } else if (scope.contains(object)) { checkFunctionsProperty(expression, object, property); } }
@Nullable private static Symbol getSymbol(ExpressionTree object) { if (object.is(Kind.IDENTIFIER_REFERENCE)) { return ((IdentifierTree) object).symbol().orElse(null); } return null; }
@Override public void visitIdentifier(IdentifierTree identifier) { if (identifier.is(Kind.THIS)) { collectionOfThiss.add(identifier); } }
private static boolean isWriteUsage(Usage usage) { if (usage.isWrite()) { return true; } return usage.identifierTree().parent().is(Tree.Kind.DOT_MEMBER_EXPRESSION, Tree.Kind.BRACKET_MEMBER_EXPRESSION, Tree.Kind.CALL_EXPRESSION); }
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); } } }
private static boolean propertyIsDeprecated(ExpressionTree property, List<String> deprecated) { if (property.is(Tree.Kind.IDENTIFIER_NAME)){ IdentifierTree identifier = (IdentifierTree) property; return deprecated.contains(identifier.name()); } return false; } }
private void inferParameterType(CallExpressionTree tree) { Type functionType = tree.callee().types().getUniqueType(Type.Kind.FUNCTION); if (functionType != null) { SeparatedList<Tree> parameters = ((FunctionType)functionType).functionTree().parameters().parameters(); SeparatedList<Tree> arguments = tree.arguments().parameters(); int minSize = arguments.size() < parameters.size() ? arguments.size() : parameters.size(); for (int i = 0; i < minSize; i++) { Preconditions.checkState(arguments.get(i) instanceof ExpressionTree); Tree currentParameter = parameters.get(i); if (currentParameter instanceof IdentifierTree) { Symbol symbol = ((IdentifierTree) currentParameter).symbol(); if (symbol != null) { addTypes(symbol, ((ExpressionTree) arguments.get(i)).types()); } else { throw new IllegalStateException(String.format( "Parameter %s has no symbol associated with it (line %s)", ((IdentifierTree) currentParameter).name(), ((JavaScriptTree) currentParameter).getLine() )); } } } } }