function cb(node) { switch (node.kind) { case ts.SyntaxKind.ClassDeclaration: checkNode(node, exports.ARGUMENT_CLASSES); break; case ts.SyntaxKind.EnumDeclaration: checkNode(node, exports.ARGUMENT_ENUMS); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; // Enum members don't have modifiers, so use the parent // enum declaration when checking the requirements. checkNode(member, exports.ARGUMENT_ENUM_MEMBERS, node); } break; case ts.SyntaxKind.FunctionDeclaration: checkNode(node, exports.ARGUMENT_FUNCTIONS); break; case ts.SyntaxKind.InterfaceDeclaration: checkNode(node, exports.ARGUMENT_INTERFACES); break; case ts.SyntaxKind.MethodDeclaration: if (node.parent.kind !== ts.SyntaxKind.ObjectLiteralExpression) { checkNode(node, exports.ARGUMENT_METHODS); } break; case ts.SyntaxKind.ModuleDeclaration: checkNode(node, exports.ARGUMENT_NAMESPACES); break; case ts.SyntaxKind.PropertyDeclaration: checkNode(node, exports.ARGUMENT_PROPERTIES); break; case ts.SyntaxKind.TypeAliasDeclaration: checkNode(node, exports.ARGUMENT_TYPES); break; case ts.SyntaxKind.VariableStatement: // Only check variables at the namespace/module-level or file-level // and not variables declared inside functions and other things. switch (node.parent.kind) { case ts.SyntaxKind.SourceFile: case ts.SyntaxKind.ModuleBlock: for (var _b = 0, _c = node.declarationList.declarations; _b < _c.length; _b++) { var declaration = _c[_b]; checkNode(declaration, exports.ARGUMENT_VARIABLES, node); } } break; case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: if (node.parent.kind !== ts.SyntaxKind.ObjectLiteralExpression) { checkNode(node, exports.ARGUMENT_PROPERTIES); } } return ts.forEachChild(node, cb); }
var cb = function (node) { if (shouldCheck(node, _this.options)) { var name = node.name, type = node.type, initializer = node.initializer; if (type !== undefined && initializer !== undefined && typeIsInferrable(type.kind, initializer)) { var fix = Lint.Replacement.deleteFromTo(name.end, type.end); _this.addFailureAtNode(type, Rule.FAILURE_STRING_FACTORY(ts.tokenToString(type.kind)), fix); } } return ts.forEachChild(node, cb); };
function handleConstructor(node) { scope.enterConstructor(); for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; if (utils.isModifierFlagSet(parameter, ts.ModifierFlags.Private)) { scope.addDeclaredVariable(parameter); } } ts.forEachChild(node, visitNode); scope.exitConstructor(); }
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isNewExpression(node) && node.expression.kind === ts.SyntaxKind.Identifier) { switch (node.expression.text) { case "Boolean": case "String": case "Number": ctx.addFailure(node.getStart(ctx.sourceFile), node.expression.end, Rule.FAILURE_STRING); } } return ts.forEachChild(node, cb); });
function walk(ctx, allowSingleConcat) { return ts.forEachChild(ctx.sourceFile, function cb(node) { var failure = getError(node, allowSingleConcat); if (failure !== undefined) { ctx.addFailureAtNode(node, failure); } else { return ts.forEachChild(node, cb); } }); }
function walk(ctx) { var sourceFile = ctx.sourceFile; return ts.forEachChild(sourceFile, function cb(node) { if (tsutils_1.isNumericLiteral(node)) { return check(node); } return ts.forEachChild(node, cb); }); function check(node) { // Apparently the number literal '0.0' has a '.text' of '0', so use '.getText()' instead. var text = node.getText(sourceFile); if (text.length <= 1) { return; } if (text.startsWith("0")) { // Hex/octal/binary number can't have decimal point or exponent, so no other errors possible. switch (text[1]) { case "x": if (!utils_1.isUpperCase(text.slice(2))) { ctx.addFailureAtNode(node, Rule.FAILURE_STRING_NOT_UPPERCASE); } return; case "o": case "b": return; case ".": break; default: ctx.addFailureAtNode(node, Rule.FAILURE_STRING_LEADING_0); return; } } var _a = text.split(/e/i), num = _a[0], exp = _a[1]; if (exp !== undefined && (exp.startsWith("-0") || exp.startsWith("0"))) { ctx.addFailureAt(node.getEnd() - exp.length, exp.length, Rule.FAILURE_STRING_LEADING_0); } if (!num.includes(".")) { return; } if (num.startsWith(".")) { fail(Rule.FAILURE_STRING_LEADING_DECIMAL); } if (num.endsWith(".")) { fail(Rule.FAILURE_STRING_TRAILING_DECIMAL); } // Allow '10', but not '1.0' if (num.endsWith("0")) { fail(Rule.FAILURE_STRING_TRAILING_0); } function fail(message) { ctx.addFailureAt(node.getStart(sourceFile), num.length, message); } } }
// Find all nodes from the AST in the subtree of node of SyntaxKind kind. function collectDeepNodes(node, kind) { const nodes = []; const helper = (child) => { if (child.kind === kind) { nodes.push(child); } ts.forEachChild(child, helper); }; ts.forEachChild(node, helper); return nodes; }
return ts.forEachChild(ctx.sourceFile, function recur(node) { if (tsutils_1.isClassLikeDeclaration(node)) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var child = _a[_i]; if (shouldCheck(child)) { check(child); } } } return ts.forEachChild(node, recur); });
TypedefWhitespaceWalker.prototype.walk = function (sourceFile) { var _this = this; var cb = function (node) { var optionType = getOptionType(node); if (optionType !== undefined) { _this.checkSpace(node, optionType); } return ts.forEachChild(node, cb); }; return ts.forEachChild(sourceFile, cb); };
function handleNode(node) { switch (node.kind) { case ts.SyntaxKind.ImportDeclaration: imports.push(node.moduleSpecifier.text); break; case ts.SyntaxKind.ImportEqualsDeclaration: imports.push(node.moduleReference.expression.text); break; } ts.forEachChild(node, handleNode); }
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) { var tc = program.getTypeChecker(); var leftType = getBaseTypeOfLiteralType(tc.getTypeAtLocation(node.left)); var rightType = getBaseTypeOfLiteralType(tc.getTypeAtLocation(node.right)); if (leftType === "invalid" || rightType === "invalid" || leftType !== rightType) { return ctx.addFailureAtNode(node, Rule.INVALID_TYPES_ERROR); } } return ts.forEachChild(node, cb); });
function visit(node) { readThrough(node); var replacement = replacer(node); if (replacement != null) { code += replacement; skip(node); } else { ts.forEachChild(node, visit); } }
function findNode(node, kind, text) { if (node.kind === kind && node.getText() === text) { // throw new Error(node.getText()); return node; } let foundNode = null; ts.forEachChild(node, childNode => { foundNode = foundNode || findNode(childNode, kind, text); }); return foundNode; }
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (node.kind === ts.SyntaxKind.ForInStatement) { var type = program.getTypeChecker().getTypeAtLocation(node.expression); if (type.symbol !== undefined && type.symbol.name === "Array" || // tslint:disable-next-line:no-bitwise (type.flags & ts.TypeFlags.StringLike) !== 0) { ctx.addFailureAtNode(node, Rule.FAILURE_STRING); } } return ts.forEachChild(node, cb); });
return ts.forEachChild(sourceFile, function cb(node) { switch (node.kind) { case ts.SyntaxKind.ArrayType: checkArrayType(node); break; case ts.SyntaxKind.TypeReference: checkTypeReference(node); break; } return ts.forEachChild(node, cb); });
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (node.kind === ts.SyntaxKind.Constructor) { for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; if (tsutils_1.isParameterProperty(parameter)) { ctx.addFailure(parameter.getStart(ctx.sourceFile), parameter.name.pos, Rule.FAILURE_STRING_FACTORY(parameter.name.getText(ctx.sourceFile))); } } } return ts.forEachChild(node, cb); });
return ts.forEachChild(sourceFile, function cb(node) { if (utils.isArrowFunction(node) && utils.isBlock(node.body)) { var expr = getSimpleReturnExpression(node.body); if (expr !== undefined && (multiline || utils.isSameLine(sourceFile, node.body.getStart(sourceFile), node.body.end))) { var isObjectLiteral = expr.kind === ts.SyntaxKind.ObjectLiteralExpression; ctx.addFailureAtNode(node.body, Rule.FAILURE_STRING(isObjectLiteral), createFix(node, node.body, expr, sourceFile.text)); } } return ts.forEachChild(node, cb); });
var cb = function (node) { if (node.kind >= ts.SyntaxKind.FirstTemplateToken && node.kind <= ts.SyntaxKind.LastTemplateToken) { intervals.push({ end: node.end, pos: node.getStart(sourceFile), }); } else { return ts.forEachChild(node, cb); } };
var cb = function (node) { if (tsutils_1.isCallExpression(node) && tsutils_1.isIdentifier(node.expression) && node.expression.text === "parseInt") { return node.arguments.length === 0 ? undefined : cb(node.arguments[0]); } if (node.kind === ts.SyntaxKind.NumericLiteral) { return _this.checkNumericLiteral(node, node.text); } if (utils_1.isNegativeNumberLiteral(node)) { return _this.checkNumericLiteral(node, "-" + node.operand.text); } return ts.forEachChild(node, cb); };
function findTopLevelFunctions(parentNode) { const topLevelFunctions = new Set(); function cb(node) { // Stop recursing into this branch if it's a definition construct. // These are function expression, function declaration, class, or arrow function (lambda). // The body of these constructs will not execute when loading the module, so we don't // need to mark function calls inside them as pure. // Class static initializers in ES2015 are an exception we don't cover. They would need similar // processing as enums to prevent property setting from causing the class to be retained. if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isClassDeclaration(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)) { return; } let noPureComment = !hasPureComment(node); let innerNode = node; while (innerNode && ts.isParenthesizedExpression(innerNode)) { innerNode = innerNode.expression; noPureComment = noPureComment && !hasPureComment(innerNode); } if (!innerNode) { return; } if (noPureComment) { if (ts.isNewExpression(innerNode)) { topLevelFunctions.add(node); } else if (ts.isCallExpression(innerNode)) { let expression = innerNode.expression; while (expression && ts.isParenthesizedExpression(expression)) { expression = expression.expression; } if (expression) { if (ts.isFunctionExpression(expression)) { // Skip IIFE's with arguments // This could be improved to check if there are any references to variables if (innerNode.arguments.length === 0) { topLevelFunctions.add(node); } } else { topLevelFunctions.add(node); } } } } ts.forEachChild(innerNode, cb); } ts.forEachChild(parentNode, cb); return topLevelFunctions; }
function findClassDeclarations(node) { const classes = []; // Find all class declarations, build a ClassData for each. ts.forEachChild(node, (child) => { if (child.kind !== ts.SyntaxKind.VariableStatement) { return; } const varStmt = child; if (varStmt.declarationList.declarations.length > 1) { return; } const varDecl = varStmt.declarationList.declarations[0]; if (varDecl.name.kind !== ts.SyntaxKind.Identifier) { return; } const name = varDecl.name.text; const expr = varDecl.initializer; if (!expr || expr.kind !== ts.SyntaxKind.ParenthesizedExpression) { return; } if (expr.expression.kind !== ts.SyntaxKind.CallExpression) { return; } const callExpr = expr.expression; if (callExpr.expression.kind !== ts.SyntaxKind.FunctionExpression) { return; } const fn = callExpr.expression; if (fn.body.statements.length < 2) { return; } if (fn.body.statements[0].kind !== ts.SyntaxKind.FunctionDeclaration) { return; } const innerFn = fn.body.statements[0]; if (fn.body.statements[fn.body.statements.length - 1].kind !== ts.SyntaxKind.ReturnStatement) { return; } if (!innerFn.name || innerFn.name.kind !== ts.SyntaxKind.Identifier) { return; } if (innerFn.name.text !== name) { return; } classes.push({ name, class: varDecl, classFunction: fn, statements: [], }); }); return classes; }
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isPropertySignature(node)) { var type = node.type; if (type !== undefined && tsutils_1.isFunctionTypeNode(type)) { ctx.addFailureAtNode(node.name, Rule.FAILURE_STRING, type.type === undefined ? undefined : [ Lint.Replacement.deleteFromTo(Lint.childOfKind(node, ts.SyntaxKind.ColonToken).getStart(), type.getStart()), Lint.Replacement.replaceFromTo(Lint.childOfKind(type, ts.SyntaxKind.EqualsGreaterThanToken).pos, type.type.pos, ":"), ]); } } return ts.forEachChild(node, cb); });
var cb = function (node) { if (tsutils_1.isIterationStatement(node)) { _this.checkStatement(node.statement, node, 0, node.end); } else if (tsutils_1.isIfStatement(node)) { _this.checkStatement(node.thenStatement, node, 0); if (node.elseStatement !== undefined && node.elseStatement.kind !== ts.SyntaxKind.IfStatement) { _this.checkStatement(node.elseStatement, node, 5); } } return ts.forEachChild(node, cb); };
// 1) If TS sees an empty decorator array, it will still emit a `__decorate` call. // This seems to be a TS bug. // 2) Also ensure nodes with modified decorators have parents // built in TS transformers assume certain nodes have parents (fixed in TS 2.7+) function cleanupDecorators(node) { if (node.decorators) { if (node.decorators.length == 0) { node.decorators = undefined; } else if (node.parent == undefined) { const originalNode = ts.getParseTreeNode(node); node.parent = originalNode.parent; } } ts.forEachChild(node, node => cleanupDecorators(node)); }
function cb(node) { if (node.kind === ts.SyntaxKind.ImportDeclaration && node.importClause) { // Save the path of the import transformed into snake case and remove relative paths. const moduleSpecifier = node.moduleSpecifier; const pureImport = moduleSpecifier.text .replace(/[\/@\-]/g, '_') .replace(/^\.+/, ''); pureImports.push(pureImport); } ts.forEachChild(node, cb); }
function fixupParentReferences(sourceFile) { "use strict"; var parent = sourceFile; function walk(n) { n.parent = parent; var saveParent = parent; parent = n; ts.forEachChild(n, walk); parent = saveParent; } ts.forEachChild(sourceFile, walk); }
function walk(ctx, tc) { return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isPropertyAccessExpression(node) && !isSafeUse(node)) { var symbol = tc.getSymbolAtLocation(node); var declaration = symbol === undefined ? undefined : symbol.valueDeclaration; if (declaration !== undefined && isMethod(declaration, ctx.options.ignoreStatic)) { ctx.addFailureAtNode(node, Rule.FAILURE_STRING); } } return ts.forEachChild(node, cb); }); }
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isThrowStatement(node)) { var expression = node.expression; if (isString(expression)) { ctx.addFailureAtNode(node, Rule.FAILURE_STRING, [ Lint.Replacement.appendText(expression.getStart(sourceFile), "new Error("), Lint.Replacement.appendText(expression.getEnd(), ")"), ]); } } return ts.forEachChild(node, cb); });
return ts.forEachChild(ctx.sourceFile, function cb(node) { if (tsutils_1.isBinaryExpression(node)) { if ((node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken || node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken) && !(isExpressionAllowed(node.right, ctx.options) || isExpressionAllowed(node.left, ctx.options))) { ctx.addFailureAtNode(node.operatorToken, node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ? Rule.EQ_FAILURE_STRING : Rule.NEQ_FAILURE_STRING); } } return ts.forEachChild(node, cb); });
TrailingCommaWalker.prototype.walk = function (sourceFile) { var _this = this; var cb = function (node) { switch (node.kind) { case ts.SyntaxKind.ArrayLiteralExpression: case ts.SyntaxKind.ArrayBindingPattern: _this.checkList(node.elements, node.end, "arrays"); break; case ts.SyntaxKind.ObjectBindingPattern: _this.checkList(node.elements, node.end, "objects"); break; case ts.SyntaxKind.NamedImports: _this.checkList(node.elements, node.end, "imports"); break; case ts.SyntaxKind.NamedExports: _this.checkList(node.elements, node.end, "exports"); break; case ts.SyntaxKind.ObjectLiteralExpression: _this.checkList(node.properties, node.end, "objects"); break; case ts.SyntaxKind.EnumDeclaration: _this.checkList(node.members, node.end, "objects"); break; case ts.SyntaxKind.NewExpression: if (node.arguments === undefined) { break; } // falls through case ts.SyntaxKind.CallExpression: _this.checkList(node.arguments, node.end, "functions"); break; case ts.SyntaxKind.ArrowFunction: case ts.SyntaxKind.Constructor: case ts.SyntaxKind.FunctionDeclaration: case ts.SyntaxKind.FunctionExpression: case ts.SyntaxKind.MethodDeclaration: case ts.SyntaxKind.SetAccessor: case ts.SyntaxKind.MethodSignature: case ts.SyntaxKind.ConstructSignature: case ts.SyntaxKind.ConstructorType: case ts.SyntaxKind.FunctionType: case ts.SyntaxKind.CallSignature: _this.checkListWithEndToken(node, node.parameters, ts.SyntaxKind.CloseParenToken, "functions"); break; case ts.SyntaxKind.TypeLiteral: _this.checkTypeLiteral(node); break; default: } return ts.forEachChild(node, cb); }; return ts.forEachChild(sourceFile, cb); };