diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000000..ffe06abf2d682 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +/built/local/** +/tests/** +/lib/** \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000000..9d473154a846f --- /dev/null +++ b/.eslintrc @@ -0,0 +1,121 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "warnOnUnsupportedTypeScriptVersion": false, + "ecmaVersion": 6, + "sourceType": "module", + "project": "./src/tsconfig-base.json" + }, + "env": { + "browser": false, + "node": true, + "es6": true + }, + "plugins": [ + "@typescript-eslint", "microsoft-typescript" + ], + "rules": { + "@typescript-eslint/adjacent-overload-signatures": "off", + "@typescript-eslint/array-type": "off", + "@typescript-eslint/ban-types": "off", + "camelcase": "off", + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/class-name-casing": "off", + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/import/order": "off", + "indent": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/member-ordering": "off", + "@typescript-eslint/no-angle-bracket-type-assertion": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-object-literal-type-assertion": "off", + "@typescript-eslint/no-parameter-properties": "off", + "@typescript-eslint/no-this-alias": "off", + "@typescript-eslint/no-triple-slash-reference": "off", + "@typescript-eslint/no-unnecessary-qualifier": "off", + "@typescript-eslint/no-unnecessary-type-assertion": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "off", + "@typescript-eslint/prefer-interface": "off", + "@typescript-eslint/prefer-namespace-keyword": "off", + "semi": "off", + "@typescript-eslint/semi": "off", + "@typescript-eslint/type-annotation-spacing": "off", + "@typescript-eslint/unified-signatures": "off", + + "microsoft-typescript/object-literal-surrounding-space": "off", + "microsoft-typescript/no-type-assertion-whitespace": "error", + "microsoft-typescript/type-operator-spacing": "off", + "microsoft-typescript/only-arrow-functions": "off", + "microsoft-typescript/no-double-space": "off", + "microsoft-typescript/boolean-trivia": "off", + "microsoft-typescript/no-in-operator": "off", + "microsoft-typescript/debug-assert": "off", + "microsoft-typescript/no-keywords": "off", + + "arrow-body-style": "off", + "arrow-parens": "off", + "brace-style": "off", + "comma-dangle": "off", + "complexity": "off", + "constructor-super": "error", + "curly": ["error", "multi-line"], + "dot-notation": "off", + "eol-last": "off", + "eqeqeq": "error", + "guard-for-in": "off", + "linebreak-style": "off", + "max-classes-per-file": "off", + "max-len": "off", + "new-parens": "error", + "no-bitwise": "off", + "no-caller": "error", + "no-cond-assign": "off", + "no-console": "off", + "no-debugger": "off", + "no-duplicate-case": "error", + "no-duplicate-imports": "error", + "no-empty": "off", + "no-eval": "off", + "no-extra-bind": "error", + "no-fallthrough": "off", + "no-invalid-this": "off", + "no-multiple-empty-lines": "off", + "no-new-func": "off", + "no-new-wrappers": "error", + "no-redeclare": "off", + "no-return-await": "error", + "no-restricted-globals": "off", + "no-sequences": "off", + "no-shadow": "off", + "no-sparse-arrays": "error", + "no-template-curly-in-string": "off", + "no-throw-literal": "off", + "no-trailing-spaces": "off", + "no-undef-init": "error", + "no-unsafe-finally": "error", + "no-unused-expressions": "off", + "no-unused-labels": "error", + "no-var": "off", + "object-shorthand": "off", + "one-var": "off", + "prefer-const": "off", + "prefer-object-spread": "error", + "quote-props": ["error", "consistent-as-needed"], + "quotes": "off", + "radix": "off", + "sort-keys": "off", + "space-before-function-paren": "off", + "space-in-parens": "off", + "unicode-bom": ["error", "never"], + "use-isnan": "error", + "valid-typeof": "off" + } +} diff --git a/Gulpfile.js b/Gulpfile.js index bfc4bf43db724..16d15164a9042 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -318,34 +318,23 @@ task("clean-tests").description = "Cleans the outputs for the test infrastructur const watchTests = () => watchProject("src/testRunner", cmdLineOptions); -const buildRules = () => buildProject("scripts/tslint"); -task("build-rules", buildRules); -task("build-rules").description = "Compiles tslint rules to js"; - -const cleanRules = () => cleanProject("scripts/tslint"); -cleanTasks.push(cleanRules); -task("clean-rules", cleanRules); -task("clean-rules").description = "Cleans the outputs for the lint rules"; - const lintFoldStart = async () => { if (fold.isTravis()) console.log(fold.start("lint")); }; const lintFoldEnd = async () => { if (fold.isTravis()) console.log(fold.end("lint")); }; -const lint = series([ - lintFoldStart, - ...["scripts/tslint/tsconfig.json", "src/tsconfig-base.json"].map(project => { - const lintOne = () => { - const args = ["node_modules/tslint/bin/tslint", "--project", project, "--formatters-dir", "./built/local/tslint/formatters", "--format", "autolinkableStylish"]; - if (cmdLineOptions.fix) args.push("--fix"); - log(`Linting: node ${args.join(" ")}`); - return exec(process.execPath, args); - }; - lintOne.dispayName = `lint(${project})`; - return lintOne; - }), - lintFoldEnd -]); +const eslint = async () => { + const args = [ + "node_modules/eslint/bin/eslint", "-f", "autolinkable-stylish", "-c", ".eslintrc", "--ext", ".ts", "." + ]; + + if (cmdLineOptions.fix) { + args.push("--fix"); + } + log(`Linting: ${args.join(" ")}`); + return exec(process.execPath, args); +} +const lint = series([lintFoldStart, eslint, lintFoldEnd]); lint.displayName = "lint"; -task("lint", series(buildRules, lint)); -task("lint").description = "Runs tslint on the compiler sources."; +task("lint", lint); +task("lint").description = "Runs eslint on the compiler sources."; task("lint").flags = { " --f[iles]=": "pattern to match files to lint", }; @@ -393,7 +382,7 @@ const generateCodeCoverage = () => exec("istanbul", ["cover", "node_modules/moch task("generate-code-coverage", series(preBuild, buildTests, generateCodeCoverage)); task("generate-code-coverage").description = "Generates code coverage data via istanbul"; -const preTest = parallel(buildRules, buildTests, buildServices, buildLssl); +const preTest = parallel(buildTests, buildServices, buildLssl); preTest.displayName = "preTest"; const postTest = (done) => cmdLineOptions.lint ? lint(done) : done(); diff --git a/README.md b/README.md index 04c8c7dbbcc36..7cd7a235bc9b1 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ gulp runtests # Run tests using the built compiler and test infrastructu # You can override the host or specify a test for this command. # Use --host= or --tests=. gulp baseline-accept # This replaces the baseline test results with the results obtained from gulp runtests. -gulp lint # Runs tslint on the TypeScript source. +gulp lint # Runs eslint on the TypeScript source. gulp help # List the above commands. ``` diff --git a/package.json b/package.json index 965c0c3bb32b1..9fab8be64e6bf 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,8 @@ "@types/through2": "latest", "@types/travis-fold": "latest", "@types/xml2js": "^0.4.0", + "@typescript-eslint/eslint-plugin": "latest", + "@typescript-eslint/parser": "latest", "azure-devops-node-api": "^8.0.0", "browser-resolve": "^1.11.2", "browserify": "latest", @@ -61,6 +63,9 @@ "chalk": "latest", "convert-source-map": "latest", "del": "latest", + "eslint": "latest", + "eslint-formatter-autolinkable-stylish": "latest", + "eslint-plugin-microsoft-typescript": "0.1.11", "fancy-log": "latest", "fs-extra": "^6.0.1", "gulp": "^4.0.0", @@ -85,7 +90,6 @@ "source-map-support": "latest", "through2": "latest", "travis-fold": "latest", - "tslint": "latest", "typescript": "next", "vinyl": "latest", "vinyl-sourcemaps-apply": "latest", diff --git a/scripts/tslint/formatters/autolinkableStylishFormatter.ts b/scripts/tslint/formatters/autolinkableStylishFormatter.ts deleted file mode 100644 index 23e01bc8587e1..0000000000000 --- a/scripts/tslint/formatters/autolinkableStylishFormatter.ts +++ /dev/null @@ -1,97 +0,0 @@ -import * as Lint from "tslint"; -import chalk from "chalk"; -import { sep } from "path"; -function groupBy(array: ReadonlyArray | undefined, getGroupId: (elem: T, index: number) => number | string): T[][] { - if (!array) { - return []; - } - - const groupIdToGroup: { [index: string]: T[] } = {}; - let result: T[][] | undefined; // Compacted array for return value - for (let index = 0; index < array.length; index++) { - const value = array[index]; - const key = getGroupId(value, index); - if (groupIdToGroup[key]) { - groupIdToGroup[key].push(value); - } - else { - const newGroup = [value]; - groupIdToGroup[key] = newGroup; - if (!result) { - result = [newGroup]; - } - else { - result.push(newGroup); - } - } - } - - return result || []; -} - -function max(array: ReadonlyArray | undefined, selector: (elem: T) => number): number { - if (!array) { - return 0; - } - - let max = 0; - for (const item of array) { - const scalar = selector(item); - if (scalar > max) { - max = scalar; - } - } - return max; -} - -function getLink(failure: Lint.RuleFailure, color: boolean): string { - const lineAndCharacter = failure.getStartPosition().getLineAndCharacter(); - const sev = failure.getRuleSeverity().toUpperCase(); - let path = failure.getFileName(); - // Most autolinks only become clickable if they contain a slash in some way; so we make a top level file into a relative path here - if (path.indexOf("/") === -1 && path.indexOf("\\") === -1) { - path = `.${sep}${path}`; - } - return `${color ? (sev === "WARNING" ? chalk.blue(sev) : chalk.red(sev)) : sev}: ${path}:${lineAndCharacter.line + 1}:${lineAndCharacter.character + 1}`; -} - -function getLinkMaxSize(failures: Lint.RuleFailure[]): number { - return max(failures, f => getLink(f, /*color*/ false).length); -} - -function getNameMaxSize(failures: Lint.RuleFailure[]): number { - return max(failures, f => f.getRuleName().length); -} - -function pad(str: string, visiblelen: number, len: number) { - if (visiblelen >= len) return str; - const count = len - visiblelen; - for (let i = 0; i < count; i++) { - str += " "; - } - return str; -} - -export class Formatter extends Lint.Formatters.AbstractFormatter { - public static metadata: Lint.IFormatterMetadata = { - formatterName: "autolinkableStylish", - description: "Human-readable formatter which creates stylish messages with autolinkable filepaths.", - descriptionDetails: Lint.Utils.dedent` - Colorized output grouped by file, with autolinkable filepaths containing line and column information - `, - sample: Lint.Utils.dedent` - src/myFile.ts - ERROR: src/myFile.ts:1:14 semicolon Missing semicolon`, - consumer: "human" - }; - public format(failures: Lint.RuleFailure[]): string { - return groupBy(failures, f => f.getFileName()).map(group => { - const currentFile = group[0].getFileName(); - const linkMaxSize = getLinkMaxSize(group); - const nameMaxSize = getNameMaxSize(group); - return ` -${currentFile} -${group.map(f => `${pad(getLink(f, /*color*/ true), getLink(f, /*color*/ false).length, linkMaxSize)} ${chalk.grey(pad(f.getRuleName(), f.getRuleName().length, nameMaxSize))} ${chalk.yellow(f.getFailure())}`).join("\n")}`; - }).join("\n"); - } -} \ No newline at end of file diff --git a/scripts/tslint/rules/booleanTriviaRule.ts b/scripts/tslint/rules/booleanTriviaRule.ts deleted file mode 100644 index 0224a0f08d86b..0000000000000 --- a/scripts/tslint/rules/booleanTriviaRule.ts +++ /dev/null @@ -1,93 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, ctx => walk(ctx)); - } -} - -function walk(ctx: Lint.WalkContext): void { - const { sourceFile } = ctx; - ts.forEachChild(sourceFile, function recur(node: ts.Node): void { - if (node.kind === ts.SyntaxKind.CallExpression) { - checkCall(node as ts.CallExpression); - } - ts.forEachChild(node, recur); - }); - - function checkCall(node: ts.CallExpression): void { - if (!shouldIgnoreCalledExpression(node.expression)) { - for (const arg of node.arguments) { - checkArg(arg); - } - } - } - - /** Skip certain function/method names whose parameter names are not informative. */ - function shouldIgnoreCalledExpression(expression: ts.Expression): boolean { - if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) { - const methodName = (expression as ts.PropertyAccessExpression).name.text; - if (methodName.startsWith("set") || methodName.startsWith("assert")) { - return true; - } - switch (methodName) { - case "apply": - case "call": - case "equal": - case "fail": - case "isTrue": - case "output": - case "stringify": - return true; - } - } - else if (expression.kind === ts.SyntaxKind.Identifier) { - const functionName = (expression as ts.Identifier).text; - if (functionName.startsWith("set") || functionName.startsWith("assert")) { - return true; - } - switch (functionName) { - case "contains": - case "createAnonymousType": - case "createImportSpecifier": - case "createProperty": - case "createSignature": - case "resolveName": - return true; - } - } - return false; - } - - function checkArg(arg: ts.Expression): void { - if (!isTrivia(arg)) { - return; - } - - const ranges = ts.getTrailingCommentRanges(sourceFile.text, arg.pos) || ts.getLeadingCommentRanges(sourceFile.text, arg.pos); - if (ranges === undefined || ranges.length !== 1 || ranges[0].kind !== ts.SyntaxKind.MultiLineCommentTrivia) { - ctx.addFailureAtNode(arg, "Tag argument with parameter name"); - return; - } - - const range = ranges[0]; - const argStart = arg.getStart(sourceFile); - if (range.end + 1 !== argStart && sourceFile.text.slice(range.end, argStart).indexOf("\n") === -1) { - ctx.addFailureAtNode(arg, "There should be 1 space between an argument and its comment."); - } - } - - function isTrivia(arg: ts.Expression): boolean { - switch (arg.kind) { - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: - return true; - case ts.SyntaxKind.Identifier: - return (arg as ts.Identifier).originalKeywordKind === ts.SyntaxKind.UndefinedKeyword; - default: - return false; - } - } -} diff --git a/scripts/tslint/rules/debugAssertRule.ts b/scripts/tslint/rules/debugAssertRule.ts deleted file mode 100644 index 933b27697b01b..0000000000000 --- a/scripts/tslint/rules/debugAssertRule.ts +++ /dev/null @@ -1,45 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, ctx => walk(ctx)); - } -} - -function walk(ctx: Lint.WalkContext): void { - ts.forEachChild(ctx.sourceFile, function recur(node) { - if (ts.isCallExpression(node)) { - checkCall(node); - } - ts.forEachChild(node, recur); - }); - - function checkCall(node: ts.CallExpression) { - if (!isDebugAssert(node.expression) || node.arguments.length < 2) { - return; - } - - const message = node.arguments[1]; - if (!ts.isStringLiteral(message)) { - ctx.addFailureAtNode(message, "Second argument to 'Debug.assert' should be a string literal."); - } - - if (node.arguments.length < 3) { - return; - } - - const message2 = node.arguments[2]; - if (!ts.isStringLiteral(message2) && !ts.isArrowFunction(message2)) { - ctx.addFailureAtNode(message, "Third argument to 'Debug.assert' should be a string literal or arrow function."); - } - } - - function isDebugAssert(expr: ts.Node): boolean { - return ts.isPropertyAccessExpression(expr) && isName(expr.expression, "Debug") && isName(expr.name, "assert"); - } - - function isName(expr: ts.Node, text: string): boolean { - return ts.isIdentifier(expr) && expr.text === text; - } -} diff --git a/scripts/tslint/rules/nextLineRule.ts b/scripts/tslint/rules/nextLineRule.ts deleted file mode 100644 index 9de80793c62e3..0000000000000 --- a/scripts/tslint/rules/nextLineRule.ts +++ /dev/null @@ -1,67 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -const OPTION_CATCH = "check-catch"; -const OPTION_ELSE = "check-else"; - -export class Rule extends Lint.Rules.AbstractRule { - public static CATCH_FAILURE_STRING = "'catch' should not be on the same line as the preceeding block's curly brace"; - public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace"; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const options = this.getOptions().ruleArguments; - const checkCatch = options.indexOf(OPTION_CATCH) !== -1; - const checkElse = options.indexOf(OPTION_ELSE) !== -1; - return this.applyWithFunction(sourceFile, ctx => walk(ctx, checkCatch, checkElse)); - } -} - -function walk(ctx: Lint.WalkContext, checkCatch: boolean, checkElse: boolean): void { - const { sourceFile } = ctx; - ts.forEachChild(sourceFile, function recur(node) { - switch (node.kind) { - case ts.SyntaxKind.IfStatement: - checkIf(node as ts.IfStatement); - break; - case ts.SyntaxKind.TryStatement: - checkTry(node as ts.TryStatement); - break; - } - ts.forEachChild(node, recur); - }); - - function checkIf(node: ts.IfStatement): void { - const { thenStatement, elseStatement } = node; - if (!elseStatement) { - return; - } - - // find the else keyword - const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword); - if (checkElse && !!elseKeyword) { - const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd()); - const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile)); - if (thenStatementEndLoc.line === elseKeywordLoc.line) { - ctx.addFailureAtNode(elseKeyword, Rule.ELSE_FAILURE_STRING); - } - } - } - - function checkTry({ tryBlock, catchClause }: ts.TryStatement): void { - if (!checkCatch || !catchClause) { - return; - } - - const tryClosingBrace = tryBlock.getLastToken(sourceFile)!; - const catchKeyword = catchClause.getFirstToken(sourceFile)!; - const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd()); - const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile)); - if (tryClosingBraceLoc.line === catchKeywordLoc.line) { - ctx.addFailureAtNode(catchKeyword, Rule.CATCH_FAILURE_STRING); - } - } -} - -function getFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind) { - return node.getChildren().filter((child) => child.kind === kind)[0]; -} diff --git a/scripts/tslint/rules/noBomRule.ts b/scripts/tslint/rules/noBomRule.ts deleted file mode 100644 index 105e2d2d68c01..0000000000000 --- a/scripts/tslint/rules/noBomRule.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING = "This file has a BOM."; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - if (ctx.sourceFile.text[0] === "\ufeff") { - ctx.addFailure(0, 1, Rule.FAILURE_STRING); - } -} diff --git a/scripts/tslint/rules/noDoubleSpaceRule.ts b/scripts/tslint/rules/noDoubleSpaceRule.ts deleted file mode 100644 index 34ab470ebced3..0000000000000 --- a/scripts/tslint/rules/noDoubleSpaceRule.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - const { sourceFile } = ctx; - const lines = sourceFile.text.split("\n"); - const strings = getLiterals(sourceFile); - lines.forEach((line, idx) => { - // Skip indentation. - const firstNonSpace = /\S/.exec(line); - if (firstNonSpace === null) { - return; - } - // Allow common uses of double spaces - // * To align `=` or `!=` signs - // * To align comments at the end of lines - // * To indent inside a comment - // * To use two spaces after a period - // * To include aligned `->` in a comment - const rgx = /[^/*. ] [^-!/= ]/g; - rgx.lastIndex = firstNonSpace.index; - const doubleSpace = rgx.exec(line); - // Also allow to align comments after `@param` - if (doubleSpace !== null && !line.includes("@param")) { - const pos = lines.slice(0, idx).reduce((len, line) => len + 1 + line.length, 0) + doubleSpace.index; - if (!strings.some(s => s.getStart() <= pos && s.end > pos)) { - ctx.addFailureAt(pos + 1, 2, "Use only one space."); - } - } - }); -} - -function getLiterals(sourceFile: ts.SourceFile): ReadonlyArray { - const out: ts.Node[] = []; - sourceFile.forEachChild(function cb(node) { - switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.TemplateMiddle: - case ts.SyntaxKind.TemplateTail: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.RegularExpressionLiteral: - out.push(node); - } - node.forEachChild(cb); - }); - return out; -} diff --git a/scripts/tslint/rules/noInOperatorRule.ts b/scripts/tslint/rules/noInOperatorRule.ts deleted file mode 100644 index 95f052ccaa62e..0000000000000 --- a/scripts/tslint/rules/noInOperatorRule.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead"; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - ts.forEachChild(ctx.sourceFile, recur); - function recur(node: ts.Node): void { - if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) { - ctx.addFailureAtNode(node, Rule.FAILURE_STRING); - } - } -} diff --git a/scripts/tslint/rules/noIncrementDecrementRule.ts b/scripts/tslint/rules/noIncrementDecrementRule.ts deleted file mode 100644 index 007d25919e183..0000000000000 --- a/scripts/tslint/rules/noIncrementDecrementRule.ts +++ /dev/null @@ -1,55 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops."; - public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators."; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - ts.forEachChild(ctx.sourceFile, recur); - function recur(node: ts.Node): void { - switch (node.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: - const { operator } = node as ts.PrefixUnaryExpression; - if (operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) { - check(node as ts.PrefixUnaryExpression); - } - break; - - case ts.SyntaxKind.PostfixUnaryExpression: - check(node as ts.PostfixUnaryExpression); - break; - } - } - - function check(node: ts.UnaryExpression): void { - if (!isAllowedLocation(node.parent)) { - ctx.addFailureAtNode(node, Rule.POSTFIX_FAILURE_STRING); - } - } -} - -function isAllowedLocation(node: ts.Node): boolean { - switch (node.kind) { - // Can be a statement - case ts.SyntaxKind.ExpressionStatement: - return true; - - // Can be directly in a for-statement - case ts.SyntaxKind.ForStatement: - return true; - - // Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`) - case ts.SyntaxKind.BinaryExpression: - return (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken && - node.parent.kind === ts.SyntaxKind.ForStatement; - - default: - return false; - } -} diff --git a/scripts/tslint/rules/noTypeAssertionWhitespaceRule.ts b/scripts/tslint/rules/noTypeAssertionWhitespaceRule.ts deleted file mode 100644 index 37017fb60e477..0000000000000 --- a/scripts/tslint/rules/noTypeAssertionWhitespaceRule.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static TRAILING_FAILURE_STRING = "Excess trailing whitespace found around type assertion."; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - ts.forEachChild(ctx.sourceFile, recur); - function recur(node: ts.Node) { - if (node.kind === ts.SyntaxKind.TypeAssertionExpression) { - const refined = node as ts.TypeAssertion; - const leftSideWhitespaceStart = refined.type.getEnd() + 1; - const rightSideWhitespaceEnd = refined.expression.getStart(); - if (leftSideWhitespaceStart !== rightSideWhitespaceEnd) { - ctx.addFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING); - } - } - ts.forEachChild(node, recur); - } -} diff --git a/scripts/tslint/rules/objectLiteralSurroundingSpaceRule.ts b/scripts/tslint/rules/objectLiteralSurroundingSpaceRule.ts deleted file mode 100644 index 8546aa6c973c3..0000000000000 --- a/scripts/tslint/rules/objectLiteralSurroundingSpaceRule.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static LEADING_FAILURE_STRING = "No leading whitespace found on single-line object literal."; - public static TRAILING_FAILURE_STRING = "No trailing whitespace found on single-line object literal."; - public static LEADING_EXCESS_FAILURE_STRING = "Excess leading whitespace found on single-line object literal."; - public static TRAILING_EXCESS_FAILURE_STRING = "Excess trailing whitespace found on single-line object literal."; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - const { sourceFile } = ctx; - ts.forEachChild(sourceFile, recur); - function recur(node: ts.Node): void { - if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { - check(node as ts.ObjectLiteralExpression); - } - ts.forEachChild(node, recur); - } - - function check(node: ts.ObjectLiteralExpression): void { - const text = node.getText(sourceFile); - if (!text.match(/^{[^\n]+}$/g)) { - return; - } - - if (text.charAt(1) !== " ") { - ctx.addFailureAtNode(node, Rule.LEADING_FAILURE_STRING); - } - if (text.charAt(2) === " ") { - ctx.addFailureAt(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING); - } - if (text.charAt(text.length - 2) !== " ") { - ctx.addFailureAtNode(node, Rule.TRAILING_FAILURE_STRING); - } - if (text.charAt(text.length - 3) === " ") { - ctx.addFailureAt(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING); - } - } -} diff --git a/scripts/tslint/rules/typeOperatorSpacingRule.ts b/scripts/tslint/rules/typeOperatorSpacingRule.ts deleted file mode 100644 index 82dccfe0eace5..0000000000000 --- a/scripts/tslint/rules/typeOperatorSpacingRule.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as Lint from "tslint/lib"; -import * as ts from "typescript"; - -export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by spaces"; - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithFunction(sourceFile, walk); - } -} - -function walk(ctx: Lint.WalkContext): void { - const { sourceFile } = ctx; - sourceFile.forEachChild(function cb(node: ts.Node): void { - if (ts.isUnionTypeNode(node) || ts.isIntersectionTypeNode(node)) { - check(node); - } - node.forEachChild(cb); - }); - - function check(node: ts.UnionTypeNode | ts.IntersectionTypeNode): void { - const list = node.getChildren().find(child => child.kind === ts.SyntaxKind.SyntaxList)!; - for (const child of list.getChildren()) { - if ((child.kind === ts.SyntaxKind.BarToken || child.kind === ts.SyntaxKind.AmpersandToken) - && (/\S/.test(sourceFile.text[child.getStart(sourceFile) - 1]) || /\S/.test(sourceFile.text[child.end]))) { - ctx.addFailureAtNode(child, Rule.FAILURE_STRING); - } - } - } -} diff --git a/scripts/tslint/tsconfig.json b/scripts/tslint/tsconfig.json deleted file mode 100644 index e9f90ad42669b..0000000000000 --- a/scripts/tslint/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "lib": ["es6"], - "sourceMap": false, - "declaration": false, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "strictNullChecks": true, - "module": "commonjs", - "outDir": "../../built/local/tslint", - "baseUrl": "../..", - "types": ["node"], - "paths": { - "typescript": ["lib/typescript.d.ts"] - } - } -} \ No newline at end of file diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 5b75ed1a55b74..0000000000000 --- a/tslint.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "extends": "tslint:latest", - "rulesDirectory": "built/local/tslint/rules", - "linterOptions": { - "exclude": [ - "tests/**/*" - ] - }, - "rules": { - "no-unnecessary-type-assertion": true, - - "array-type": [true, "array"], - "ban": [ - true, - "setInterval", - "setTimeout" - ], - "ban-types": { - "options": [ - ["Object", "Avoid using the `Object` type. Did you mean `object`?"], - ["Function", "Avoid using the `Function` type. Prefer a specific function type, like `() => void`, or use `ts.AnyFunction`."], - ["Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?"], - ["Number", "Avoid using the `Number` type. Did you mean `number`?"], - ["String", "Avoid using the `String` type. Did you mean `string`?"] - ] - }, - "boolean-trivia": true, - "class-name": true, - "comment-format": [true, - "check-space" - ], - "curly":[true, "ignore-same-line"], - "debug-assert": true, - "indent": [true, - "spaces" - ], - "interface-name": [true, "never-prefix"], - "interface-over-type-literal": true, - "jsdoc-format": true, - "linebreak-style": [true, "CRLF"], - "next-line": [true, - "check-catch", - "check-else" - ], - "no-bom": true, - "no-double-space": true, - "no-eval": true, - "no-in-operator": true, - "no-increment-decrement": true, - "no-inferrable-types": true, - "no-internal-module": true, - "no-null-keyword": true, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": [true, "ignore-template-strings"], - "no-type-assertion-whitespace": true, - "no-unnecessary-qualifier": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "object-literal-surrounding-space": true, - "one-line": [true, - "check-open-brace", - "check-whitespace" - ], - "prefer-const": true, - "quotemark": [true, - "double", - "avoid-escape" - ], - "semicolon": [true, "always", "ignore-bound-class-methods"], - "space-within-parens": true, - "triple-equals": true, - "type-operator-spacing": true, - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" - } - ], - "whitespace": [true, - "check-branch", - "check-decl", - "check-operator", - "check-module", - "check-separator", - "check-type" - ], - - // Config different from tslint:latest - "no-implicit-dependencies": [true, "dev"], - "object-literal-key-quotes": [true, "consistent-as-needed"], - "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"], - - // TODO - "arrow-parens": false, // [true, "ban-single-arg-parens"] - "arrow-return-shorthand": false, - "ban-types": false, - "forin": false, - "member-access": false, // [true, "no-public"] - "no-conditional-assignment": false, - "no-console": false, - "no-debugger": false, - "no-empty-interface": false, - "no-object-literal-type-assertion": false, - "no-shadowed-variable": false, - "no-submodule-imports": false, - "no-var-requires": false, - "ordered-imports": false, - "prefer-conditional-expression": false, - "radix": false, - "trailing-comma": false, - - // These should be done automatically by a formatter. https://github.com/Microsoft/TypeScript/issues/18340 - "align": false, - "eofline": false, - "max-line-length": false, - "no-consecutive-blank-lines": false, - "space-before-function-paren": false, - - // Not doing - "ban-comma-operator": false, - "max-classes-per-file": false, - "member-ordering": false, - "no-angle-bracket-type-assertion": false, - "no-bitwise": false, - "no-namespace": false, - "no-reference": false, - "object-literal-sort-keys": false, - "one-variable-per-declaration": false - } -}