// @module: commonjs // @skipLibCheck: true // @includebuiltfile: typescriptServices.d.ts // @noImplicitAny:true // @strictNullChecks:true // @filename: node_modules/typescript/index.d.ts declare module "typescript" { export = ts; } // @filename: APISample_linter.ts /* * Note: This test is a public API sample. The sample sources can be found * at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#traversing-the-ast-with-a-little-linter * Please log a "breaking change" issue for any API breaking change affecting this issue */ declare var process: any; declare var console: any; declare var readFileSync: any; import * as ts from "typescript"; export function delint(sourceFile: ts.SourceFile) { delintNode(sourceFile); function delintNode(node: ts.Node) { switch (node.kind) { case ts.SyntaxKind.ForStatement: case ts.SyntaxKind.ForInStatement: case ts.SyntaxKind.WhileStatement: case ts.SyntaxKind.DoStatement: if ((node).statement.kind !== ts.SyntaxKind.Block) { report(node, "A looping statement's contents should be wrapped in a block body."); } break; case ts.SyntaxKind.IfStatement: let ifStatement = (node); if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) { report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body."); } if (ifStatement.elseStatement && ifStatement.elseStatement.kind !== ts.SyntaxKind.Block && ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) { report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body."); } break; case ts.SyntaxKind.BinaryExpression: let op = (node).operatorToken.kind; if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) { report(node, "Use '===' and '!=='.") } break; } ts.forEachChild(node, delintNode); } function report(node: ts.Node, message: string) { let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`); } } const fileNames: string[] = process.argv.slice(2); fileNames.forEach(fileName => { // Parse a file let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES2015, /*setParentNodes */ true); // delint it delint(sourceFile); });