From d5efb2d875b6012f8bc48f431da0fa709f8f5371 Mon Sep 17 00:00:00 2001 From: Saugat Acharya Date: Fri, 2 Nov 2018 00:21:24 +0545 Subject: [PATCH 01/37] Add prettier, prettierrc and prettierignore --- .prettierignore | 5 +++++ .prettierrc | 2 ++ package-lock.json | 8 +++++++- package.json | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..72f7d4acc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Discard build directory +dist/ + +# Discard definition files +*.d.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..c3c19a41e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,2 @@ +tabWidth: 4 +printWidth: 140 diff --git a/package-lock.json b/package-lock.json index 29c17644f..698e2e6d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2522,6 +2522,12 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "prettier": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz", + "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==", + "dev": true + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -2545,7 +2551,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 330fa2dc8..0ba38236d 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "generate:package-json-for-npm": "node build-tasks/generate-package-json-for-npm.js", "lint:rules": "tslint -p tsconfig.json -t stylish -c tslint.json -e \"src/tests/**\" \"src/**/*.ts\"", "lint:tests": "tslint -p tsconfig.json -t stylish -c src/tests/tslint.json -e src/tests/references.ts \"src/tests/**/*.ts\"", + "prettier": "prettier --write \"**/{*.js,*.ts,*.tsx}\"", "start": "npm-run-all clean copy:json watch:src", "test:mocha": "mocha \"dist/src/tests/**/*.js\" --timeout 5000", "test:rules": "tslint -r dist/src --test \"tests/**\"", @@ -73,6 +74,7 @@ "glob": "^7.1.3", "mocha": "5.2.0", "npm-run-all": "^4.1.3", + "prettier": "^1.14.3", "rimraf": "^2.6.2", "strip-json-comments": "^2.0.1", "tslint": "^5.11.0", From 2b5de333c529beb306a7b851c223f4f5b6a04a51 Mon Sep 17 00:00:00 2001 From: Saugat Acharya Date: Fri, 2 Nov 2018 00:29:34 +0545 Subject: [PATCH 02/37] Add tslint-config-prettier to avoid tslint and prettier conflicts --- package-lock.json | 6 ++++++ package.json | 2 ++ tslint.json | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 698e2e6d0..72c2c0264 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3093,6 +3093,12 @@ } } }, + "tslint-config-prettier": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.15.0.tgz", + "integrity": "sha512-06CgrHJxJmNYVgsmeMoa1KXzQRoOdvfkqnJth6XUkNeOz707qxN0WfxfhYwhL5kXHHbYJRby2bqAPKwThlZPhw==", + "dev": true + }, "tsutils": { "version": "2.28.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", diff --git a/package.json b/package.json index 0ba38236d..559a09c35 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "test:rules": "tslint -r dist/src --test \"tests/**\"", "test": "npm-run-all clean copy:json tsc:src test:* lint:* validate:* copy:package copy:meta generate:*", "tsc:src": "tsc", + "tslint:check": "tslint-config-prettier-check ./tslint.json", "validate:config": "node build-tasks/validate-config.js", "validate:documentation": "node build-tasks/validate-documentation.js", "watch:run-tests": "node build-tasks/watch-run-tests.js", @@ -78,6 +79,7 @@ "rimraf": "^2.6.2", "strip-json-comments": "^2.0.1", "tslint": "^5.11.0", + "tslint-config-prettier": "^1.15.0", "typescript": "3.1.1", "underscore": "1.9.1" }, diff --git a/tslint.json b/tslint.json index 1056b26b5..269f4e010 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,8 @@ { - "extends": "tslint:all", + "extends": [ + "tslint:all", + "tslint-config-prettier" + ], "rulesDirectory": [ "dist/src" ], From baafedf6d5f8f960f2c601897aff27e9f930b091 Mon Sep 17 00:00:00 2001 From: Saugat Acharya Date: Fri, 2 Nov 2018 00:30:20 +0545 Subject: [PATCH 03/37] First prettier run --- build-tasks/common/files.js | 16 +- build-tasks/common/meta.js | 49 +- build-tasks/create-rule.js | 42 +- build-tasks/generate-default-tslint-json.js | 10 +- build-tasks/generate-package-json-for-npm.js | 6 +- build-tasks/generate-recommendations.js | 30 +- build-tasks/generate-rule-metadata.js | 6 +- build-tasks/generate-sdl-report.js | 66 +- .../templates/recommended_ruleset.template.js | 18 +- build-tasks/templates/rule.template.js | 4 +- build-tasks/validate-config.js | 38 +- build-tasks/validate-documentation.js | 28 +- build-tasks/watch-run-tests.js | 47 +- recommended_ruleset.js | 88 +- src/.baseDir.ts | 2 +- src/chaiPreferContainsToIndexOfRule.ts | 38 +- src/chaiVagueErrorsRule.ts | 49 +- src/exportNameRule.ts | 116 +- src/fixNoRequireImportsFormatter.ts | 26 +- src/fixNoVarKeywordFormatter.ts | 18 +- src/functionNameRule.ts | 97 +- src/importNameRule.ts | 138 +- src/informativeDocsRule.ts | 89 +- src/insecureRandomRule.ts | 39 +- src/jqueryDeferredMustCompleteRule.ts | 99 +- src/maxFuncBodyLengthRule.ts | 107 +- src/missingJsdocRule.ts | 32 +- src/missingOptionalAnnotationRule.ts | 49 +- src/mochaAvoidOnlyRule.ts | 59 +- src/mochaNoSideEffectCodeRule.ts | 117 +- src/mochaUnneededDoneRule.ts | 78 +- src/noBackboneGetSetOutsideModelRule.ts | 39 +- src/noBannedTermsRule.ts | 44 +- src/noConstantConditionRule.ts | 50 +- src/noControlRegexRule.ts | 30 +- src/noCookiesRule.ts | 40 +- src/noDeleteExpressionRule.ts | 29 +- src/noDisableAutoSanitizationRule.ts | 37 +- src/noDocumentDomainRule.ts | 44 +- src/noDocumentWriteRule.ts | 43 +- src/noDuplicateCaseRule.ts | 60 +- src/noDuplicateParameterNamesRule.ts | 54 +- src/noEmptyInterfacesRule.ts | 38 +- src/noEmptyLineAfterOpeningBraceRule.ts | 42 +- src/noExecScriptRule.ts | 41 +- src/noForInRule.ts | 27 +- ...noFunctionConstructorWithStringArgsRule.ts | 39 +- src/noFunctionExpressionRule.ts | 41 +- src/noHttpStringRule.ts | 45 +- src/noIncrementDecrementRule.ts | 34 +- src/noInnerHtmlRule.ts | 46 +- src/noInvalidRegexpRule.ts | 27 +- src/noJqueryRawElementsRule.ts | 39 +- src/noMissingVisibilityModifiersRule.ts | 41 +- src/noMultilineStringRule.ts | 39 +- src/noMultipleVarDeclRule.ts | 35 +- src/noOctalLiteralRule.ts | 32 +- src/noRegexSpacesRule.ts | 31 +- src/noRelativeImportsRule.ts | 47 +- src/noReservedKeywordsRule.ts | 117 +- src/noSingleLineBlockCommentRule.ts | 42 +- src/noStatelessClassRule.ts | 103 +- src/noStringBasedSetImmediateRule.ts | 37 +- src/noStringBasedSetIntervalRule.ts | 35 +- src/noStringBasedSetTimeoutRule.ts | 37 +- src/noSuspiciousCommentRule.ts | 41 +- src/noTypeofUndefinedRule.ts | 42 +- src/noUnexternalizedStringsRule.ts | 85 +- src/noUnnecessaryBindRule.ts | 126 +- src/noUnnecessaryFieldInitializationRule.ts | 106 +- src/noUnnecessaryLocalVariableRule.ts | 44 +- src/noUnnecessaryOverrideRule.ts | 33 +- src/noUnnecessarySemicolonsRule.ts | 29 +- src/noUnsupportedBrowserCodeRule.ts | 65 +- src/noUselessFilesRule.ts | 31 +- src/noVarSelfRule.ts | 34 +- src/noWithStatementRule.ts | 31 +- src/nonLiteralFsPathRule.ts | 38 +- src/nonLiteralRequireRule.ts | 54 +- src/possibleTimingAttackRule.ts | 53 +- src/preferArrayLiteralRule.ts | 44 +- src/preferTypeCastRule.ts | 33 +- src/promiseMustCompleteRule.ts | 95 +- src/reactA11yAnchorsRule.ts | 204 +- src/reactA11yAriaUnsupportedElementsRule.ts | 49 +- src/reactA11yEventHasRoleRule.ts | 65 +- src/reactA11yImageButtonHasAltRule.ts | 44 +- src/reactA11yImgHasAltRule.ts | 102 +- src/reactA11yInputElementsRule.ts | 41 +- src/reactA11yLangRule.ts | 217 +- src/reactA11yMetaRule.ts | 42 +- src/reactA11yNoOnchangeRule.ts | 41 +- src/reactA11yPropsRule.ts | 36 +- src/reactA11yProptypesRule.ts | 117 +- src/reactA11yRequiredRule.ts | 40 +- src/reactA11yRoleHasRequiredAriaPropsRule.ts | 75 +- src/reactA11yRoleRule.ts | 42 +- src/reactA11yRoleSupportsAriaPropsRule.ts | 75 +- src/reactA11yTabindexNoPositiveRule.ts | 34 +- src/reactA11yTitlesRule.ts | 56 +- src/reactAnchorBlankNoopenerRule.ts | 55 +- src/reactIframeMissingSandboxRule.ts | 100 +- src/reactNoDangerousHtmlRule.ts | 96 +- src/reactThisBindingIssueRule.ts | 208 +- src/reactTsxCurlySpacingRule.ts | 44 +- src/reactUnusedPropsAndStateRule.ts | 118 +- src/tests/AstUtilsTests.ts | 22 +- .../ChaiPreferContainsToIndexOfRuleTests.ts | 70 +- src/tests/ChaiVagueErrorsRuleTests.ts | 334 +- src/tests/ExportNameRuleTests.ts | 295 +- .../FixNoRequireImportsFormatterTests.ts | 42 +- src/tests/FixNoVarKeywordFormatterTests.ts | 41 +- src/tests/FunctionNameRuleTests.ts | 241 +- src/tests/GetImplicitRoleTest.ts | 629 +- src/tests/ImportNameRuleTests.ts | 250 +- src/tests/InformativeDocsRuleTests.ts | 108 +- src/tests/InsecureRandomRuleTests.ts | 63 +- src/tests/MaxFuncBodyLengthRuleTests.ts | 275 +- src/tests/MissingJsdocRuleTests.ts | 80 +- src/tests/MissingOptionalAnnotationTests.ts | 164 +- src/tests/MochaAvoidOnlyRuleTests.ts | 99 +- src/tests/MochaNoSideEffectCodeRuleTests.ts | 309 +- src/tests/MochaUnneededDoneRuleTests.ts | 133 +- .../NoBackboneGetSetOutsideModelRuleTests.ts | 41 +- src/tests/NoBannedTermsTests.ts | 987 +-- src/tests/NoConstantConditionRuleTests.ts | 479 +- src/tests/NoControlRegexRuleTests.ts | 71 +- src/tests/NoCookiesTests.ts | 119 +- src/tests/NoDeleteExpressionTests.ts | 27 +- src/tests/NoDisableAutoSanitizationTests.ts | 58 +- src/tests/NoDocumentDomainRuleTests.ts | 55 +- src/tests/NoDocumentWriteTests.ts | 49 +- src/tests/NoDuplicateCaseRuleTests.ts | 51 +- src/tests/NoDuplicateParameterNamesTests.ts | 73 +- src/tests/NoEmptyInterfacesRuleTests.ts | 45 +- .../NoEmptyLineAfterOpeningBraceRuleTests.ts | 20 +- src/tests/NoExecScriptTests.ts | 109 +- src/tests/NoForInRuleTests.ts | 34 +- ...oFunctionConstructorWithStringArgsTests.ts | 25 +- src/tests/NoFunctionExpressionRuleTests.ts | 78 +- src/tests/NoHttpStringRuleTests.ts | 90 +- src/tests/NoIncrementDecrementTests.ts | 61 +- src/tests/NoInnerHtmlRuleTests.ts | 100 +- src/tests/NoInvalidRegexpRuleTests.ts | 39 +- src/tests/NoJqueryRawElementsRuleTests.ts | 125 +- .../NoMissingVisibilityModifiersRuleTests.ts | 57 +- src/tests/NoMultilineStringTests.ts | 25 +- src/tests/NoMultipleVarDeclRuleTests.ts | 42 +- src/tests/NoOctalLiteralTests.ts | 522 +- src/tests/NoRegexSpacesRuleTests.ts | 63 +- src/tests/NoRelativeImportsRuleTests.ts | 140 +- src/tests/NoReservedKeywordsTests.ts | 5971 ++++++++--------- .../NoSingleLineBlockCommentRuleTests.ts | 56 +- src/tests/NoStatelessClassRuleTests.ts | 111 +- src/tests/NoStringBasedSetImmediateTests.ts | 224 +- src/tests/NoStringBasedSetIntervalTests.ts | 146 +- src/tests/NoStringBasedSetTimeoutTests.ts | 375 +- src/tests/NoSuspiciousCommentRuleTests.ts | 77 +- src/tests/NoTypeofUndefinedRuleTests.ts | 62 +- src/tests/NoUnexternalizedStringsRuleTests.ts | 172 +- src/tests/NoUnnecessaryBindRuleTests.ts | 272 +- src/tests/NoUnnecessaryOverrideRuleTests.ts | 136 +- src/tests/NoUnnecessarySemicolonsTests.ts | 92 +- .../NoUnsupportedBrowserCodeRuleTests.ts | 125 +- src/tests/NoUselessFilesRuleTests.ts | 110 +- src/tests/NoVarSelfRuleTests.ts | 124 +- src/tests/NoWithStatementTests.ts | 26 +- src/tests/NonLiteralFsPathRuleTest.ts | 28 +- src/tests/NonLiteralRequireRuleTests.ts | 66 +- src/tests/PossibleTimingAttackRuleTests.ts | 102 +- src/tests/PreferTypeCastRuleTests.ts | 31 +- src/tests/PromiseMustCompleteRuleTests.ts | 259 +- src/tests/ReactA11yAnchorsRuleTests.ts | 429 +- ...eactA11yAriaUnsupportedElementsRuleTest.ts | 48 +- src/tests/ReactA11yEventHasRoleRuleTest.ts | 48 +- .../ReactA11yImageButtonHasAltRuleTests.ts | 26 +- src/tests/ReactA11yInputElementsRuleTests.ts | 50 +- src/tests/ReactA11yLangRuleTests.ts | 60 +- src/tests/ReactA11yMetaRuleTests.ts | 52 +- src/tests/ReactA11yNoOnchangeRuleTests.ts | 68 +- src/tests/ReactA11yProptypesRuleTest.ts | 512 +- src/tests/ReactA11yRequiredRuleTests.ts | 70 +- src/tests/ReactA11yTitlesRuleTests.ts | 101 +- .../ReactAnchorBlankNoopenerRuleTests.ts | 243 +- .../ReactIframeMissingSandboxRuleTests.ts | 115 +- src/tests/ReactNoDangerousHtmlRuleTests.ts | 46 +- src/tests/ReactThisBindingIssueRuleTests.ts | 158 +- src/tests/ReactTsxCurlySpacingRuleTests.ts | 141 +- .../ReactUnusedPropsAndStateRuleTests.ts | 218 +- src/tests/TestHelper.ts | 88 +- src/tests/TypeGuardTests.ts | 42 +- ...UnderscoreConsistentInvocationRuleTests.ts | 992 +-- .../UnnecessaryLocalVariableRuleTests.ts | 92 +- src/tests/UseNamedParameterRuleTests.ts | 34 +- src/tests/UtilsTests.ts | 90 +- src/tests/ValidTypeofRuleTests.ts | 96 +- .../jqueryDeferredMustCompleteRuleTests.ts | 217 +- ...UnnecessaryFieldInitializationRuleTests.ts | 84 +- src/tests/preferArrayLiteralRuleTests.ts | 83 +- src/tests/reactA11yImgHasAltRuleTests.ts | 734 +- src/tests/reactA11yPropsRuleTests.ts | 114 +- ...ctA11yRoleHasRequiredAriaPropsRuleTests.ts | 173 +- src/tests/reactA11yRoleRuleTests.ts | 232 +- ...reactA11yRoleSupportsAriaPropsRuleTests.ts | 200 +- .../reactA11yTabindexNoPositiveRuleTests.ts | 249 +- src/underscoreConsistentInvocationRule.ts | 127 +- src/useNamedParameterRule.ts | 33 +- src/utils/AstUtils.ts | 153 +- src/utils/BannedTermWalker.ts | 21 +- src/utils/BaseFormatter.ts | 17 +- src/utils/ChaiUtils.ts | 9 +- src/utils/ExtendedMetadata.ts | 12 +- src/utils/JsxAttribute.ts | 47 +- src/utils/MochaUtils.ts | 40 +- .../NoStringParameterToFunctionCallWalker.ts | 32 +- src/utils/NodeDocs.ts | 12 +- src/utils/Scope.ts | 42 +- src/utils/ScopedSymbolTrackingWalker.ts | 70 +- src/utils/TypeGuard.ts | 8 +- src/utils/Utils.ts | 36 +- src/utils/getImplicitRole.ts | 6 +- src/utils/implicitRoles/a.ts | 8 +- src/utils/implicitRoles/area.ts | 8 +- src/utils/implicitRoles/article.ts | 2 +- src/utils/implicitRoles/aside.ts | 2 +- src/utils/implicitRoles/body.ts | 2 +- src/utils/implicitRoles/button.ts | 2 +- src/utils/implicitRoles/datalist.ts | 2 +- src/utils/implicitRoles/dd.ts | 2 +- src/utils/implicitRoles/details.ts | 2 +- src/utils/implicitRoles/dialog.ts | 2 +- src/utils/implicitRoles/dl.ts | 2 +- src/utils/implicitRoles/dt.ts | 2 +- src/utils/implicitRoles/footer.ts | 6 +- src/utils/implicitRoles/form.ts | 2 +- src/utils/implicitRoles/h1.ts | 2 +- src/utils/implicitRoles/h2.ts | 2 +- src/utils/implicitRoles/h3.ts | 2 +- src/utils/implicitRoles/h4.ts | 2 +- src/utils/implicitRoles/h5.ts | 2 +- src/utils/implicitRoles/h6.ts | 2 +- src/utils/implicitRoles/header.ts | 6 +- src/utils/implicitRoles/hr.ts | 2 +- src/utils/implicitRoles/img.ts | 10 +- src/utils/implicitRoles/index.ts | 100 +- src/utils/implicitRoles/input.ts | 74 +- src/utils/implicitRoles/li.ts | 6 +- src/utils/implicitRoles/link.ts | 8 +- src/utils/implicitRoles/main.ts | 2 +- src/utils/implicitRoles/math.ts | 2 +- src/utils/implicitRoles/menu.ts | 8 +- src/utils/implicitRoles/menuitem.ts | 20 +- src/utils/implicitRoles/meter.ts | 2 +- src/utils/implicitRoles/nav.ts | 2 +- src/utils/implicitRoles/ol.ts | 2 +- src/utils/implicitRoles/optgroup.ts | 2 +- src/utils/implicitRoles/option.ts | 2 +- src/utils/implicitRoles/output.ts | 2 +- src/utils/implicitRoles/progress.ts | 2 +- src/utils/implicitRoles/section.ts | 2 +- src/utils/implicitRoles/select.ts | 2 +- src/utils/implicitRoles/summary.ts | 2 +- src/utils/implicitRoles/table.ts | 2 +- src/utils/implicitRoles/tbody.ts | 2 +- src/utils/implicitRoles/td.ts | 2 +- src/utils/implicitRoles/textarea.ts | 2 +- src/utils/implicitRoles/tfoot.ts | 2 +- src/utils/implicitRoles/th.ts | 2 +- src/utils/implicitRoles/thead.ts | 2 +- src/utils/implicitRoles/tr.ts | 2 +- src/utils/implicitRoles/ul.ts | 2 +- src/validTypeofRule.ts | 40 +- .../ExportNameRuleFailingTestInput.ts | 4 +- .../ExportNameRuleFailingTestInput2.tsx | 4 +- .../ExportNameRulePassingTestInput.ts | 4 +- .../ExportNameRulePassingTestInput2.tsx | 4 +- .../NoCookies/NoCookiesFailingTestInput.ts | 14 +- .../NoCookies/NoCookiesPassingTestInput.ts | 11 +- .../NoCookies/NoCookiesTestInput-error.ts | 5 +- ...ctionConstructorWithStringArgsTestInput.ts | 8 +- test-data/NoFunctionExpressionWithInTSX.tsx | 4 +- .../NoOctalLiteralTestInput-passing.ts | 10 +- .../NoReservedKeywordsTestInput-any.ts | 19 +- .../NoReservedKeywordsTestInput-as.ts | 26 +- .../NoReservedKeywordsTestInput-boolean.ts | 22 +- .../NoReservedKeywordsTestInput-break.ts | 9 +- .../NoReservedKeywordsTestInput-case.ts | 9 +- .../NoReservedKeywordsTestInput-catch.ts | 8 +- .../NoReservedKeywordsTestInput-class.ts | 4 +- .../NoReservedKeywordsTestInput-const.ts | 8 +- ...NoReservedKeywordsTestInput-constructor.ts | 26 +- .../NoReservedKeywordsTestInput-continue.ts | 8 +- .../NoReservedKeywordsTestInput-debugger.ts | 8 +- .../NoReservedKeywordsTestInput-declare.ts | 26 +- .../NoReservedKeywordsTestInput-default.ts | 8 +- .../NoReservedKeywordsTestInput-delete.ts | 8 +- .../NoReservedKeywordsTestInput-do.ts | 9 +- .../NoReservedKeywordsTestInput-else.ts | 8 +- .../NoReservedKeywordsTestInput-enum.ts | 8 +- .../NoReservedKeywordsTestInput-export.ts | 9 +- .../NoReservedKeywordsTestInput-extends.ts | 8 +- .../NoReservedKeywordsTestInput-false.ts | 10 +- .../NoReservedKeywordsTestInput-finally.ts | 8 +- .../NoReservedKeywordsTestInput-for.ts | 8 +- .../NoReservedKeywordsTestInput-from.ts | 26 +- .../NoReservedKeywordsTestInput-function.ts | 8 +- .../NoReservedKeywordsTestInput-get.ts | 26 +- .../NoReservedKeywordsTestInput-if.ts | 9 +- .../NoReservedKeywordsTestInput-implements.ts | 14 +- .../NoReservedKeywordsTestInput-import.ts | 8 +- .../NoReservedKeywordsTestInput-in.ts | 8 +- .../NoReservedKeywordsTestInput-instanceof.ts | 8 +- .../NoReservedKeywordsTestInput-interface.ts | 14 +- .../NoReservedKeywordsTestInput-let.ts | 14 +- .../NoReservedKeywordsTestInput-module.ts | 26 +- .../NoReservedKeywordsTestInput-new.ts | 8 +- .../NoReservedKeywordsTestInput-null.ts | 8 +- .../NoReservedKeywordsTestInput-number.ts | 22 +- .../NoReservedKeywordsTestInput-of.ts | 26 +- .../NoReservedKeywordsTestInput-package.ts | 14 +- .../NoReservedKeywordsTestInput-private.ts | 14 +- .../NoReservedKeywordsTestInput-protected.ts | 14 +- .../NoReservedKeywordsTestInput-public.ts | 14 +- .../NoReservedKeywordsTestInput-require.ts | 26 +- .../NoReservedKeywordsTestInput-return.ts | 8 +- .../NoReservedKeywordsTestInput-set.ts | 26 +- .../NoReservedKeywordsTestInput-static.ts | 14 +- .../NoReservedKeywordsTestInput-string.ts | 22 +- .../NoReservedKeywordsTestInput-super.ts | 8 +- .../NoReservedKeywordsTestInput-switch.ts | 9 +- .../NoReservedKeywordsTestInput-symbol.ts | 22 +- .../NoReservedKeywordsTestInput-this.ts | 8 +- .../NoReservedKeywordsTestInput-throw.ts | 8 +- .../NoReservedKeywordsTestInput-true.ts | 8 +- .../NoReservedKeywordsTestInput-try.ts | 9 +- .../NoReservedKeywordsTestInput-type.ts | 26 +- .../NoReservedKeywordsTestInput-typeof.ts | 8 +- .../NoReservedKeywordsTestInput-var.ts | 8 +- .../NoReservedKeywordsTestInput-void.ts | 8 +- .../NoReservedKeywordsTestInput-while.ts | 9 +- .../NoReservedKeywordsTestInput-with.ts | 9 +- .../NoReservedKeywordsTestInput-yield.ts | 14 +- .../NoStringBasedSetImmediateTestInput.ts | 61 +- .../NoStringBasedSetIntervalTestInput.ts | 62 +- ...etTimeoutFailingTestInput-any-functions.ts | 6 +- ...etTimeoutFailingTestInput-any-variables.ts | 8 +- ...dSetTimeoutFailingTestInput-constructor.ts | 3 +- ...edSetTimeoutFailingTestInput-parameters.ts | 11 +- ...imeoutFailingTestInput-string-functions.ts | 10 +- ...TimeoutFailingTestInput-string-literals.ts | 1 - ...imeoutFailingTestInput-string-variables.ts | 8 +- ...imeoutFailingTestInput-template-strings.ts | 4 +- .../NoStringBasedSetTimeoutTestInput-case2.ts | 12 +- .../NoStringBasedSetTimeoutTestInput-case3.ts | 13 +- .../NoStringBasedSetTimeoutTestInput-case4.ts | 6 +- .../NoStringBasedSetTimeoutTestInput-error.ts | 3 +- ...NoStringBasedSetTimeoutTestInput-error3.ts | 15 +- ...NoStringBasedSetTimeoutTestInput-error4.ts | 7 +- ...NoStringBasedSetTimeoutTestInput-error5.ts | 17 +- ...SetTimeoutTestInput-formerFalsePositive.ts | 5 +- ...oStringBasedSetTimeoutTestInput-issue46.ts | 12 +- ...edSetTimeoutTestInput-shadowedVariables.ts | 54 +- test-data/NoUnnecessarySemicolonsTestInput.ts | 5 +- test-data/PreferTypeCastRuleTests-passing.tsx | 2 +- .../ReactThisBindingIssue-anon-instance.tsx | 29 +- .../ReactThisBindingIssue-doublebinding.tsx | 10 +- .../ReactThisBindingIssue-local-instance.tsx | 12 +- .../ReactThisBindingIssue-passing.tsx | 24 +- .../ReactThisBindingIssue-unbound.tsx | 18 +- ...tThisBindingIssueWithDecorator-passing.tsx | 23 +- ...HasEmptyAltValueAndNotPresentationRole.tsx | 16 +- .../CustomElementHasNoAltProp.tsx | 12 +- ...HasNonEmptyAltValueAndPresentationRole.tsx | 16 +- ...NonEmptyAltValueAndNotPresentationRole.tsx | 16 +- .../ElementNeitherImgNorCustomElement.tsx | 8 +- .../FailingTestInputs/ImgElementHasNoAlt.tsx | 6 +- ...HasNonEmptyAltValueAndPresentationRole.tsx | 17 +- .../PassingTestInputs/ElementNotImg.tsx | 8 +- ...NonEmptyAltValueAndNotPresentationRole.tsx | 10 +- ...HasNonEmptyAltValueAndPresentationRole.tsx | 10 +- ...tyAltValueAndUndefinedPresentationRole.tsx | 10 +- .../ImgElementHasSpreadAttribute.tsx | 6 +- .../ImgElementNotLowerCase.tsx | 10 +- .../InvalidAriaAttributeName.tsx | 12 +- .../PassingTestInputs/AttributeNotAria.tsx | 12 +- .../CorrectAriaAttributeName.tsx | 10 +- .../FailingTestInputs/boolean.tsx | 10 +- .../FailingTestInputs/integer.tsx | 16 +- .../FailingTestInputs/notAllowUndefined.tsx | 6 +- .../FailingTestInputs/number.tsx | 10 +- .../FailingTestInputs/string.tsx | 8 +- .../a11yProptypes/FailingTestInputs/token.tsx | 12 +- .../FailingTestInputs/tokenlist.tsx | 14 +- .../FailingTestInputs/tristate.tsx | 10 +- .../PassingTestInputs/allowUndefined.tsx | 12 +- .../PassingTestInputs/boolean.tsx | 14 +- .../canNotCheckUntilRunTime.tsx | 20 +- .../PassingTestInputs/integer.tsx | 16 +- .../PassingTestInputs/number.tsx | 18 +- .../PassingTestInputs/string.tsx | 6 +- .../a11yProptypes/PassingTestInputs/token.tsx | 24 +- .../PassingTestInputs/tokenlist.tsx | 18 +- .../PassingTestInputs/tristate.tsx | 14 +- .../FailingTestInputs/AbstractRole.tsx | 8 +- .../FailingTestInputs/InvalidRole.tsx | 8 +- .../PassingTestInputs/AttributeNotRole.tsx | 8 +- .../PassingTestInputs/CorrectName.tsx | 10 +- .../PassingTestInputs/MultipleCorrectRole.tsx | 8 +- .../RoleNameNotStringLiteral.tsx | 6 +- .../ExplicitRoleMissingRequiredProps.tsx | 10 +- .../AttributeHasNoValidRole.tsx | 14 +- .../RoleHasNoRequiredProps.tsx | 8 +- ...oleValueAndAttributesHaveRequiredProps.tsx | 16 +- .../RoleValueNotLiteralString.tsx | 6 +- ...ntHasNotSupportedAriaPropsForEmptyRole.tsx | 6 +- ...asNotSupportedAriaPropsForExplicitRole.tsx | 8 +- ...asNotSupportedAriaPropsForImplicitRole.tsx | 8 +- .../CustomElementSupportsAllAriaProps.tsx | 14 +- .../ExplicitRoleSupportsAllAriaProps.tsx | 60 +- .../ImplicitRoleSupportsAllAriaProps.tsx | 46 +- .../UnretrievableRoleSupportsAllAriaProps.tsx | 62 +- .../TabindexValueNotNumericLiteral.tsx | 8 +- .../AttributeNotTabindex.tsx | 10 +- .../CorrectTabindexValue.tsx | 10 +- .../TabindexValueNotLiteral.tsx | 8 +- 425 files changed, 15204 insertions(+), 15060 deletions(-) diff --git a/build-tasks/common/files.js b/build-tasks/common/files.js index 5308590f6..d896648ca 100644 --- a/build-tasks/common/files.js +++ b/build-tasks/common/files.js @@ -1,21 +1,21 @@ -const { red } = require('chalk'); -const fs = require('fs'); +const { red } = require("chalk"); +const fs = require("fs"); const stripJsonComments = require("strip-json-comments"); function readFile(fileName) { try { - return fs.readFileSync(fileName, { encoding: 'utf8' }); + return fs.readFileSync(fileName, { encoding: "utf8" }); } catch (e) { - console.log(red(`Unable to read file: ${ fileName }. Error code: ${ e.code }`)); + console.log(red(`Unable to read file: ${fileName}. Error code: ${e.code}`)); process.exit(1); } } function writeFile(fileName, data) { try { - return fs.writeFileSync(fileName, data, { encoding: 'utf8' }); + return fs.writeFileSync(fileName, data, { encoding: "utf8" }); } catch (e) { - console.log(red(`Unable to write file: ${ fileName }. Error code: ${ e.code }`)); + console.log(red(`Unable to write file: ${fileName}. Error code: ${e.code}`)); process.exit(1); } } @@ -24,7 +24,7 @@ function readJSON(fileName) { try { return JSON.parse(readFile(fileName)); } catch (e) { - console.log(red(`Unable to parse JSON file: ${ fileName }. \n ${ e }`)); + console.log(red(`Unable to parse JSON file: ${fileName}. \n ${e}`)); process.exit(1); } } @@ -33,7 +33,7 @@ function readJSONWithComments(fileName) { try { return JSON.parse(stripJsonComments(readFile(fileName))); } catch (e) { - console.log(red(`Unable to parse commented JSON file: ${ fileName }. \n ${ e }`)); + console.log(red(`Unable to parse commented JSON file: ${fileName}. \n ${e}`)); process.exit(1); } } diff --git a/build-tasks/common/meta.js b/build-tasks/common/meta.js index 366fd795b..03ce8425a 100644 --- a/build-tasks/common/meta.js +++ b/build-tasks/common/meta.js @@ -1,19 +1,19 @@ -const path = require('path'); -const glob = require('glob'); -const { readJSON } = require('./files'); +const path = require("path"); +const glob = require("glob"); +const { readJSON } = require("./files"); function getAllRules() { - const contribRules = glob.sync('dist/build/*Rule.js'); - const baseRules = glob.sync('node_modules/tslint/lib/rules/*Rule.js'); + const contribRules = glob.sync("dist/build/*Rule.js"); + const baseRules = glob.sync("node_modules/tslint/lib/rules/*Rule.js"); return contribRules.concat(baseRules); } function getMetadataFromFile(ruleFile) { - const moduleName = path.resolve(ruleFile.replace(/\.js$/, '')); + const moduleName = path.resolve(ruleFile.replace(/\.js$/, "")); const module = require(moduleName); if (module.Rule.metadata === undefined) { - console.log(red('No metadata found for ' + moduleName)); + console.log(red("No metadata found for " + moduleName)); process.exit(1); } return module.Rule.metadata; @@ -21,33 +21,33 @@ function getMetadataFromFile(ruleFile) { let additionalMetadata; function getMetadataValue(metadata, name, allowEmpty, doNotEscape) { - additionalMetadata = additionalMetadata || readJSON('additional_rule_metadata.json'); + additionalMetadata = additionalMetadata || readJSON("additional_rule_metadata.json"); let value = metadata[name]; if (value === undefined) { if (additionalMetadata[metadata.ruleName] === undefined) { if (allowEmpty === false) { - console.log(red(`Could not read metadata for rule ${ metadata.ruleName } from additional_rule_metadata.json`)); + console.log(red(`Could not read metadata for rule ${metadata.ruleName} from additional_rule_metadata.json`)); process.exit(1); } else { - return ''; + return ""; } } value = additionalMetadata[metadata.ruleName][name]; if (value === undefined) { if (allowEmpty === false) { - console.log(red(`Could not read attribute ${ name } of rule ${ metadata.ruleName }`)); + console.log(red(`Could not read attribute ${name} of rule ${metadata.ruleName}`)); process.exit(1); } - return ''; + return ""; } } if (doNotEscape === true) { return value; } - value = value.replace(/^\n+/, ''); // strip leading newlines - value = value.replace(/\n/, ' '); // convert newlines - if (value.indexOf(',') > -1) { + value = value.replace(/^\n+/, ""); // strip leading newlines + value = value.replace(/\n/, " "); // convert newlines + if (value.indexOf(",") > -1) { return '"' + value + '"'; } else { return value; @@ -55,26 +55,27 @@ function getMetadataValue(metadata, name, allowEmpty, doNotEscape) { } function kebabCase(input) { - return input.split('').reduce((memo, element) => { + return input.split("").reduce((memo, element) => { if (element.toLowerCase() === element) { memo = memo + element; } else { - memo = memo + '-' + element.toLowerCase(); + memo = memo + "-" + element.toLowerCase(); } return memo; - }, ''); + }, ""); } function getContribRuleNames() { const convertToRuleNames = filename => { filename = filename - .replace(/Rule\..*/, '') // file extension plus Rule suffix - .replace(/.*\//, ''); // leading path + .replace(/Rule\..*/, "") // file extension plus Rule suffix + .replace(/.*\//, ""); // leading path return kebabCase(filename); }; - return glob.sync('src/*Rule.ts') + return glob + .sync("src/*Rule.ts") .map(convertToRuleNames) .sort(); } @@ -82,13 +83,13 @@ function getContribRuleNames() { function getAllFormatterNames() { const convertToFormatterNames = filename => { filename = filename - .replace(/Formatter\..*/, '') // file extension plus Formatter suffix - .replace(/.*\//, ''); // leading path + .replace(/Formatter\..*/, "") // file extension plus Formatter suffix + .replace(/.*\//, ""); // leading path return kebabCase(filename); }; - const formatters = glob.sync('src/*Formatter.ts').map(convertToFormatterNames); + const formatters = glob.sync("src/*Formatter.ts").map(convertToFormatterNames); formatters.sort(); return formatters; diff --git a/build-tasks/create-rule.js b/build-tasks/create-rule.js index 2d511eb54..0d0596833 100644 --- a/build-tasks/create-rule.js +++ b/build-tasks/create-rule.js @@ -1,32 +1,32 @@ -const fs = require('fs'); -const { red } = require('chalk'); -const { readJSON, writeFile } = require('./common/files'); +const fs = require("fs"); +const { red } = require("chalk"); +const { readJSON, writeFile } = require("./common/files"); const ruleName = getRuleName(); validateAguments(); -const ruleFile = camelCase(ruleName) + 'Rule'; -const sourceFileName = 'src/' + ruleFile + '.ts'; -const testsFolder = 'tests/' + ruleName; -const testFile = testsFolder + '/test.ts.lint'; -const lintFile = testsFolder + '/tslint.json'; +const ruleFile = camelCase(ruleName) + "Rule"; +const sourceFileName = "src/" + ruleFile + ".ts"; +const testsFolder = "tests/" + ruleName; +const testFile = testsFolder + "/test.ts.lint"; +const lintFile = testsFolder + "/tslint.json"; createImplementationFile(); createTestFiles(); addToConfig(); -console.log('Rule created'); -console.log('Rule source: ' + sourceFileName); -console.log('Test file: ' + testFile); +console.log("Rule created"); +console.log("Rule source: " + sourceFileName); +console.log("Test file: " + testFile); function getRuleName() { - const option = process.argv.find(str => str.startsWith('--rule-name')); + const option = process.argv.find(str => str.startsWith("--rule-name")); if (!option) { return; } - return option.split('=')[1]; + return option.split("=")[1]; } function camelCase(input) { @@ -34,10 +34,10 @@ function camelCase(input) { } function validateAguments() { - const USAGE_EXAMPLE = '\nUsage example:\nnpm run create-rule -- --rule-name=no-something-or-other\n'; + const USAGE_EXAMPLE = "\nUsage example:\nnpm run create-rule -- --rule-name=no-something-or-other\n"; if (!ruleName) { - console.log(red('--rule-name parameter is required.' + USAGE_EXAMPLE)); + console.log(red("--rule-name parameter is required." + USAGE_EXAMPLE)); process.exit(1); } @@ -48,16 +48,16 @@ function validateAguments() { } function createImplementationFile() { - const walkerName = ruleFile.charAt(0).toUpperCase() + ruleFile.substr(1) + 'Walker'; + const walkerName = ruleFile.charAt(0).toUpperCase() + ruleFile.substr(1) + "Walker"; - const ruleTemplate = require('./templates/rule.template'); - const ruleSource = ruleTemplate({ruleName, walkerName}); + const ruleTemplate = require("./templates/rule.template"); + const ruleSource = ruleTemplate({ ruleName, walkerName }); writeFile(sourceFileName, ruleSource); } function createTestFiles() { - const testContent = '// Code that should be checked by rule'; + const testContent = "// Code that should be checked by rule"; const tslintContent = { rules: { [ruleName]: true @@ -71,9 +71,9 @@ function createTestFiles() { } function addToConfig() { - const currentRuleset = readJSON('tslint.json'); + const currentRuleset = readJSON("tslint.json"); currentRuleset.rules[ruleName] = true; - writeFile('tslint.json', JSON.stringify(currentRuleset, undefined, 2)); + writeFile("tslint.json", JSON.stringify(currentRuleset, undefined, 2)); } diff --git a/build-tasks/generate-default-tslint-json.js b/build-tasks/generate-default-tslint-json.js index e27266c42..633093786 100644 --- a/build-tasks/generate-default-tslint-json.js +++ b/build-tasks/generate-default-tslint-json.js @@ -2,10 +2,10 @@ * Converts recommended_ruleset.js to ./dist/build/tslint.json. */ -const path = require('path'); -const { writeFile } = require('./common/files'); +const path = require("path"); +const { writeFile } = require("./common/files"); -const data = require(path.resolve('recommended_ruleset.js')); -data.rulesDirectory = './'; +const data = require(path.resolve("recommended_ruleset.js")); +data.rulesDirectory = "./"; -writeFile('dist/build/tslint.json', JSON.stringify(data, undefined, 2)); +writeFile("dist/build/tslint.json", JSON.stringify(data, undefined, 2)); diff --git a/build-tasks/generate-package-json-for-npm.js b/build-tasks/generate-package-json-for-npm.js index 13acdb4ec..703756889 100644 --- a/build-tasks/generate-package-json-for-npm.js +++ b/build-tasks/generate-package-json-for-npm.js @@ -2,9 +2,9 @@ * Creates a package.json file for the npm module */ -const { readJSON, writeFile } = require('./common/files'); +const { readJSON, writeFile } = require("./common/files"); -const basePackageJson = readJSON('package.json'); +const basePackageJson = readJSON("package.json"); delete basePackageJson.devDependencies; -writeFile('dist/build/package.json', JSON.stringify(basePackageJson, undefined, 2)); +writeFile("dist/build/package.json", JSON.stringify(basePackageJson, undefined, 2)); diff --git a/build-tasks/generate-recommendations.js b/build-tasks/generate-recommendations.js index 9283d967a..c90ec9435 100644 --- a/build-tasks/generate-recommendations.js +++ b/build-tasks/generate-recommendations.js @@ -2,41 +2,41 @@ * Generates the recommended_ruleset.js file. */ -const { red } = require('chalk'); -const { writeFile } = require('./common/files'); -const { getAllRules, getMetadataFromFile, getMetadataValue } = require('./common/meta'); +const { red } = require("chalk"); +const { writeFile } = require("./common/files"); +const { getAllRules, getMetadataFromFile, getMetadataValue } = require("./common/meta"); const groupedRows = {}; const warnings = []; getAllRules().forEach(ruleFile => { const metadata = getMetadataFromFile(ruleFile); - const groupName = getMetadataValue(metadata, 'group'); - if (groupName === 'Ignored') { + const groupName = getMetadataValue(metadata, "group"); + if (groupName === "Ignored") { return; } - if (groupName === '') { - warnings.push('Could not generate recommendation for rule file: ' + ruleFile); + if (groupName === "") { + warnings.push("Could not generate recommendation for rule file: " + ruleFile); } if (groupedRows[groupName] === undefined) { groupedRows[groupName] = []; } - let recommendation = getMetadataValue(metadata, 'recommendation', true, true); - if (recommendation === '') { - recommendation = 'true,'; + let recommendation = getMetadataValue(metadata, "recommendation", true, true); + if (recommendation === "") { + recommendation = "true,"; } - const ruleName = getMetadataValue(metadata, 'ruleName'); - groupedRows[groupName].push(` "${ ruleName }": ${ recommendation }`); + const ruleName = getMetadataValue(metadata, "ruleName"); + groupedRows[groupName].push(` "${ruleName}": ${recommendation}`); }); if (warnings.length > 0) { - console.log('\n' + red(warnings.join('\n'))); + console.log("\n" + red(warnings.join("\n"))); process.exit(1); } Object.keys(groupedRows).forEach(groupName => groupedRows[groupName].sort()); -const recommendedTemplate = require('./templates/recommended_ruleset.template'); +const recommendedTemplate = require("./templates/recommended_ruleset.template"); const data = recommendedTemplate(groupedRows); -writeFile('recommended_ruleset.js', data); +writeFile("recommended_ruleset.js", data); diff --git a/build-tasks/generate-rule-metadata.js b/build-tasks/generate-rule-metadata.js index 2916bce98..7bf24cfd5 100644 --- a/build-tasks/generate-rule-metadata.js +++ b/build-tasks/generate-rule-metadata.js @@ -2,8 +2,8 @@ * Generates rule-metadata.json which contains a json array of all rule metadata. */ -const { writeFile } = require('./common/files'); -const { getAllRules, getMetadataFromFile } = require('./common/meta'); +const { writeFile } = require("./common/files"); +const { getAllRules, getMetadataFromFile } = require("./common/meta"); const allMetadata = []; getAllRules().forEach(ruleFile => { @@ -11,4 +11,4 @@ getAllRules().forEach(ruleFile => { allMetadata.push(metadata); }); -writeFile('rule-metadata.json', JSON.stringify(allMetadata, undefined, 2)); +writeFile("rule-metadata.json", JSON.stringify(allMetadata, undefined, 2)); diff --git a/build-tasks/generate-sdl-report.js b/build-tasks/generate-sdl-report.js index d733b4214..f405767af 100644 --- a/build-tasks/generate-sdl-report.js +++ b/build-tasks/generate-sdl-report.js @@ -2,37 +2,37 @@ * Generates an SDL report in csv format. */ -const { red } = require('chalk'); -const { readJSON, writeFile } = require('./common/files'); -const { getAllRules, getMetadataFromFile, getMetadataValue } = require('./common/meta'); -const allCweDescriptions = readJSON('cwe_descriptions.json'); +const { red } = require("chalk"); +const { readJSON, writeFile } = require("./common/files"); +const { getAllRules, getMetadataFromFile, getMetadataValue } = require("./common/meta"); +const allCweDescriptions = readJSON("cwe_descriptions.json"); const rows = []; -const resolution = 'See description on the tslint or tslint-microsoft-contrib website'; -const procedure = 'TSLint Procedure'; -const header = 'Title,Description,ErrorID,Tool,IssueClass,IssueType,SDL Bug Bar Severity,' + - 'SDL Level,Resolution,SDL Procedure,CWE,CWE Description'; +const resolution = "See description on the tslint or tslint-microsoft-contrib website"; +const procedure = "TSLint Procedure"; +const header = + "Title,Description,ErrorID,Tool,IssueClass,IssueType,SDL Bug Bar Severity," + "SDL Level,Resolution,SDL Procedure,CWE,CWE Description"; getAllRules().forEach(ruleFile => { const metadata = getMetadataFromFile(ruleFile); - const issueClass = getMetadataValue(metadata, 'issueClass'); - if (issueClass === 'Ignored') { + const issueClass = getMetadataValue(metadata, "issueClass"); + if (issueClass === "Ignored") { return; } - const ruleName = getMetadataValue(metadata, 'ruleName'); - const errorId = 'TSLINT' + getHash(ruleName); - const issueType = getMetadataValue(metadata, 'issueType'); - const severity = getMetadataValue(metadata, 'severity'); - const level = getMetadataValue(metadata, 'level'); - const description = getMetadataValue(metadata, 'description'); - const cwe = getMetadataValue(metadata, 'commonWeaknessEnumeration', true, false); + const ruleName = getMetadataValue(metadata, "ruleName"); + const errorId = "TSLINT" + getHash(ruleName); + const issueType = getMetadataValue(metadata, "issueType"); + const severity = getMetadataValue(metadata, "severity"); + const level = getMetadataValue(metadata, "level"); + const description = getMetadataValue(metadata, "description"); + const cwe = getMetadataValue(metadata, "commonWeaknessEnumeration", true, false); const cweDescription = createCweDescription(metadata); const row = [ ruleName, description, errorId, - 'tslint', + "tslint", issueClass, issueType, severity, @@ -41,14 +41,14 @@ getAllRules().forEach(ruleFile => { procedure, cwe, cweDescription - ].join(','); + ].join(","); rows.push(row); }); rows.sort(); rows.unshift(header); -writeFile('tslint-warnings.csv', rows.join('\n')); +writeFile("tslint-warnings.csv", rows.join("\n")); function getHash(input) { // initialized with a prime number @@ -59,30 +59,32 @@ function getHash(input) { hash = 31 * hash + input.charCodeAt(i); // run the hash function on all chars hash = hash | 0; // convert to 32 bit signed integer } - return Math.abs(hash).toString(32).toUpperCase(); + return Math.abs(hash) + .toString(32) + .toUpperCase(); } function createCweDescription(metadata) { - const cwe = getMetadataValue(metadata, 'commonWeaknessEnumeration', true, true); - if (cwe === '') { - return ''; + const cwe = getMetadataValue(metadata, "commonWeaknessEnumeration", true, true); + if (cwe === "") { + return ""; } - let result = ''; - cwe.split(',').forEach(cweNumber => { + let result = ""; + cwe.split(",").forEach(cweNumber => { cweNumber = cweNumber.trim(); const description = allCweDescriptions[cweNumber]; if (description === undefined) { - console.log(red(`Cannot find description of ${ cweNumber } for rule ${ metadata.ruleName } in cwe_descriptions.json`)); + console.log(red(`Cannot find description of ${cweNumber} for rule ${metadata.ruleName} in cwe_descriptions.json`)); process.exit(1); } - if (result !== '') { - result = result + '\n'; + if (result !== "") { + result = result + "\n"; } - result = result + `CWE ${ cweNumber } - ${ description }`; + result = result + `CWE ${cweNumber} - ${description}`; }); - if (result !== '') { - return `"${ result }"`; + if (result !== "") { + return `"${result}"`; } return result; } diff --git a/build-tasks/templates/recommended_ruleset.template.js b/build-tasks/templates/recommended_ruleset.template.js index 76c0b347f..b679f125c 100644 --- a/build-tasks/templates/recommended_ruleset.template.js +++ b/build-tasks/templates/recommended_ruleset.template.js @@ -1,5 +1,5 @@ -module.exports = (rows) => -`/** +module.exports = rows => + `/** * These rule settings are a broad, general recommendation for a good default configuration. * This file is exported in the npm/nuget package as ./tslint.json. */ @@ -10,41 +10,41 @@ module.exports = { * Security Rules. The following rules should be turned on because they find security issues * or are recommended in the Microsoft Secure Development Lifecycle (SDL) */ -${rows.Security.join('\n')} +${rows.Security.join("\n")} /** * Common Bugs and Correctness. The following rules should be turned on because they find * common bug patterns in the code or enforce type safety. */ -${rows.Correctness.join('\n')} +${rows.Correctness.join("\n")} /** * Code Clarity. The following rules should be turned on because they make the code * generally more clear to the reader. */ -${rows.Clarity.join('\n')} +${rows.Clarity.join("\n")} /** * Accessibility. The following rules should be turned on to guarantee the best user * experience for keyboard and screen reader users. */ -${rows.Accessibility.join('\n')} +${rows.Accessibility.join("\n")} /** * Whitespace related rules. The only recommended whitespace strategy is to pick a single format and * be consistent. */ -${rows.Whitespace.join('\n')} +${rows.Whitespace.join("\n")} /** * Controversial/Configurable rules. */ -${rows.Configurable.join('\n')} +${rows.Configurable.join("\n")} /** * Deprecated rules. The following rules are deprecated for various reasons. */ -${rows.Deprecated.join('\n')} +${rows.Deprecated.join("\n")} } }; `; diff --git a/build-tasks/templates/rule.template.js b/build-tasks/templates/rule.template.js index bf38840f8..72e89a69e 100644 --- a/build-tasks/templates/rule.template.js +++ b/build-tasks/templates/rule.template.js @@ -1,5 +1,5 @@ -module.exports = ({ruleName, walkerName}) => -`import * as ts from 'typescript'; +module.exports = ({ ruleName, walkerName }) => + `import * as ts from 'typescript'; import * as Lint from 'tslint'; import {ExtendedMetadata} from './utils/ExtendedMetadata'; diff --git a/build-tasks/validate-config.js b/build-tasks/validate-config.js index 1a6180552..17fec87e9 100644 --- a/build-tasks/validate-config.js +++ b/build-tasks/validate-config.js @@ -2,18 +2,18 @@ * Makes sure all the rules in the project are defined to run during the build. */ -const { yellow, yellowBright } = require('chalk'); -const { readJSONWithComments } = require('./common/files'); -const { getContribRuleNames } = require('./common/meta'); +const { yellow, yellowBright } = require("chalk"); +const { readJSONWithComments } = require("./common/files"); +const { getContribRuleNames } = require("./common/meta"); -const tslintConfig = readJSONWithComments('tslint.json'); +const tslintConfig = readJSONWithComments("tslint.json"); function ruleIsEnabled(value) { if (value === undefined) { return false; } - if (typeof value === 'boolean') { + if (typeof value === "boolean") { return value; } @@ -21,17 +21,17 @@ function ruleIsEnabled(value) { } const disabledRules = new Set([ - 'missing-jsdoc', - 'no-duplicate-case', - 'no-empty-interfaces', - 'no-empty-line-after-opening-brace', - 'no-multiline-string', - 'no-relative-imports', - 'no-stateless-class', - 'no-unexternalized-strings', - 'no-var-self', - 'react-tsx-curly-spacing', - 'valid-typeof' + "missing-jsdoc", + "no-duplicate-case", + "no-empty-interfaces", + "no-empty-line-after-opening-brace", + "no-multiline-string", + "no-relative-imports", + "no-stateless-class", + "no-unexternalized-strings", + "no-var-self", + "react-tsx-curly-spacing", + "valid-typeof" ]); const errors = []; @@ -41,12 +41,12 @@ getContribRuleNames().forEach(ruleName => { } if (!ruleIsEnabled(tslintConfig.rules[ruleName])) { - errors.push('A tslint-microsoft-contrib rule was found that is not enabled on the project: ' + ruleName); + errors.push("A tslint-microsoft-contrib rule was found that is not enabled on the project: " + ruleName); } }); if (errors.length > 0) { - console.log(yellow(errors.join('\n'))); - console.log(yellowBright(`Add the missing rule${errors.length === 1 ? '' : 's'} to tslint.json.`)); + console.log(yellow(errors.join("\n"))); + console.log(yellowBright(`Add the missing rule${errors.length === 1 ? "" : "s"} to tslint.json.`)); process.exit(1); } diff --git a/build-tasks/validate-documentation.js b/build-tasks/validate-documentation.js index bdbd09b04..1b7f1d43b 100644 --- a/build-tasks/validate-documentation.js +++ b/build-tasks/validate-documentation.js @@ -3,34 +3,38 @@ * and validates that the package.json version is the same version defined in README.md. */ -const { yellowBright } = require('chalk'); -const { readFile, readJSON } = require('./common/files'); -const { getAllFormatterNames, getContribRuleNames } = require('./common/meta'); +const { yellowBright } = require("chalk"); +const { readFile, readJSON } = require("./common/files"); +const { getAllFormatterNames, getContribRuleNames } = require("./common/meta"); -const readmeText = readFile('README.md'); -const packageJson = readJSON('package.json'); +const readmeText = readFile("README.md"); +const packageJson = readJSON("package.json"); const validationErrors = []; getContribRuleNames().forEach(ruleName => { if (readmeText.indexOf(ruleName) === -1) { - validationErrors.push('A rule was found that is not documented in README.md: ' + ruleName); + validationErrors.push("A rule was found that is not documented in README.md: " + ruleName); } }); getAllFormatterNames().forEach(formatterName => { if (readmeText.indexOf(formatterName) === -1) { - validationErrors.push('A formatter was found that is not documented in README.md: ' + formatterName); + validationErrors.push("A formatter was found that is not documented in README.md: " + formatterName); validationFailed = true; } }); -if (readmeText.indexOf('[npm-' + packageJson.version + ']') === -1) { - validationErrors.push('Version not documented in README.md correctly.\n' + - 'package.json declares: ' + packageJson.version + '\n' + - 'README.md declares something different.'); +if (readmeText.indexOf("[npm-" + packageJson.version + "]") === -1) { + validationErrors.push( + "Version not documented in README.md correctly.\n" + + "package.json declares: " + + packageJson.version + + "\n" + + "README.md declares something different." + ); } if (validationErrors.length > 0) { - console.log(yellowBright(validationErrors.join('\n'))); + console.log(yellowBright(validationErrors.join("\n"))); process.exit(1); } diff --git a/build-tasks/watch-run-tests.js b/build-tasks/watch-run-tests.js index 98b15d259..30b0f42e8 100644 --- a/build-tasks/watch-run-tests.js +++ b/build-tasks/watch-run-tests.js @@ -1,6 +1,6 @@ -const { yellowBright, red, green } = require('chalk'); -const chokidar = require('chokidar'); -const runAll = require('npm-run-all'); +const { yellowBright, red, green } = require("chalk"); +const chokidar = require("chokidar"); +const runAll = require("npm-run-all"); const changes = new Set(); let testsRunning = false; @@ -15,35 +15,36 @@ function simpleDebounce(delay, fn) { } function runTests() { - console.log(green('\nStarting tests')); + console.log(green("\nStarting tests")); testsRunning = true; - return runAll(['test:*', 'lint:*'], { + return runAll(["test:*", "lint:*"], { stdin: process.stdin, stdout: process.stdout, stderr: process.stderr }) - .then(() => console.log(green('\nSuccess.'))) - .catch(() => console.error(red('\nFailure!'))) - .then(() => { testsRunning = false; }) + .then(() => console.log(green("\nSuccess."))) + .catch(() => console.error(red("\nFailure!"))) + .then(() => { + testsRunning = false; + }); } const scheduleTests = simpleDebounce(1000, () => { - console.log(yellowBright('Scheduling new tests because of changes in: \n') + [...changes].join('\n')); + console.log(yellowBright("Scheduling new tests because of changes in: \n") + [...changes].join("\n")); changes.clear(); - runTests() - .then(() => { - if (changes.size > 0) { - scheduleTests(); - } - }); + runTests().then(() => { + if (changes.size > 0) { + scheduleTests(); + } + }); }); function registerChange(path) { - console.log(yellowBright('Registered change: ') + path); + console.log(yellowBright("Registered change: ") + path); changes.add(path); if (!testsRunning) { @@ -51,19 +52,17 @@ function registerChange(path) { } } -const fileWatcher = chokidar - .watch(['dist/src/**/*.js', 'test-data/**', 'tests/**']); +const fileWatcher = chokidar.watch(["dist/src/**/*.js", "test-data/**", "tests/**"]); function subscribeFileEvents() { fileWatcher - .on('add', registerChange) - .on('change', registerChange) - .on('unlink', registerChange); + .on("add", registerChange) + .on("change", registerChange) + .on("unlink", registerChange); } -fileWatcher.on('ready', () => { - const watchedCount = Object.keys(fileWatcher.getWatched()) - .reduce((memo, items) => memo + items.length, 0); +fileWatcher.on("ready", () => { + const watchedCount = Object.keys(fileWatcher.getWatched()).reduce((memo, items) => memo + items.length, 0); console.log(`Watching ${watchedCount} files and folders.`); subscribeFileEvents(); diff --git a/recommended_ruleset.js b/recommended_ruleset.js index 57e536151..43accde94 100644 --- a/recommended_ruleset.js +++ b/recommended_ruleset.js @@ -3,8 +3,7 @@ * This file is exported in the npm/nuget package as ./tslint.json. */ module.exports = { - "rules": { - + rules: { /** * Security Rules. The following rules should be turned on because they find security issues * or are recommended in the Microsoft Secure Development Lifecycle (SDL) @@ -38,7 +37,7 @@ module.exports = { * common bug patterns in the code or enforce type safety. */ "await-promise": true, - "forin": true, + forin: true, "jquery-deferred-must-complete": true, "label-position": true, "match-default-export-name": true, @@ -87,7 +86,7 @@ module.exports = { "no-with-statement": true, "promise-function-async": true, "promise-must-complete": true, - "radix": true, + radix: true, "react-this-binding-issue": true, "react-unused-props-and-state": true, "restrict-plus-operands": true, // the plus operand should really only be used for strings and numbers @@ -120,12 +119,12 @@ module.exports = { "informative-docs": true, "interface-name": true, "jsdoc-format": true, - "max-classes-per-file": [true, 3], // we generally recommend making one public class per file + "max-classes-per-file": [true, 3], // we generally recommend making one public class per file "max-file-line-count": true, - "max-func-body-length": [true, 100, {"ignore-parameters-to-function-regex": "^describe$"}], + "max-func-body-length": [true, 100, { "ignore-parameters-to-function-regex": "^describe$" }], "max-line-length": [true, 140], "member-access": true, - "member-ordering": [true, { "order": "fields-first" }], + "member-ordering": [true, { order: "fields-first" }], "mocha-unneeded-done": true, "new-parens": true, "newline-per-chained-call": true, @@ -160,7 +159,7 @@ module.exports = { "number-literal-format": true, "object-literal-sort-keys": false, // turn object-literal-sort-keys off and sort keys in a meaningful manner "one-variable-per-declaration": true, - "only-arrow-functions": false, // there are many valid reasons to declare a function + "only-arrow-functions": false, // there are many valid reasons to declare a function "ordered-imports": true, "prefer-array-literal": true, "prefer-const": true, @@ -171,7 +170,16 @@ module.exports = { "prefer-template": true, "prefer-while": true, "type-literal-delimiter": true, - "typedef": [true, "call-signature", "arrow-call-signature", "parameter", "arrow-parameter", "property-declaration", "variable-declaration", "member-variable-declaration"], + typedef: [ + true, + "call-signature", + "arrow-call-signature", + "parameter", + "arrow-parameter", + "property-declaration", + "variable-declaration", + "member-variable-declaration" + ], "underscore-consistent-invocation": true, "unified-signatures": true, "use-default-type-parameter": true, @@ -203,12 +211,12 @@ module.exports = { * Whitespace related rules. The only recommended whitespace strategy is to pick a single format and * be consistent. */ - "align": [true, "parameters", "arguments", "statements"], - "curly": true, - "encoding": true, - "eofline": true, + align: [true, "parameters", "arguments", "statements"], + curly: true, + encoding: true, + eofline: true, "import-spacing": true, - "indent": [true, "spaces"], + indent: [true, "spaces"], "linebreak-style": true, "newline-before-return": true, "no-consecutive-blank-lines": true, @@ -219,57 +227,57 @@ module.exports = { "no-unnecessary-semicolons": true, "object-literal-key-quotes": [true, "as-needed"], "one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"], - "quotemark": [true, "single"], - "semicolon": [true, "always"], + quotemark: [true, "single"], + semicolon: [true, "always"], "space-within-parens": true, - "trailing-comma": [true, {"singleline": "never", "multiline": "never"}], // forcing trailing commas for multi-line - // lists results in lists that are easier to reorder and version control diffs that are more clear. - // Many teams like to have multiline be 'always'. There is no clear consensus on this rule but the - // internal MS JavaScript coding standard does discourage it. + "trailing-comma": [true, { singleline: "never", multiline: "never" }], // forcing trailing commas for multi-line + // lists results in lists that are easier to reorder and version control diffs that are more clear. + // Many teams like to have multiline be 'always'. There is no clear consensus on this rule but the + // internal MS JavaScript coding standard does discourage it. "typedef-whitespace": false, - "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type"], + whitespace: [true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type"], /** * Controversial/Configurable rules. */ - "ban": false, // only enable this if you have some code pattern that you want to ban + ban: false, // only enable this if you have some code pattern that you want to ban "ban-types": true, "cyclomatic-complexity": true, - "deprecation": false, // deprecated APIs are sometimes unavoidable - "file-header": false, // enable this rule only if you are legally required to add a file header - "import-blacklist": false, // enable and configure this as you desire - "interface-over-type-literal": false, // there are plenty of reasons to prefer interfaces - "no-angle-bracket-type-assertion": false, // pick either type-cast format and use it consistently - "no-inferred-empty-object-type": false, // if the compiler is satisfied then this is probably not an issue + deprecation: false, // deprecated APIs are sometimes unavoidable + "file-header": false, // enable this rule only if you are legally required to add a file header + "import-blacklist": false, // enable and configure this as you desire + "interface-over-type-literal": false, // there are plenty of reasons to prefer interfaces + "no-angle-bracket-type-assertion": false, // pick either type-cast format and use it consistently + "no-inferred-empty-object-type": false, // if the compiler is satisfied then this is probably not an issue "no-internal-module": false, // only enable this if you are not using internal modules - "no-magic-numbers": false, // by default it will find too many false positives - "no-mergeable-namespace": false, // your project may require mergeable namespaces - "no-namespace": false, // only enable this if you are not using modules/namespaces - "no-reference": true, // in general you should use a module system and not /// reference imports + "no-magic-numbers": false, // by default it will find too many false positives + "no-mergeable-namespace": false, // your project may require mergeable namespaces + "no-namespace": false, // only enable this if you are not using modules/namespaces + "no-reference": true, // in general you should use a module system and not /// reference imports "no-unexternalized-strings": false, // the VS Code team has a specific localization process that this rule enforces - "object-literal-shorthand": false, // object-literal-shorthand offers an abbreviation not an abstraction + "object-literal-shorthand": false, // object-literal-shorthand offers an abbreviation not an abstraction "prefer-conditional-expression": false, // unnecessarily strict "prefer-switch": false, // more of a style preference - "prefer-type-cast": true, // pick either type-cast format and use it consistently + "prefer-type-cast": true, // pick either type-cast format and use it consistently "return-undefined": false, // this actually affect the readability of the code - "space-before-function-paren": false, // turn this on if this is really your coding standard + "space-before-function-paren": false, // turn this on if this is really your coding standard /** * Deprecated rules. The following rules are deprecated for various reasons. */ "missing-jsdoc": false, - "missing-optional-annotation": false, // now supported by TypeScript compiler + "missing-optional-annotation": false, // now supported by TypeScript compiler "no-duplicate-case": false, "no-duplicate-parameter-names": false, // now supported by TypeScript compiler "no-empty-interfaces": false, // use tslint no-empty-interface rule instead "no-missing-visibility-modifiers": false, // use tslint member-access rule instead - "no-multiple-var-decl": false, // use tslint one-variable-per-declaration rule instead + "no-multiple-var-decl": false, // use tslint one-variable-per-declaration rule instead "no-stateless-class": false, - "no-switch-case-fall-through": false, // now supported by TypeScript compiler + "no-switch-case-fall-through": false, // now supported by TypeScript compiler "no-unnecessary-class": true, "no-var-self": false, "react-tsx-curly-spacing": false, - "typeof-compare": false, // the valid-typeof rule is currently superior to this version - "valid-typeof": false, + "typeof-compare": false, // the valid-typeof rule is currently superior to this version + "valid-typeof": false } }; diff --git a/src/.baseDir.ts b/src/.baseDir.ts index ec32b31ec..f873e7d77 100644 --- a/src/.baseDir.ts +++ b/src/.baseDir.ts @@ -1 +1 @@ -// Ignore this file. See https://github.com/grunt-ts/grunt-ts/issues/77 \ No newline at end of file +// Ignore this file. See https://github.com/grunt-ts/grunt-ts/issues/77 diff --git a/src/chaiPreferContainsToIndexOfRule.ts b/src/chaiPreferContainsToIndexOfRule.ts index 1670e2d7b..43f09ca4b 100644 --- a/src/chaiPreferContainsToIndexOfRule.ts +++ b/src/chaiPreferContainsToIndexOfRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ChaiUtils} from './utils/ChaiUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ChaiUtils } from "./utils/ChaiUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Found chai call with indexOf that can be converted to .contain assertion: '; +const FAILURE_STRING: string = "Found chai call with indexOf that can be converted to .contain assertion: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'chai-prefer-contains-to-index-of', - type: 'maintainability', - description: 'Avoid Chai assertions that invoke indexOf and compare for a -1 result.', + ruleName: "chai-prefer-contains-to-index-of", + type: "maintainability", + description: "Avoid Chai assertions that invoke indexOf and compare for a -1 result.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,7 +29,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class ChaiPreferContainsToIndexOfRuleWalker extends Lint.RuleWalker { - protected visitCallExpression(node: ts.CallExpression): void { if (ChaiUtils.isExpectInvocation(node)) { if (this.isFirstArgumentIndexOfResult(node)) { @@ -49,7 +47,7 @@ class ChaiPreferContainsToIndexOfRuleWalker extends Lint.RuleWalker { private isFirstArgumentNegative1(node: ts.CallExpression): boolean { if (node.arguments !== undefined && node.arguments.length > 0) { const firstArgument: ts.Expression = node.arguments[0]; - if (firstArgument.getText() === '-1') { + if (firstArgument.getText() === "-1") { return true; } } @@ -61,7 +59,7 @@ class ChaiPreferContainsToIndexOfRuleWalker extends Lint.RuleWalker { if (expectCall !== undefined && expectCall.arguments !== undefined && expectCall.arguments.length > 0) { const firstArgument: ts.Expression = expectCall.arguments[0]; if (firstArgument.kind === ts.SyntaxKind.CallExpression) { - if (AstUtils.getFunctionName(firstArgument) === 'indexOf') { + if (AstUtils.getFunctionName(firstArgument) === "indexOf") { return true; } } diff --git a/src/chaiVagueErrorsRule.ts b/src/chaiVagueErrorsRule.ts index 1e3a2a3f6..dc24493fa 100644 --- a/src/chaiVagueErrorsRule.ts +++ b/src/chaiVagueErrorsRule.ts @@ -1,31 +1,30 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ChaiUtils } from './utils/ChaiUtils'; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; +import { ChaiUtils } from "./utils/ChaiUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const BASE_ERROR: string = 'Found chai call with vague failure message. '; -const FAILURE_STRING: string = BASE_ERROR + 'Please add an explicit failure message'; -const FAILURE_STRING_COMPARE_TRUE: string = BASE_ERROR + 'Move the strict equality comparison from the expect ' + - 'call into the assertion value'; -const FAILURE_STRING_COMPARE_FALSE: string = BASE_ERROR + 'Move the strict inequality comparison from the expect ' + - 'call into the assertion value. '; +const BASE_ERROR: string = "Found chai call with vague failure message. "; +const FAILURE_STRING: string = BASE_ERROR + "Please add an explicit failure message"; +const FAILURE_STRING_COMPARE_TRUE: string = + BASE_ERROR + "Move the strict equality comparison from the expect " + "call into the assertion value"; +const FAILURE_STRING_COMPARE_FALSE: string = + BASE_ERROR + "Move the strict inequality comparison from the expect " + "call into the assertion value. "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'chai-vague-errors', - type: 'maintainability', - description: 'Avoid Chai assertions that result in vague errors', + ruleName: "chai-vague-errors", + type: "maintainability", + description: "Avoid Chai assertions that result in vague errors", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -64,12 +63,12 @@ class ChaiVagueErrorsRuleWalker extends Lint.RuleWalker { if (expectedValue !== undefined) { const binaryExpression: ts.BinaryExpression = actualValue; const operator: string = binaryExpression.operatorToken.getText(); - const expectingBooleanKeyword: boolean = expectedValue.kind === ts.SyntaxKind.TrueKeyword - || expectedValue.kind === ts.SyntaxKind.FalseKeyword; + const expectingBooleanKeyword: boolean = + expectedValue.kind === ts.SyntaxKind.TrueKeyword || expectedValue.kind === ts.SyntaxKind.FalseKeyword; - if (operator === '===' && expectingBooleanKeyword) { + if (operator === "===" && expectingBooleanKeyword) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING_COMPARE_TRUE); - } else if (operator === '!==' && expectingBooleanKeyword) { + } else if (operator === "!==" && expectingBooleanKeyword) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING_COMPARE_FALSE); } } diff --git a/src/exportNameRule.ts b/src/exportNameRule.ts index 759678016..09f781bff 100644 --- a/src/exportNameRule.ts +++ b/src/exportNameRule.ts @@ -1,36 +1,34 @@ +import * as ts from "typescript"; +import * as Lint from "tslint"; -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import { Utils } from "./utils/Utils"; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -import {Utils} from './utils/Utils'; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; - -export const OPTION_IGNORE_CASE: string = 'ignore-case'; +export const OPTION_IGNORE_CASE: string = "ignore-case"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'export-name', - type: 'maintainability', - description: 'The name of the exported module must match the filename of the source file', + ruleName: "export-name", + type: "maintainability", + description: "The name of the exported module must match the filename of the source file", options: { - type: 'list', + type: "list", listType: { anyOf: [ { - type: 'string' + type: "string" }, { - type: 'object', + type: "object", properties: { - 'ignore-case': { - type: 'boolean' + "ignore-case": { + type: "boolean" }, allow: { - type: 'array', + type: "array", items: { - type: 'string' + type: "string" } } } @@ -38,30 +36,30 @@ export class Rule extends Lint.Rules.AbstractRule { ] } }, - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "710" }; - public static FAILURE_STRING: string = 'The exported module or identifier name must match the file name. Found: '; + public static FAILURE_STRING: string = "The exported module or identifier name must match the file name. Found: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new ExportNameWalker(sourceFile, this.getOptions())); } /* tslint:disable:function-name */ - public static getExceptions(options : Lint.IOptions): string[] | undefined { - /* tslint:enable:function-name */ + public static getExceptions(options: Lint.IOptions): string[] | undefined { + /* tslint:enable:function-name */ if (options.ruleArguments instanceof Array) { return options.ruleArguments[0]; } if (options instanceof Array) { - return typeof options[0] === 'object' ? options[0].allow : options; + return typeof options[0] === "object" ? options[0].allow : options; } return undefined; } @@ -70,9 +68,7 @@ export class Rule extends Lint.Rules.AbstractRule { public static getIgnoreCase(options: Lint.IOptions): boolean { /* tslint:enable:function-name */ if (options instanceof Array) { - return typeof options[0] === 'object' ? - options[0]['ignore-case'] : - true; + return typeof options[0] === "object" ? options[0]["ignore-case"] : true; } return true; } @@ -84,24 +80,23 @@ function isExportedDeclaration(element: ts.Statement): boolean { type ExportStatement = ts.ExportDeclaration | ts.ExportAssignment; function isExportStatement(node: ts.Statement): node is ExportStatement { - return ts.isExportAssignment(node) || ts.isExportDeclaration(node); + return ts.isExportAssignment(node) || ts.isExportDeclaration(node); } function getExportsFromStatement(node: ExportStatement): [string, ts.Node][] { - if (ts.isExportAssignment(node)) { - return [[node.expression.getText(), node.expression]]; - } else { - const symbolAndNodes: [string, ts.Node][] = []; - node.exportClause!.elements.forEach(e => { - symbolAndNodes.push([e.name.getText(), node]); - }); - return symbolAndNodes; - } + if (ts.isExportAssignment(node)) { + return [[node.expression.getText(), node.expression]]; + } else { + const symbolAndNodes: [string, ts.Node][] = []; + node.exportClause!.elements.forEach(e => { + symbolAndNodes.push([e.name.getText(), node]); + }); + return symbolAndNodes; + } } export class ExportNameWalker extends Lint.RuleWalker { protected visitSourceFile(node: ts.SourceFile): void { - // look for single export assignment from file first const singleExport = node.statements.filter(isExportStatement); if (singleExport.length === 1) { @@ -118,12 +113,14 @@ export class ExportNameWalker extends Lint.RuleWalker { // exports might be hidden inside a namespace if (exportedTopLevelElements.length === 0) { - node.statements.forEach((element: ts.Statement): void => { - if (element.kind === ts.SyntaxKind.ModuleDeclaration) { - const exportStatements = this.getExportStatementsWithinModules((element)) || []; - exportedTopLevelElements = exportedTopLevelElements.concat(exportStatements); + node.statements.forEach( + (element: ts.Statement): void => { + if (element.kind === ts.SyntaxKind.ModuleDeclaration) { + const exportStatements = this.getExportStatementsWithinModules(element) || []; + exportedTopLevelElements = exportedTopLevelElements.concat(exportStatements); + } } - }); + ); } this.validateExportedElements(exportedTopLevelElements); } @@ -143,9 +140,7 @@ export class ExportNameWalker extends Lint.RuleWalker { // only validate the exported elements when a single export statement is made if (exportedElements.length === 1) { const element = exportedElements[0]; - if (ts.isModuleDeclaration(element) || - ts.isClassDeclaration(element) || - ts.isFunctionDeclaration(element)) { + if (ts.isModuleDeclaration(element) || ts.isClassDeclaration(element) || ts.isFunctionDeclaration(element)) { if (element.name !== undefined) { this.validateExport(element.name!.text, exportedElements[0]); } @@ -161,11 +156,11 @@ export class ExportNameWalker extends Lint.RuleWalker { } private validateExport(exportedName: string, node: ts.Node): void { - const flags = Rule.getIgnoreCase(this.getOptions()) ? 'i' : ''; - const regex : RegExp = new RegExp(exportedName + '\..*', flags); // filename must be exported name plus any extension + const flags = Rule.getIgnoreCase(this.getOptions()) ? "i" : ""; + const regex: RegExp = new RegExp(exportedName + "..*", flags); // filename must be exported name plus any extension if (!regex.test(this.getFilename())) { if (!this.isSuppressed(exportedName)) { - const failureString: string = Rule.FAILURE_STRING + this.getSourceFile().fileName + ' and ' + exportedName; + const failureString: string = Rule.FAILURE_STRING + this.getSourceFile().fileName + " and " + exportedName; this.addFailureAt(node.getStart(), node.getWidth(), failureString); } } @@ -173,18 +168,21 @@ export class ExportNameWalker extends Lint.RuleWalker { private getFilename(): string { const filename = this.getSourceFile().fileName; - const lastSlash = filename.lastIndexOf('/'); + const lastSlash = filename.lastIndexOf("/"); if (lastSlash > -1) { return filename.substring(lastSlash + 1); } return filename; } - private isSuppressed(exportedName: string) : boolean { + private isSuppressed(exportedName: string): boolean { const allExceptions = Rule.getExceptions(this.getOptions()); - return Utils.exists(allExceptions, (exception: string): boolean => { - return new RegExp(exception).test(exportedName); - }); + return Utils.exists( + allExceptions, + (exception: string): boolean => { + return new RegExp(exception).test(exportedName); + } + ); } } diff --git a/src/fixNoRequireImportsFormatter.ts b/src/fixNoRequireImportsFormatter.ts index 8e5c9a527..b82db820d 100644 --- a/src/fixNoRequireImportsFormatter.ts +++ b/src/fixNoRequireImportsFormatter.ts @@ -1,7 +1,7 @@ -'use strict'; +"use strict"; -import {RuleFailure} from 'tslint'; -import {BaseFormatter} from './utils/BaseFormatter'; +import { RuleFailure } from "tslint"; +import { BaseFormatter } from "./utils/BaseFormatter"; let warnedForDeprecation = false; @@ -10,40 +10,38 @@ let warnedForDeprecation = false; */ /* tslint:disable:export-name */ export class Formatter extends BaseFormatter { -/* tslint:enable:export-name */ + /* tslint:enable:export-name */ constructor() { if (!warnedForDeprecation) { - console.warn('The fix-no-require-imports formatter is deprecated. Use --fix instead.'); + console.warn("The fix-no-require-imports formatter is deprecated. Use --fix instead."); warnedForDeprecation = true; } - super('no-require-imports', function (this: Formatter, failure: RuleFailure): void { + super("no-require-imports", function(this: Formatter, failure: RuleFailure): void { const fileName: string = failure.getFileName(); const fileContents: string = this.readFile(fileName); const start: number = failure.getStartPosition().getPosition(); const end: number = failure.getEndPosition().getPosition(); - let importStartIndex = fileContents.lastIndexOf('\n', start) + 1; + let importStartIndex = fileContents.lastIndexOf("\n", start) + 1; if (importStartIndex === -1) { importStartIndex = 0; } - const importEndIndex = fileContents.indexOf('\n', end); + const importEndIndex = fileContents.indexOf("\n", end); const leftSide: string = fileContents.substring(0, importStartIndex); const middle: string = fileContents.substring(importStartIndex, importEndIndex).trim(); const rightSide: string = fileContents.substring(importEndIndex); - let newImport: string = middle.replace( - /import\s+(.*)\s+=\s*require\(((.|\s)*)\);/m, - 'import {$1} from $2;'); - newImport = newImport.replace(/from \n/, 'from\n'); // clean up some spacing + let newImport: string = middle.replace(/import\s+(.*)\s+=\s*require\(((.|\s)*)\);/m, "import {$1} from $2;"); + newImport = newImport.replace(/from \n/, "from\n"); // clean up some spacing const newContent: string = leftSide + newImport + rightSide; this.writeFile(fileName, newContent); /* tslint:disable:no-console */ - console.log('Automatically converting require-style import to an ES6 import. Please re-compile and re-lint: ' + fileName); + console.log("Automatically converting require-style import to an ES6 import. Please re-compile and re-lint: " + fileName); /* tslint:enable:no-console */ }); } -} \ No newline at end of file +} diff --git a/src/fixNoVarKeywordFormatter.ts b/src/fixNoVarKeywordFormatter.ts index 5c6016c08..b8b6272ba 100644 --- a/src/fixNoVarKeywordFormatter.ts +++ b/src/fixNoVarKeywordFormatter.ts @@ -1,7 +1,7 @@ -'use strict'; +"use strict"; -import {RuleFailure} from 'tslint'; -import {BaseFormatter} from './utils/BaseFormatter'; +import { RuleFailure } from "tslint"; +import { BaseFormatter } from "./utils/BaseFormatter"; let warnedForDeprecation = false; @@ -10,28 +10,28 @@ let warnedForDeprecation = false; */ /* tslint:disable:export-name */ export class Formatter extends BaseFormatter { -/* tslint:enable:export-name */ + /* tslint:enable:export-name */ constructor() { if (!warnedForDeprecation) { - console.warn('The fix-no-var-keyword formatter is deprecated. Use --fix instead.'); + console.warn("The fix-no-var-keyword formatter is deprecated. Use --fix instead."); warnedForDeprecation = true; } - super('no-var-keyword', function (this: Formatter, failure: RuleFailure): void { + super("no-var-keyword", function(this: Formatter, failure: RuleFailure): void { const fileName: string = failure.getFileName(); const fileContents: string = this.readFile(fileName); const end: number = failure.getEndPosition().getPosition(); let leftSide: string = fileContents.substring(0, end); - leftSide = leftSide.replace(/var$/, 'let'); + leftSide = leftSide.replace(/var$/, "let"); const rightSide: string = fileContents.substring(end); const newContent: string = leftSide + rightSide; this.writeFile(fileName, newContent); /* tslint:disable:no-console */ - console.log('Automatically converting var to let. Please re-compile and re-lint: ' + fileName); + console.log("Automatically converting var to let. Please re-compile and re-lint: " + fileName); /* tslint:enable:no-console */ }); } -} \ No newline at end of file +} diff --git a/src/functionNameRule.ts b/src/functionNameRule.ts index 2d34066b3..104e81fef 100644 --- a/src/functionNameRule.ts +++ b/src/functionNameRule.ts @@ -1,24 +1,23 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import { isObject } from './utils/TypeGuard'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { isObject } from "./utils/TypeGuard"; -const METHOD_REGEX = 'method-regex'; -const PRIVATE_METHOD_REGEX = 'private-method-regex'; -const PROTECTED_METHOD_REGEX = 'protected-method-regex'; -const STATIC_METHOD_REGEX = 'static-method-regex'; -const FUNCTION_REGEX = 'function-regex'; +const METHOD_REGEX = "method-regex"; +const PRIVATE_METHOD_REGEX = "private-method-regex"; +const PROTECTED_METHOD_REGEX = "protected-method-regex"; +const STATIC_METHOD_REGEX = "static-method-regex"; +const FUNCTION_REGEX = "function-regex"; -const VALIDATE_PRIVATE_STATICS_AS_PRIVATE = 'validate-private-statics-as-private'; -const VALIDATE_PRIVATE_STATICS_AS_STATIC = 'validate-private-statics-as-static'; -const VALIDATE_PRIVATE_STATICS_AS_EITHER = 'validate-private-statics-as-either'; +const VALIDATE_PRIVATE_STATICS_AS_PRIVATE = "validate-private-statics-as-private"; +const VALIDATE_PRIVATE_STATICS_AS_STATIC = "validate-private-statics-as-static"; +const VALIDATE_PRIVATE_STATICS_AS_EITHER = "validate-private-statics-as-either"; const VALID_ARGS = [VALIDATE_PRIVATE_STATICS_AS_PRIVATE, VALIDATE_PRIVATE_STATICS_AS_STATIC, VALIDATE_PRIVATE_STATICS_AS_EITHER]; function parseOptions(ruleArguments: unknown[]): Options { - if (ruleArguments.length === 0) { return { validateStatics: VALIDATE_PRIVATE_STATICS_AS_PRIVATE @@ -41,11 +40,10 @@ interface Options { } export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'function-name', - type: 'maintainability', - description: 'Applies a naming convention to function names and method names', + ruleName: "function-name", + type: "maintainability", + description: "Applies a naming convention to function names and method names", optionsDescription: Lint.Utils.dedent` Function styles should be consistent throughout the code. Users may want functions with multiple descriptors to be validated a certain way. @@ -55,10 +53,10 @@ export class Rule extends Lint.Rules.AbstractRule { * \`${VALIDATE_PRIVATE_STATICS_AS_EITHER}\` enforces validation as either. `, options: { - type: 'array', + type: "array", items: [ { - type: 'string', + type: "string", enum: [VALIDATE_PRIVATE_STATICS_AS_PRIVATE, VALIDATE_PRIVATE_STATICS_AS_STATIC, VALIDATE_PRIVATE_STATICS_AS_EITHER] } ], @@ -72,12 +70,12 @@ export class Rule extends Lint.Rules.AbstractRule { [true] ], typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -86,7 +84,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class FunctionNameRuleWalker extends Lint.RuleWalker { - private methodRegex: RegExp = /^[a-z][\w\d]+$/; private privateMethodRegex: RegExp = this.methodRegex; private protectedMethodRegex: RegExp = this.privateMethodRegex; @@ -113,28 +110,31 @@ class FunctionNameRuleWalker extends Lint.RuleWalker { if (AstUtils.hasComputedName(node)) { // allow computed names } else if (AstUtils.isPrivate(node)) { - if ( - !this.privateMethodRegex.test(name) - && this.args.validateStatics === VALIDATE_PRIVATE_STATICS_AS_PRIVATE) { - this.addFailureAt(node.name.getStart(), node.name.getWidth(), - `Private method name does not match ${this.privateMethodRegex}: ${name}`); + if (!this.privateMethodRegex.test(name) && this.args.validateStatics === VALIDATE_PRIVATE_STATICS_AS_PRIVATE) { + this.addFailureAt( + node.name.getStart(), + node.name.getWidth(), + `Private method name does not match ${this.privateMethodRegex}: ${name}` + ); } } else if (AstUtils.isProtected(node)) { - if ( - !this.protectedMethodRegex.test(name) - && this.args.validateStatics === VALIDATE_PRIVATE_STATICS_AS_PRIVATE - ) { - this.addFailureAt(node.name.getStart(), node.name.getWidth(), - `Protected method name does not match ${this.protectedMethodRegex}: ${name}`); + if (!this.protectedMethodRegex.test(name) && this.args.validateStatics === VALIDATE_PRIVATE_STATICS_AS_PRIVATE) { + this.addFailureAt( + node.name.getStart(), + node.name.getWidth(), + `Protected method name does not match ${this.protectedMethodRegex}: ${name}` + ); } } else if (AstUtils.isStatic(node)) { if (!this.staticMethodRegex.test(name)) { - this.addFailureAt(node.name.getStart(), node.name.getWidth(), - `Static method name does not match ${this.staticMethodRegex}: ${name}`); + this.addFailureAt( + node.name.getStart(), + node.name.getWidth(), + `Static method name does not match ${this.staticMethodRegex}: ${name}` + ); } } else if (!this.methodRegex.test(name)) { - this.addFailureAt(node.name.getStart(), node.name.getWidth(), - `Method name does not match ${this.methodRegex}: ${name}`); + this.addFailureAt(node.name.getStart(), node.name.getWidth(), `Method name does not match ${this.methodRegex}: ${name}`); } super.visitMethodDeclaration(node); } @@ -143,22 +143,25 @@ class FunctionNameRuleWalker extends Lint.RuleWalker { if (node.name !== undefined) { const name: string = node.name.text; if (!this.functionRegex.test(name)) { - this.addFailureAt(node.name.getStart(), node.name.getWidth(), - `Function name does not match ${this.functionRegex}: ${name}`); + this.addFailureAt( + node.name.getStart(), + node.name.getWidth(), + `Function name does not match ${this.functionRegex}: ${name}` + ); } } super.visitFunctionDeclaration(node); } - private getOptionOrDefault(option: {[key: string]: unknown}, key: string, defaultValue: RegExp): RegExp { + private getOptionOrDefault(option: { [key: string]: unknown }, key: string, defaultValue: RegExp): RegExp { try { const value = option[key]; - if (value !== undefined && (typeof value === 'string' || value instanceof RegExp)) { + if (value !== undefined && (typeof value === "string" || value instanceof RegExp)) { return new RegExp(value); } } catch (e) { /* tslint:disable:no-console */ - console.error('Could not read ' + key + ' within function-name configuration'); + console.error("Could not read " + key + " within function-name configuration"); /* tslint:enable:no-console */ } return defaultValue; diff --git a/src/importNameRule.ts b/src/importNameRule.ts index 54c1db092..bef90ced7 100644 --- a/src/importNameRule.ts +++ b/src/importNameRule.ts @@ -1,32 +1,31 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import { isObject } from './utils/TypeGuard'; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { isObject } from "./utils/TypeGuard"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'import-name', - type: 'maintainability', - description: 'The name of the imported module must match the name of the thing being imported', + ruleName: "import-name", + type: "maintainability", + description: "The name of the imported module must match the name of the thing being imported", hasFix: true, options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", optionExamples: [ [true], - [true, { moduleName: 'importedName' }], - [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2']], - [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2'], { ignoreExternalModule: false }] + [true, { moduleName: "importedName" }], + [true, { moduleName: "importedName" }, ["moduleName1", "moduleName2"]], + [true, { moduleName: "importedName" }, ["moduleName1", "moduleName2"], { ignoreExternalModule: false }] ], typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -34,10 +33,10 @@ export class Rule extends Lint.Rules.AbstractRule { } } -type Replacement = { [index: string]: string; }; +type Replacement = { [index: string]: string }; type IgnoredList = string[]; -type ConfigKey = 'ignoreExternalModule'; -type Config = { [index in ConfigKey]: unknown; }; +type ConfigKey = "ignoreExternalModule"; +type Config = { [index in ConfigKey]: unknown }; // This is for temporarily reolving type errors. Actual runtime Node, SourceFile object // has those properties. @@ -49,13 +48,12 @@ interface RuntimeNode extends ts.Node { } type Option = { - replacements: Replacement - ignoredList: IgnoredList - config: Config + replacements: Replacement; + ignoredList: IgnoredList; + config: Config; }; class ImportNameRuleWalker extends Lint.RuleWalker { - private readonly option: Option; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { @@ -64,7 +62,7 @@ class ImportNameRuleWalker extends Lint.RuleWalker { } private extractOptions(): Option { - const result : Option = { + const result: Option = { replacements: {}, ignoredList: [], config: { @@ -92,31 +90,36 @@ class ImportNameRuleWalker extends Lint.RuleWalker { private extractReplacements(opt: Replacement | unknown): Replacement { const result: Replacement = {}; if (isObject(opt)) { - Object.keys(opt).forEach((key: string): void => { - const value: unknown = opt[key]; - if (typeof value === 'string') { - result[key] = value; + Object.keys(opt).forEach( + (key: string): void => { + const value: unknown = opt[key]; + if (typeof value === "string") { + result[key] = value; + } } - }); + ); } return result; } private extractIgnoredList(opt: IgnoredList): IgnoredList { - return opt.filter((moduleName: string) => typeof moduleName === 'string'); + return opt.filter((moduleName: string) => typeof moduleName === "string"); } private extractConfig(opt: unknown): Config { const result: Config = { ignoreExternalModule: true }; - const configKeyLlist: ConfigKey[] = ['ignoreExternalModule']; + const configKeyLlist: ConfigKey[] = ["ignoreExternalModule"]; if (isObject(opt)) { - return Object.keys(opt).reduce((accum: Config, key: string) => { - if (configKeyLlist.filter((configKey: string) => configKey === key).length >= 1) { - accum[key] = opt[key]; + return Object.keys(opt).reduce( + (accum: Config, key: string) => { + if (configKeyLlist.filter((configKey: string) => configKey === key).length >= 1) { + accum[key] = opt[key]; + return accum; + } return accum; - } - return accum; - }, { ignoreExternalModule: true }); + }, + { ignoreExternalModule: true } + ); } return result; } @@ -132,7 +135,7 @@ class ImportNameRuleWalker extends Lint.RuleWalker { } } else if (node.moduleReference.kind === ts.SyntaxKind.QualifiedName) { let moduleName = node.moduleReference.getText(); - moduleName = moduleName.replace(/.*\./, ''); // chop off the qualified parts + moduleName = moduleName.replace(/.*\./, ""); // chop off the qualified parts this.validateImport(node, name, moduleName); } super.visitImportEqualsDeclaration(node); @@ -150,16 +153,17 @@ class ImportNameRuleWalker extends Lint.RuleWalker { } private validateImport(node: ts.ImportEqualsDeclaration | ts.ImportDeclaration, importedName: string, moduleName: string): void { - let expectedImportedName = moduleName.replace(/.*\//, ''); // chop off the path - if (expectedImportedName === '' || expectedImportedName === '.' || expectedImportedName === '..') { + let expectedImportedName = moduleName.replace(/.*\//, ""); // chop off the path + if (expectedImportedName === "" || expectedImportedName === "." || expectedImportedName === "..") { return; } expectedImportedName = this.makeCamelCase(expectedImportedName); if (this.isImportNameValid(importedName, expectedImportedName, moduleName, node) === false) { const message: string = `Misnamed import. Import should be named '${expectedImportedName}' but found '${importedName}'`; - const nameNode = node.kind === ts.SyntaxKind.ImportEqualsDeclaration - ? (node).name - : (node).importClause!.name; + const nameNode = + node.kind === ts.SyntaxKind.ImportEqualsDeclaration + ? (node).name + : (node).importClause!.name; const nameNodeStartPos = nameNode!.getStart(); const fix = new Lint.Replacement(nameNodeStartPos, nameNode!.end - nameNodeStartPos, expectedImportedName); this.addFailureAt(node.getStart(), node.getWidth(), message, fix); @@ -168,13 +172,20 @@ class ImportNameRuleWalker extends Lint.RuleWalker { private makeCamelCase(input: string): string { // tslint:disable-next-line:variable-name - return input.replace(/[-|\.|_](.)/g, (_match: string, group1: string): string => { - return group1.toUpperCase(); - }); + return input.replace( + /[-|\.|_](.)/g, + (_match: string, group1: string): string => { + return group1.toUpperCase(); + } + ); } - private isImportNameValid(importedName: string, expectedImportedName: string, moduleName: string, - node: ts.ImportEqualsDeclaration | ts.ImportDeclaration): boolean { + private isImportNameValid( + importedName: string, + expectedImportedName: string, + moduleName: string, + node: ts.ImportEqualsDeclaration | ts.ImportDeclaration + ): boolean { if (expectedImportedName === importedName) { return true; } @@ -197,22 +208,29 @@ class ImportNameRuleWalker extends Lint.RuleWalker { return false; } - private checkReplacementsExist(importedName: string, expectedImportedName: string, moduleName: string, replacements: Replacement) - : boolean { + private checkReplacementsExist( + importedName: string, + expectedImportedName: string, + moduleName: string, + replacements: Replacement + ): boolean { // Allowed Replacement keys are specifiers that are allowed when overriding or adding exceptions // to import-name rule. // Example: for below import statement // `import cgi from 'fs-util/cgi-common'` // The Valid specifiers are: [cgiCommon, fs-util/cgi-common, cgi-common] - const allowedReplacementKeys: string[] = [expectedImportedName, moduleName, moduleName.replace(/.*\//, '')]; - return Utils.exists(Object.keys(replacements), (replacementKey: string): boolean => { - for (let index = 0; allowedReplacementKeys.length > index; index = index + 1) { - if (replacementKey === allowedReplacementKeys[index]) { - return importedName === replacements[replacementKey]; + const allowedReplacementKeys: string[] = [expectedImportedName, moduleName, moduleName.replace(/.*\//, "")]; + return Utils.exists( + Object.keys(replacements), + (replacementKey: string): boolean => { + for (let index = 0; allowedReplacementKeys.length > index; index = index + 1) { + if (replacementKey === allowedReplacementKeys[index]) { + return importedName === replacements[replacementKey]; + } } + return false; } - return false; - }); + ); } // Ignore array of strings that comes from third argument. diff --git a/src/informativeDocsRule.ts b/src/informativeDocsRule.ts index dc2a2950c..e266462b0 100644 --- a/src/informativeDocsRule.ts +++ b/src/informativeDocsRule.ts @@ -1,16 +1,16 @@ -import * as Lint from 'tslint'; -import * as ts from 'typescript'; +import * as Lint from "tslint"; +import * as ts from "typescript"; -import { getApparentJsDoc, getNodeName } from './utils/NodeDocs'; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; +import { getApparentJsDoc, getNodeName } from "./utils/NodeDocs"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const defaultUselessWords = ['a', 'an', 'of', 'our', 'the']; +const defaultUselessWords = ["a", "an", "of", "our", "the"]; const defaultAliases: { [i: string]: string[] } = { - a: ['an', 'our'] + a: ["an", "our"] }; -const failureString = 'This comment is roughly the same as the object\'s name. Either be more informative or don\'t include a comment.'; +const failureString = "This comment is roughly the same as the object's name. Either be more informative or don't include a comment."; interface RawOptions { aliases?: { [i: string]: string[] }; @@ -27,18 +27,21 @@ interface Options { */ export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - description: 'Enforces that comments do more than just reiterate names of objects.', + description: "Enforces that comments do more than just reiterate names of objects.", options: undefined, - optionsDescription: 'Not configurable.', + optionsDescription: "Not configurable.", optionExamples: [ true, - [true, { - aliases: { - a: ['an', 'our'], - emoji: ['smiley'] - }, - uselessWords: [...defaultUselessWords, 'also'] - }] + [ + true, + { + aliases: { + a: ["an", "our"], + emoji: ["smiley"] + }, + uselessWords: [...defaultUselessWords, "also"] + } + ] ], rationale: Lint.Utils.dedent` The documentation for an object should not be equivalent to just the object's name. @@ -49,14 +52,14 @@ export class Rule extends Lint.Rules.AbstractRule { Alternately, if something's name is so descriptive that it doesn't need to be fully documented, just leave out documentation altogether. `, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Clarity', - recommendation: 'true,', - ruleName: 'informative-docs', - type: 'maintainability', + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Clarity", + recommendation: "true,", + ruleName: "informative-docs", + type: "maintainability", typescriptOnly: false }; @@ -66,16 +69,10 @@ export class Rule extends Lint.Rules.AbstractRule { } function parseOptions(ruleArguments: unknown[]): Options { - const rawOptions: RawOptions = ruleArguments.length === 0 - ? {} - : ruleArguments[0]; + const rawOptions: RawOptions = ruleArguments.length === 0 ? {} : ruleArguments[0]; return { - aliases: parseAliasesOption( - rawOptions.aliases === undefined - ? defaultAliases - : rawOptions.aliases - ), + aliases: parseAliasesOption(rawOptions.aliases === undefined ? defaultAliases : rawOptions.aliases), uselessWords: new Set(rawOptions.uselessWords === undefined ? defaultUselessWords : rawOptions.uselessWords) }; } @@ -102,9 +99,11 @@ function walk(context: Lint.WalkContext) { realDocWords.delete(nameWord); } - uselessWords.forEach((uselessWord: string): void => { - realDocWords.delete(uselessWord); - }); + uselessWords.forEach( + (uselessWord: string): void => { + realDocWords.delete(uselessWord); + } + ); return realDocWords.size !== 0; } @@ -121,22 +120,20 @@ function walk(context: Lint.WalkContext) { } function splitNameIntoWords(name: string): string[] | undefined { - if (name.length > 2 && name[0] === 'I' && Lint.Utils.isUpperCase(name[1])) { + if (name.length > 2 && name[0] === "I" && Lint.Utils.isUpperCase(name[1])) { name = name.substring(1); } const nameSpaced = name - .replace(/\W/g, '') - .replace(/([a-z])([A-Z])/g, '$1 $2') + .replace(/\W/g, "") + .replace(/([a-z])([A-Z])/g, "$1 $2") .trim(); if (nameSpaced.length === 0) { return undefined; } - return nameSpaced - .split(' ') - .map(normalizeWord); + return nameSpaced.split(" ").map(normalizeWord); } function getNodeDocComments(node: ts.Node): string[] | undefined { @@ -145,18 +142,16 @@ function walk(context: Lint.WalkContext) { return undefined; } - const docs = docsRaw - .map((doc) => doc.comment) - .filter((comment) => comment !== undefined); + const docs = docsRaw.map(doc => doc.comment).filter(comment => comment !== undefined); if (docs.length === 0) { return undefined; } return docs - .join(' ') - .replace(/[^A-Za-z0-9 ]/g, '') - .split(' ') + .join(" ") + .replace(/[^A-Za-z0-9 ]/g, "") + .split(" ") .map(normalizeWord); } diff --git a/src/insecureRandomRule.ts b/src/insecureRandomRule.ts index f8f2c3e0c..f2c8c968b 100644 --- a/src/insecureRandomRule.ts +++ b/src/insecureRandomRule.ts @@ -1,29 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const MATH_FAIL_STRING: string = 'Math.random produces insecure random numbers. ' + - 'Use crypto.randomBytes() or window.crypto.getRandomValues() instead'; +const MATH_FAIL_STRING: string = + "Math.random produces insecure random numbers. " + "Use crypto.randomBytes() or window.crypto.getRandomValues() instead"; -const NODE_FAIL_STRING: string = 'crypto.pseudoRandomBytes produces insecure random numbers. ' + - 'Use crypto.randomBytes() instead'; +const NODE_FAIL_STRING: string = "crypto.pseudoRandomBytes produces insecure random numbers. " + "Use crypto.randomBytes() instead"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'insecure-random', - type: 'functionality', - description: 'Do not use insecure sources for random bytes', + ruleName: "insecure-random", + type: "functionality", + description: "Do not use insecure sources for random bytes", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Security', - commonWeaknessEnumeration: '330' + issueClass: "SDL", + issueType: "Error", + severity: "Important", + level: "Opportunity for Excellence", + group: "Security", + commonWeaknessEnumeration: "330" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -32,11 +30,10 @@ export class Rule extends Lint.Rules.AbstractRule { } class InsecureRandomRuleWalker extends Lint.RuleWalker { - protected visitPropertyAccessExpression(node: ts.PropertyAccessExpression): void { - if (node.expression.getText() === 'Math' && node.name.text === 'random') { + if (node.expression.getText() === "Math" && node.name.text === "random") { this.addFailureAt(node.getStart(), node.getWidth(), MATH_FAIL_STRING); - } else if (node.name.text === 'pseudoRandomBytes') { + } else if (node.name.text === "pseudoRandomBytes") { this.addFailureAt(node.getStart(), node.getWidth(), NODE_FAIL_STRING); } super.visitPropertyAccessExpression(node); diff --git a/src/jqueryDeferredMustCompleteRule.ts b/src/jqueryDeferredMustCompleteRule.ts index 68a8df325..26e753f55 100644 --- a/src/jqueryDeferredMustCompleteRule.ts +++ b/src/jqueryDeferredMustCompleteRule.ts @@ -1,58 +1,57 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'jquery-deferred-must-complete', - type: 'maintainability', - description: 'When a JQuery Deferred instance is created, then either reject() or resolve() must be called ' + - 'on it within all code branches in the scope.', + ruleName: "jquery-deferred-must-complete", + type: "maintainability", + description: + "When a JQuery Deferred instance is created, then either reject() or resolve() must be called " + + "on it within all code branches in the scope.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness" }; - public static FAILURE_STRING: string = 'A JQuery deferred was found that appears to not have resolve ' + - 'or reject invoked on all code paths: '; + public static FAILURE_STRING: string = + "A JQuery deferred was found that appears to not have resolve " + "or reject invoked on all code paths: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new JQueryDeferredAnalyzer(sourceFile, this.getOptions())); } - } -function isPromiseInstantiation(expression: ts.Expression) : boolean { +function isPromiseInstantiation(expression: ts.Expression): boolean { if (expression !== undefined && expression.kind === ts.SyntaxKind.CallExpression) { const functionName = AstUtils.getFunctionName(expression); const functionTarget = AstUtils.getFunctionTarget(expression); - if (functionName === 'Deferred' && functionTarget !== undefined && AstUtils.isJQuery(functionTarget)) { + if (functionName === "Deferred" && functionTarget !== undefined && AstUtils.isJQuery(functionTarget)) { return true; } } return false; } -function isCompletionFunction(functionName : string) : boolean { +function isCompletionFunction(functionName: string): boolean { return /^(resolve|reject)$/.test(functionName); } class JQueryDeferredAnalyzer extends Lint.RuleWalker { protected visitBinaryExpression(node: ts.BinaryExpression): void { - if (node.operatorToken.getText() === '=' && isPromiseInstantiation(node.right)) { + if (node.operatorToken.getText() === "=" && isPromiseInstantiation(node.right)) { if (node.left.kind === ts.SyntaxKind.Identifier) { if ((node.left).text !== undefined) { - const name : ts.Identifier = node.left; + const name: ts.Identifier = node.left; this.validateDeferredUsage(node, name); } } @@ -63,33 +62,32 @@ class JQueryDeferredAnalyzer extends Lint.RuleWalker { protected visitVariableDeclaration(node: ts.VariableDeclaration): void { if (node.initializer !== undefined && isPromiseInstantiation(node.initializer)) { if ((node.name).text !== undefined) { - const name : ts.Identifier = node.name; + const name: ts.Identifier = node.name; this.validateDeferredUsage(node, name); } } super.visitVariableDeclaration(node); } - private validateDeferredUsage(rootNode: ts.Node, deferredIdentifier: ts.Identifier) : void { - const parent : ts.Node = AstUtils.findParentBlock(rootNode); + private validateDeferredUsage(rootNode: ts.Node, deferredIdentifier: ts.Identifier): void { + const parent: ts.Node = AstUtils.findParentBlock(rootNode); const blockAnalyzer = new DeferredCompletionWalker(this.getSourceFile(), this.getOptions(), deferredIdentifier); blockAnalyzer.visitNode(parent); if (!blockAnalyzer.isAlwaysCompleted()) { - const failureString = Rule.FAILURE_STRING + '\'' + rootNode.getText() + '\''; + const failureString = Rule.FAILURE_STRING + "'" + rootNode.getText() + "'"; this.addFailureAt(rootNode.getStart(), rootNode.getWidth(), failureString); } } - } class DeferredCompletionWalker extends Lint.RuleWalker { - private readonly deferredIdentifier : ts.Identifier; - private wasCompleted : boolean = false; - private allBranchesCompleted : boolean = true; // by default, there are no branches, so this is true - private hasBranches : boolean = false; + private readonly deferredIdentifier: ts.Identifier; + private wasCompleted: boolean = false; + private allBranchesCompleted: boolean = true; // by default, there are no branches, so this is true + private hasBranches: boolean = false; private readonly walkerOptions: Lint.IOptions; - constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, deferredIdentifier : ts.Identifier) { + constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, deferredIdentifier: ts.Identifier) { super(sourceFile, options); this.walkerOptions = options; // we need to store this because this.getOptions() returns undefined even when this has a value this.deferredIdentifier = deferredIdentifier; @@ -102,7 +100,7 @@ class DeferredCompletionWalker extends Lint.RuleWalker { } /* tslint:enable:no-unnecessary-override */ - public isAlwaysCompleted() : boolean { + public isAlwaysCompleted(): boolean { if (this.wasCompleted) { return true; // if the main code path completed then it doesn't matter what the child branches did } @@ -134,10 +132,10 @@ class DeferredCompletionWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) { - const prop : ts.PropertyAccessExpression = node.expression; + const prop: ts.PropertyAccessExpression = node.expression; if (AstUtils.isSameIdentifer(this.deferredIdentifier, prop.expression)) { - const functionName : string = prop.name.getText(); // possibly resolve or reject + const functionName: string = prop.name.getText(); // possibly resolve or reject if (isCompletionFunction(functionName)) { this.wasCompleted = true; return; // this branch was completed, do not walk any more. @@ -145,9 +143,12 @@ class DeferredCompletionWalker extends Lint.RuleWalker { } } - const referenceEscaped : boolean = Utils.exists(node.arguments, (argument: ts.Expression) : boolean => { - return AstUtils.isSameIdentifer(this.deferredIdentifier, argument); - }); + const referenceEscaped: boolean = Utils.exists( + node.arguments, + (argument: ts.Expression): boolean => { + return AstUtils.isSameIdentifer(this.deferredIdentifier, argument); + } + ); if (referenceEscaped) { this.wasCompleted = true; return; // this branch was completed, do not walk any more. @@ -156,9 +157,12 @@ class DeferredCompletionWalker extends Lint.RuleWalker { } protected visitArrowFunction(node: ts.ArrowFunction): void { - const isDeferredShadowed : boolean = Utils.exists(node.parameters, (param : ts.ParameterDeclaration) : boolean => { - return AstUtils.isSameIdentifer(this.deferredIdentifier, param.name); - }); + const isDeferredShadowed: boolean = Utils.exists( + node.parameters, + (param: ts.ParameterDeclaration): boolean => { + return AstUtils.isSameIdentifer(this.deferredIdentifier, param.name); + } + ); if (isDeferredShadowed) { this.hasBranches = true; this.allBranchesCompleted = false; @@ -168,9 +172,12 @@ class DeferredCompletionWalker extends Lint.RuleWalker { } protected visitFunctionExpression(node: ts.FunctionExpression): void { - const isDeferredShadowed : boolean = Utils.exists(node.parameters, (param : ts.ParameterDeclaration) : boolean => { - return AstUtils.isSameIdentifer(this.deferredIdentifier, param.name); - }); + const isDeferredShadowed: boolean = Utils.exists( + node.parameters, + (param: ts.ParameterDeclaration): boolean => { + return AstUtils.isSameIdentifer(this.deferredIdentifier, param.name); + } + ); if (isDeferredShadowed) { this.hasBranches = true; this.allBranchesCompleted = false; diff --git a/src/maxFuncBodyLengthRule.ts b/src/maxFuncBodyLengthRule.ts index a1aac4e24..495af4a22 100644 --- a/src/maxFuncBodyLengthRule.ts +++ b/src/maxFuncBodyLengthRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; -import {AstUtils} from './utils/AstUtils'; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {forEachTokenWithTrivia} from 'tsutils'; -import { isObject } from './utils/TypeGuard'; +import * as ts from "typescript"; +import * as Lint from "tslint"; +import { AstUtils } from "./utils/AstUtils"; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { forEachTokenWithTrivia } from "tsutils"; +import { isObject } from "./utils/TypeGuard"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'max-func-body-length', - type: 'maintainability', - description: 'Avoid long functions.', + ruleName: "max-func-body-length", + type: "maintainability", + description: "Avoid long functions.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Clarity', + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Clarity", recommendation: '[true, 100, {"ignore-parameters-to-function-regex": "^describe$"}],', - commonWeaknessEnumeration: '398, 710' + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -29,13 +28,13 @@ export class Rule extends Lint.Rules.AbstractRule { } } -const FUNC_BODY_LENGTH = 'func-body-length'; -const FUNC_EXPRESSION_BODY_LENGTH = 'func-express-body-length'; -const ARROW_BODY_LENGTH = 'arrow-body-length'; -const METHOD_BODY_LENGTH = 'method-body-length'; -const CTOR_BODY_LENGTH = 'ctor-body-length'; -const IGNORE_PARAMETERS_TO_FUNCTION = 'ignore-parameters-to-function-regex'; -const IGNORE_COMMENTS = 'ignore-comments'; +const FUNC_BODY_LENGTH = "func-body-length"; +const FUNC_EXPRESSION_BODY_LENGTH = "func-express-body-length"; +const ARROW_BODY_LENGTH = "arrow-body-length"; +const METHOD_BODY_LENGTH = "method-body-length"; +const CTOR_BODY_LENGTH = "ctor-body-length"; +const IGNORE_PARAMETERS_TO_FUNCTION = "ignore-parameters-to-function-regex"; +const IGNORE_COMMENTS = "ignore-comments"; class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { private maxBodyLength!: number; @@ -58,9 +57,11 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { const functionName = AstUtils.getFunctionName(node); if (this.ignoreParametersToFunctionRegex && this.ignoreParametersToFunctionRegex.test(functionName)) { // temporarily store a list of ignored references - node.arguments.forEach((argument: ts.Expression): void => { - this.ignoreNodes.push(argument); - }); + node.arguments.forEach( + (argument: ts.Expression): void => { + this.ignoreNodes.push(argument); + } + ); super.visitCallExpression(node); // clear the list of ignored references this.ignoreNodes = Utils.removeAll(this.ignoreNodes, node.arguments); @@ -95,7 +96,7 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { } protected visitClassDeclaration(node: ts.ClassDeclaration): void { - this.currentClassName = (node.name && node.name.text) || 'default'; + this.currentClassName = (node.name && node.name.text) || "default"; super.visitClassDeclaration(node); this.currentClassName = undefined; } @@ -125,12 +126,12 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { private calcBodyCommentLength(node: ts.FunctionLikeDeclaration) { let commentLineCount = 0; - commentLineCount += node.getFullText() + commentLineCount += node + .getFullText() .split(/\n/) - .filter((line) => { + .filter(line => { return line.trim().match(/^\/\//) !== null; - }) - .length; + }).length; forEachTokenWithTrivia(node, (text, tokenSyntaxKind) => { if (tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia) { @@ -141,13 +142,13 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { return commentLineCount; } - private isFunctionTooLong (nodeKind: ts.SyntaxKind, length: number): boolean { + private isFunctionTooLong(nodeKind: ts.SyntaxKind, length: number): boolean { return length > this.getMaxLength(nodeKind); } - private parseOptions () { + private parseOptions() { this.getOptions().forEach((opt: unknown) => { - if (typeof(opt) === 'number') { + if (typeof opt === "number") { this.maxBodyLength = opt; return; } @@ -171,42 +172,40 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { this.addFailureAt(node.getStart(), node.getWidth(), this.formatFailureText(node, length)); } - private formatFailureText (node: ts.FunctionLikeDeclaration, length: number) { + private formatFailureText(node: ts.FunctionLikeDeclaration, length: number) { const funcTypeText: string = this.getFuncTypeText(node.kind); const maxLength: number = this.getMaxLength(node.kind); const placeText: string = this.formatPlaceText(node); - return `Max ${ funcTypeText } body length exceeded${ placeText } - max: ${ maxLength }, actual: ${ length }`; + return `Max ${funcTypeText} body length exceeded${placeText} - max: ${maxLength}, actual: ${length}`; } - private formatPlaceText (node: ts.FunctionLikeDeclaration) { + private formatPlaceText(node: ts.FunctionLikeDeclaration) { const funcTypeText = this.getFuncTypeText(node.kind); - if (ts.isMethodDeclaration(node) || - ts.isFunctionDeclaration(node) || - ts.isFunctionExpression(node)) { - return ` in ${ funcTypeText } ${ node.name ? node.name.getText() : '' }()`; + if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) { + return ` in ${funcTypeText} ${node.name ? node.name.getText() : ""}()`; } else if (node.kind === ts.SyntaxKind.Constructor) { - return ` in class ${ this.currentClassName }`; + return ` in class ${this.currentClassName}`; } - return ''; + return ""; } - private getFuncTypeText (nodeKind: ts.SyntaxKind) { + private getFuncTypeText(nodeKind: ts.SyntaxKind) { if (nodeKind === ts.SyntaxKind.FunctionDeclaration) { - return 'function'; + return "function"; } else if (nodeKind === ts.SyntaxKind.FunctionExpression) { - return 'function expression'; + return "function expression"; } else if (nodeKind === ts.SyntaxKind.MethodDeclaration) { - return 'method'; + return "method"; } else if (nodeKind === ts.SyntaxKind.ArrowFunction) { - return 'arrow function'; + return "arrow function"; } else if (nodeKind === ts.SyntaxKind.Constructor) { - return 'constructor'; + return "constructor"; } else { - throw new Error(`Unsupported node kind: ${ nodeKind }`); + throw new Error(`Unsupported node kind: ${nodeKind}`); } } - private getMaxLength (nodeKind: ts.SyntaxKind) { + private getMaxLength(nodeKind: ts.SyntaxKind) { let result: number; if (nodeKind === ts.SyntaxKind.FunctionDeclaration) { @@ -220,7 +219,7 @@ class MaxFunctionBodyLengthRuleWalker extends Lint.RuleWalker { } else if (nodeKind === ts.SyntaxKind.Constructor) { result = this.maxCtorBodyLength; } else { - throw new Error(`Unsupported node kind: ${ nodeKind }`); + throw new Error(`Unsupported node kind: ${nodeKind}`); } return result || this.maxBodyLength; diff --git a/src/missingJsdocRule.ts b/src/missingJsdocRule.ts index 4b3f4c887..b0e76b2cc 100644 --- a/src/missingJsdocRule.ts +++ b/src/missingJsdocRule.ts @@ -1,33 +1,31 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'missing-jsdoc', - type: 'maintainability', - description: 'All files must have a top level JSDoc comment.', + ruleName: "missing-jsdoc", + type: "maintainability", + description: "All files must have a top level JSDoc comment.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false,' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false," }; - public static FAILURE_STRING: string = 'File missing JSDoc comment at the top-level: '; + public static FAILURE_STRING: string = "File missing JSDoc comment at the top-level: "; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn('Warning: missing-jsdoc rule is deprecated. ' + - 'Replace your usage with the TSLint missing-jsdoc rule.'); + console.warn("Warning: missing-jsdoc rule is deprecated. " + "Replace your usage with the TSLint missing-jsdoc rule."); Rule.isWarningShown = true; } return this.applyWithWalker(new MissingJSDocWalker(sourceFile, this.getOptions())); diff --git a/src/missingOptionalAnnotationRule.ts b/src/missingOptionalAnnotationRule.ts index e0f8efb20..e72d34be0 100644 --- a/src/missingOptionalAnnotationRule.ts +++ b/src/missingOptionalAnnotationRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'missing-optional-annotation', - type: 'maintainability', - description: 'Deprecated - This rule is now enforced by the TypeScript compiler', + ruleName: "missing-optional-annotation", + type: "maintainability", + description: "Deprecated - This rule is now enforced by the TypeScript compiler", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false, // now supported by TypeScript compiler' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false, // now supported by TypeScript compiler" }; - public static FAILURE_STRING: string = 'Argument following optional argument missing optional annotation: '; + public static FAILURE_STRING: string = "Argument following optional argument missing optional annotation: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new MissingOptionalAnnotationWalker(sourceFile, this.getOptions())); @@ -53,19 +52,21 @@ class MissingOptionalAnnotationWalker extends Lint.RuleWalker { super.visitFunctionExpression(node); } - private validateParameters(node : ts.SignatureDeclaration) { + private validateParameters(node: ts.SignatureDeclaration) { let optionalParameterFound = false; if (node.parameters === undefined) { return; } - node.parameters.forEach((parameter : ts.ParameterDeclaration) : void => { - if (parameter.questionToken !== undefined || parameter.initializer !== undefined) { - optionalParameterFound = true; - } else if (optionalParameterFound && parameter.initializer === undefined) { - // we found a non-optional parameter that comes *after* an optional parameter - const msg = Rule.FAILURE_STRING + parameter.getFullText(); - this.addFailureAt(parameter.name.getStart(), parameter.name.getWidth(), msg); + node.parameters.forEach( + (parameter: ts.ParameterDeclaration): void => { + if (parameter.questionToken !== undefined || parameter.initializer !== undefined) { + optionalParameterFound = true; + } else if (optionalParameterFound && parameter.initializer === undefined) { + // we found a non-optional parameter that comes *after* an optional parameter + const msg = Rule.FAILURE_STRING + parameter.getFullText(); + this.addFailureAt(parameter.name.getStart(), parameter.name.getWidth(), msg); + } } - }); + ); } } diff --git a/src/mochaAvoidOnlyRule.ts b/src/mochaAvoidOnlyRule.ts index 73aa3634a..8b2a9546b 100644 --- a/src/mochaAvoidOnlyRule.ts +++ b/src/mochaAvoidOnlyRule.ts @@ -1,38 +1,35 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {MochaUtils} from './utils/MochaUtils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { MochaUtils } from "./utils/MochaUtils"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'mocha-avoid-only', - type: 'maintainability', - description: 'Do not invoke Mocha\'s describe.only, it.only or context.only functions.', + ruleName: "mocha-avoid-only", + type: "maintainability", + description: "Do not invoke Mocha's describe.only, it.only or context.only functions.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness" }; - public static FAILURE_STRING_IT: string = 'Do not commit Mocha it.only function call'; - public static FAILURE_STRING_SPECIFY: string = 'Do not commit Mocha specify.only function call'; - public static FAILURE_STRING_DESCRIBE: string = 'Do not commit Mocha describe.only function call'; - public static FAILURE_STRING_CONTEXT: string = 'Do not commit Mocha context.only function call'; + public static FAILURE_STRING_IT: string = "Do not commit Mocha it.only function call"; + public static FAILURE_STRING_SPECIFY: string = "Do not commit Mocha specify.only function call"; + public static FAILURE_STRING_DESCRIBE: string = "Do not commit Mocha describe.only function call"; + public static FAILURE_STRING_CONTEXT: string = "Do not commit Mocha context.only function call"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new MochaAvoidOnlyRuleWalker(sourceFile, this.getOptions())); } - } class MochaAvoidOnlyRuleWalker extends Lint.RuleWalker { - protected visitSourceFile(node: ts.SourceFile): void { if (MochaUtils.isMochaTest(node)) { super.visitSourceFile(node); @@ -43,16 +40,18 @@ class MochaAvoidOnlyRuleWalker extends Lint.RuleWalker { if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) { if (node.arguments.length === 2) { if (node.arguments[0].kind === ts.SyntaxKind.StringLiteral) { - if (node.arguments[1].kind === ts.SyntaxKind.FunctionExpression - || node.arguments[1].kind === ts.SyntaxKind.ArrowFunction) { - if (node.expression.getText() === 'it.only') { - this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_IT); - } else if (node.expression.getText() === 'specify.only') { - this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_SPECIFY); - } else if (node.expression.getText() === 'describe.only') { - this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_DESCRIBE); - } else if (node.expression.getText() === 'context.only') { - this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_CONTEXT); + if ( + node.arguments[1].kind === ts.SyntaxKind.FunctionExpression || + node.arguments[1].kind === ts.SyntaxKind.ArrowFunction + ) { + if (node.expression.getText() === "it.only") { + this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_IT); + } else if (node.expression.getText() === "specify.only") { + this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_SPECIFY); + } else if (node.expression.getText() === "describe.only") { + this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_DESCRIBE); + } else if (node.expression.getText() === "context.only") { + this.addFailureAt(node.getStart(), node.expression.getText().length, Rule.FAILURE_STRING_CONTEXT); } } } diff --git a/src/mochaNoSideEffectCodeRule.ts b/src/mochaNoSideEffectCodeRule.ts index cdc7207d1..91b27f621 100644 --- a/src/mochaNoSideEffectCodeRule.ts +++ b/src/mochaNoSideEffectCodeRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {AstUtils} from './utils/AstUtils'; -import {MochaUtils} from './utils/MochaUtils'; -import {Utils} from './utils/Utils'; -import { isObject } from './utils/TypeGuard'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { AstUtils } from "./utils/AstUtils"; +import { MochaUtils } from "./utils/MochaUtils"; +import { Utils } from "./utils/Utils"; +import { isObject } from "./utils/TypeGuard"; -const FAILURE_STRING: string = 'Mocha test contains dangerous variable initialization. Move to before()/beforeEach(): '; +const FAILURE_STRING: string = "Mocha test contains dangerous variable initialization. Move to before()/beforeEach(): "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'mocha-no-side-effect-code', - type: 'maintainability', - description: 'All test logic in a Mocha test case should be within Mocha lifecycle method.', + ruleName: "mocha-no-side-effect-code", + type: "maintainability", + description: "All test logic in a Mocha test case should be within Mocha lifecycle method.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', // one of 'Mandatory' | 'Opportunity for Excellence' - group: 'Correctness' + issueClass: "Ignored", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", // one of 'Mandatory' | 'Opportunity for Excellence' + group: "Correctness" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -31,7 +30,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { - private isInDescribe: boolean = false; private ignoreRegex!: RegExp; @@ -43,7 +41,7 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { private parseOptions() { this.getOptions().forEach((opt: unknown) => { if (isObject(opt)) { - if (opt.ignore !== undefined && (typeof opt.ignore === 'string' || opt.ignore instanceof RegExp)) { + if (opt.ignore !== undefined && (typeof opt.ignore === "string" || opt.ignore instanceof RegExp)) { this.ignoreRegex = new RegExp(opt.ignore); } } @@ -52,24 +50,28 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { protected visitSourceFile(node: ts.SourceFile): void { if (MochaUtils.isMochaTest(node)) { - node.statements.forEach((statement: ts.Statement): void => { - // validate variable declarations in global scope - if (statement.kind === ts.SyntaxKind.VariableStatement) { - const declarationList: ts.VariableDeclarationList = (statement).declarationList; - declarationList.declarations.forEach((declaration: ts.VariableDeclaration): void => { - if (declaration.initializer !== undefined) { - this.validateExpression(declaration.initializer, declaration); - } - }); - } + node.statements.forEach( + (statement: ts.Statement): void => { + // validate variable declarations in global scope + if (statement.kind === ts.SyntaxKind.VariableStatement) { + const declarationList: ts.VariableDeclarationList = (statement).declarationList; + declarationList.declarations.forEach( + (declaration: ts.VariableDeclaration): void => { + if (declaration.initializer !== undefined) { + this.validateExpression(declaration.initializer, declaration); + } + } + ); + } - // walk into the describe calls - if (MochaUtils.isStatementDescribeCall(statement)) { - const expression: ts.Expression = (statement).expression; - const call: ts.CallExpression = expression; - this.visitCallExpression(call); + // walk into the describe calls + if (MochaUtils.isStatementDescribeCall(statement)) { + const expression: ts.Expression = (statement).expression; + const call: ts.CallExpression = expression; + this.visitCallExpression(call); + } } - }); + ); } } @@ -113,16 +115,17 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { return; } // function expressions are not executed now and will not throw an error - if (initializer.kind === ts.SyntaxKind.FunctionExpression - || initializer.kind === ts.SyntaxKind.ArrowFunction) { + if (initializer.kind === ts.SyntaxKind.FunctionExpression || initializer.kind === ts.SyntaxKind.ArrowFunction) { return; } // empty arrays and arrays filled with constants are allowed if (initializer.kind === ts.SyntaxKind.ArrayLiteralExpression) { const arrayLiteral: ts.ArrayLiteralExpression = initializer; - arrayLiteral.elements.forEach((expression: ts.Expression): void => { - this.validateExpression(expression, parentNode); - }); + arrayLiteral.elements.forEach( + (expression: ts.Expression): void => { + this.validateExpression(expression, parentNode); + } + ); return; } // template strings are OK (it is too hard to analyze a template string fully) @@ -147,12 +150,14 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { if (initializer.kind === ts.SyntaxKind.ObjectLiteralExpression) { const literal: ts.ObjectLiteralExpression = initializer; - literal.properties.forEach((element: ts.ObjectLiteralElement): void => { - if (element.kind === ts.SyntaxKind.PropertyAssignment) { - const assignment: ts.PropertyAssignment = element; - this.validateExpression(assignment.initializer, parentNode); + literal.properties.forEach( + (element: ts.ObjectLiteralElement): void => { + if (element.kind === ts.SyntaxKind.PropertyAssignment) { + const assignment: ts.PropertyAssignment = element; + this.validateExpression(assignment.initializer, parentNode); + } } - }); + ); return; } // From https://mochajs.org/, `this.retries(...)`, `this.slow(...)`, and @@ -161,16 +166,18 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { return; } // moment() is OK - if (initializer.getText() === 'moment()') { + if (initializer.getText() === "moment()") { return; } - if (initializer.kind === ts.SyntaxKind.CallExpression - && AstUtils.getFunctionTarget(initializer) === 'moment()') { + if ( + initializer.kind === ts.SyntaxKind.CallExpression && + AstUtils.getFunctionTarget(initializer) === "moment()" + ) { return; } // new Date is OK if (initializer.kind === ts.SyntaxKind.NewExpression) { - if (AstUtils.getFunctionName(initializer) === 'Date') { + if (AstUtils.getFunctionName(initializer) === "Date") { return; } } @@ -180,13 +187,15 @@ class MochaNoSideEffectCodeRuleWalker extends Lint.RuleWalker { if (callExp.expression.kind === ts.SyntaxKind.PropertyAccessExpression) { const propExp: ts.PropertyAccessExpression = callExp.expression; if (propExp.expression.kind === ts.SyntaxKind.ArrayLiteralExpression) { - if (propExp.name.getText() === 'forEach') { + if (propExp.name.getText() === "forEach") { // The forEach() call is OK, but check the contents of the array and the parameters // to the forEach call because they could contain code with side effects. this.validateExpression(propExp.expression, parentNode); - callExp.arguments.forEach((arg: ts.Expression): void => { - super.visitNode(arg); - }); + callExp.arguments.forEach( + (arg: ts.Expression): void => { + super.visitNode(arg); + } + ); return; } } diff --git a/src/mochaUnneededDoneRule.ts b/src/mochaUnneededDoneRule.ts index 266b97b69..7f7e9f395 100644 --- a/src/mochaUnneededDoneRule.ts +++ b/src/mochaUnneededDoneRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {Utils} from './utils/Utils'; -import {MochaUtils} from './utils/MochaUtils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { Utils } from "./utils/Utils"; +import { MochaUtils } from "./utils/MochaUtils"; -const FAILURE_STRING: string = 'Unneeded Mocha Done. Parameter can be safely removed: '; +const FAILURE_STRING: string = "Unneeded Mocha Done. Parameter can be safely removed: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'mocha-unneeded-done', - type: 'maintainability', - description: 'A function declares a MochaDone parameter but only resolves it synchronously in the main function.', + ruleName: "mocha-unneeded-done", + type: "maintainability", + description: "A function declares a MochaDone parameter but only resolves it synchronously in the main function.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -29,7 +28,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class MochaUnneededDoneRuleWalker extends Lint.RuleWalker { - protected visitSourceFile(node: ts.SourceFile): void { if (MochaUtils.isMochaTest(node)) { super.visitSourceFile(node); @@ -56,7 +54,9 @@ class MochaUnneededDoneRuleWalker extends Lint.RuleWalker { } const walker: IdentifierReferenceCountWalker = new IdentifierReferenceCountWalker( - this.getSourceFile(), this.getOptions(), doneIdentifier + this.getSourceFile(), + this.getOptions(), + doneIdentifier ); const count: number = walker.getReferenceCount(node.body); if (count === 1) { @@ -69,29 +69,34 @@ class MochaUnneededDoneRuleWalker extends Lint.RuleWalker { return false; } const block: ts.Block = node.body; - return Utils.exists(block.statements, (statement: ts.Statement): boolean => { - if (statement.kind === ts.SyntaxKind.ExpressionStatement) { - const expression: ts.Expression = (statement).expression; - if (expression.kind === ts.SyntaxKind.CallExpression) { - const leftHandSideExpression: ts.Expression = (expression).expression; - return leftHandSideExpression.getText() === doneIdentifier.getText(); + return Utils.exists( + block.statements, + (statement: ts.Statement): boolean => { + if (statement.kind === ts.SyntaxKind.ExpressionStatement) { + const expression: ts.Expression = (statement).expression; + if (expression.kind === ts.SyntaxKind.CallExpression) { + const leftHandSideExpression: ts.Expression = (expression).expression; + return leftHandSideExpression.getText() === doneIdentifier.getText(); + } } - } - return false; - }); + return false; + } + ); } private maybeGetMochaDoneParameter(node: ts.FunctionLikeDeclaration): ts.Identifier | undefined { if (node.parameters.length === 0) { return undefined; } - const allDones: ts.ParameterDeclaration[] = node.parameters.filter((parameter: ts.ParameterDeclaration): boolean => { - if (parameter.type !== undefined && parameter.type.getText() === 'MochaDone') { - return true; + const allDones: ts.ParameterDeclaration[] = node.parameters.filter( + (parameter: ts.ParameterDeclaration): boolean => { + if (parameter.type !== undefined && parameter.type.getText() === "MochaDone") { + return true; + } + return parameter.name.getText() === "done"; } - return parameter.name.getText() === 'done'; - }); + ); if (allDones.length === 0 || allDones[0].name.kind !== ts.SyntaxKind.Identifier) { return undefined; @@ -101,7 +106,6 @@ class MochaUnneededDoneRuleWalker extends Lint.RuleWalker { } class IdentifierReferenceCountWalker extends Lint.RuleWalker { - private readonly identifierText: string; private count!: number; @@ -112,9 +116,11 @@ class IdentifierReferenceCountWalker extends Lint.RuleWalker { public getReferenceCount(body: ts.Block): number { this.count = 0; - body.statements.forEach((statement: ts.Statement): void => { - this.walk(statement); - }); + body.statements.forEach( + (statement: ts.Statement): void => { + this.walk(statement); + } + ); return this.count; } diff --git a/src/noBackboneGetSetOutsideModelRule.ts b/src/noBackboneGetSetOutsideModelRule.ts index 82b7a3ad5..459484698 100644 --- a/src/noBackboneGetSetOutsideModelRule.ts +++ b/src/noBackboneGetSetOutsideModelRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-backbone-get-set-outside-model', - type: 'maintainability', - description: 'Avoid using `model.get(\'x\')` and `model.set(\'x\', value)` Backbone accessors outside of the owning model.', + ruleName: "no-backbone-get-set-outside-model", + type: "maintainability", + description: "Avoid using `model.get('x')` and `model.set('x', value)` Backbone accessors outside of the owning model.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; - public static GET_FAILURE_STRING: string = 'Backbone get() called outside of owning model: '; - public static SET_FAILURE_STRING: string = 'Backbone set() called outside of owning model: '; + public static GET_FAILURE_STRING: string = "Backbone get() called outside of owning model: "; + public static SET_FAILURE_STRING: string = "Backbone set() called outside of owning model: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoBackboneGetSetOutsideModelRuleWalker(sourceFile, this.getOptions())); @@ -31,13 +30,13 @@ export class Rule extends Lint.Rules.AbstractRule { class NoBackboneGetSetOutsideModelRuleWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { - if (AstUtils.getFunctionTarget(node) !== 'this') { + if (AstUtils.getFunctionTarget(node) !== "this") { const functionName: string = AstUtils.getFunctionName(node); - if (functionName === 'get' && node.arguments.length === 1 && node.arguments[0].kind === ts.SyntaxKind.StringLiteral) { + if (functionName === "get" && node.arguments.length === 1 && node.arguments[0].kind === ts.SyntaxKind.StringLiteral) { const msg: string = Rule.GET_FAILURE_STRING + node.getText(); this.addFailureAt(node.getStart(), node.getEnd(), msg); } - if (functionName === 'set' && node.arguments.length === 2 && node.arguments[0].kind === ts.SyntaxKind.StringLiteral) { + if (functionName === "set" && node.arguments.length === 2 && node.arguments[0].kind === ts.SyntaxKind.StringLiteral) { const msg: string = Rule.SET_FAILURE_STRING + node.getText(); this.addFailureAt(node.getStart(), node.getEnd(), msg); } diff --git a/src/noBannedTermsRule.ts b/src/noBannedTermsRule.ts index 08afd6028..3e4617016 100644 --- a/src/noBannedTermsRule.ts +++ b/src/noBannedTermsRule.ts @@ -1,36 +1,30 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {BannedTermWalker} from './utils/BannedTermWalker'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { BannedTermWalker } from "./utils/BannedTermWalker"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-banned-terms', - type: 'maintainability', - description: 'Do not use banned terms: caller, callee, eval, arguments.', + ruleName: "no-banned-terms", + type: "maintainability", + description: "Do not use banned terms: caller, callee, eval, arguments.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '676, 242, 116' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "676, 242, 116" }; - private static readonly FAILURE_STRING: string = 'Forbidden reference to banned term: '; - private static readonly BANNED_TERMS : string[] = [ 'caller', 'callee', 'arguments', 'eval' ]; + private static readonly FAILURE_STRING: string = "Forbidden reference to banned term: "; + private static readonly BANNED_TERMS: string[] = ["caller", "callee", "arguments", "eval"]; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { - const walker : Lint.RuleWalker = new BannedTermWalker( - sourceFile, - this.getOptions(), - Rule.FAILURE_STRING, - Rule.BANNED_TERMS - ); + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const walker: Lint.RuleWalker = new BannedTermWalker(sourceFile, this.getOptions(), Rule.FAILURE_STRING, Rule.BANNED_TERMS); return this.applyWithWalker(walker); } -} \ No newline at end of file +} diff --git a/src/noConstantConditionRule.ts b/src/noConstantConditionRule.ts index 09bd22e03..e5ca5863c 100644 --- a/src/noConstantConditionRule.ts +++ b/src/noConstantConditionRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import { isObject } from './utils/TypeGuard'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { isObject } from "./utils/TypeGuard"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-constant-condition', - type: 'maintainability', - description: 'Do not use constant expressions in conditions.', + ruleName: "no-constant-condition", + type: "maintainability", + description: "Do not use constant expressions in conditions.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 570, 571, 670' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 570, 571, 670" }; - public static FAILURE_STRING: string = 'Found constant conditional: '; + public static FAILURE_STRING: string = "Found constant conditional: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoConstantConditionRuleWalker(sourceFile, this.getOptions())); @@ -30,19 +29,18 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoConstantConditionRuleWalker extends Lint.RuleWalker { - private readonly checkLoops: boolean; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { super(sourceFile, options); - this.checkLoops = this.extractBoolean('checkLoops'); + this.checkLoops = this.extractBoolean("checkLoops"); } private extractBoolean(keyName: string): boolean { - let result : boolean = true; + let result: boolean = true; this.getOptions().forEach((opt: unknown) => { if (isObject(opt)) { - if (opt[keyName] === false || opt[keyName] === 'false') { + if (opt[keyName] === false || opt[keyName] === "false") { result = false; } } @@ -52,7 +50,7 @@ class NoConstantConditionRuleWalker extends Lint.RuleWalker { protected visitIfStatement(node: ts.IfStatement): void { if (AstUtils.isConstantExpression(node.expression)) { - const message: string = Rule.FAILURE_STRING + 'if (' + node.expression.getText() + ')'; + const message: string = Rule.FAILURE_STRING + "if (" + node.expression.getText() + ")"; this.addFailureAt(node.getStart(), node.getWidth(), message); } super.visitIfStatement(node); @@ -60,7 +58,7 @@ class NoConstantConditionRuleWalker extends Lint.RuleWalker { protected visitConditionalExpression(node: ts.ConditionalExpression): void { if (AstUtils.isConstantExpression(node.condition)) { - const message: string = Rule.FAILURE_STRING + node.condition.getText() + ' ?'; + const message: string = Rule.FAILURE_STRING + node.condition.getText() + " ?"; this.addFailureAt(node.getStart(), node.getWidth(), message); } super.visitConditionalExpression(node); @@ -69,7 +67,7 @@ class NoConstantConditionRuleWalker extends Lint.RuleWalker { protected visitWhileStatement(node: ts.WhileStatement): void { if (this.checkLoops) { if (AstUtils.isConstantExpression(node.expression)) { - const message: string = Rule.FAILURE_STRING + 'while (' + node.expression.getText() + ')'; + const message: string = Rule.FAILURE_STRING + "while (" + node.expression.getText() + ")"; this.addFailureAt(node.getStart(), node.getWidth(), message); } } @@ -79,7 +77,7 @@ class NoConstantConditionRuleWalker extends Lint.RuleWalker { protected visitDoStatement(node: ts.DoStatement): void { if (this.checkLoops) { if (AstUtils.isConstantExpression(node.expression)) { - const message: string = Rule.FAILURE_STRING + 'while (' + node.expression.getText() + ')'; + const message: string = Rule.FAILURE_STRING + "while (" + node.expression.getText() + ")"; this.addFailureAt(node.getStart(), node.getWidth(), message); } } @@ -89,7 +87,7 @@ class NoConstantConditionRuleWalker extends Lint.RuleWalker { protected visitForStatement(node: ts.ForStatement): void { if (this.checkLoops && node.condition !== undefined) { if (AstUtils.isConstantExpression(node.condition)) { - const message: string = Rule.FAILURE_STRING + ';' + node.condition.getText() + ';'; + const message: string = Rule.FAILURE_STRING + ";" + node.condition.getText() + ";"; this.addFailureAt(node.getStart(), node.getWidth(), message); } } diff --git a/src/noControlRegexRule.ts b/src/noControlRegexRule.ts index b402aa3cb..3d3544c62 100644 --- a/src/noControlRegexRule.ts +++ b/src/noControlRegexRule.ts @@ -1,30 +1,28 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-control-regex', - type: 'maintainability', - description: 'Do not use control characters in regular expressions', + ruleName: "no-control-regex", + type: "maintainability", + description: "Do not use control characters in regular expressions", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Correctness" }; - public static FAILURE_STRING: string = 'Unexpected control character in regular expression'; + public static FAILURE_STRING: string = "Unexpected control character in regular expression"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoControlRegexRuleWalker(sourceFile, this.getOptions())); } - } class NoControlRegexRuleWalker extends Lint.RuleWalker { @@ -47,7 +45,7 @@ class NoControlRegexRuleWalker extends Lint.RuleWalker { /* tslint:disable:no-control-regex */ private validateCall(expression: ts.CallExpression | ts.NewExpression): void { - if (expression.expression.getText() === 'RegExp' && expression.arguments !== undefined && expression.arguments.length > 0) { + if (expression.expression.getText() === "RegExp" && expression.arguments !== undefined && expression.arguments.length > 0) { const arg1: ts.Expression = expression.arguments[0]; if (arg1.kind === ts.SyntaxKind.StringLiteral) { const regexpText: string = (arg1).text; diff --git a/src/noCookiesRule.ts b/src/noCookiesRule.ts index a71c38692..68aee4e52 100644 --- a/src/noCookiesRule.ts +++ b/src/noCookiesRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.TypedRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-cookies', - type: 'maintainability', - description: 'Do not use cookies', + ruleName: "no-cookies", + type: "maintainability", + description: "Do not use cookies", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '315, 539, 565, 614' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "315, 539, 565, 614" }; - public static FAILURE_STRING: string = 'Forbidden call to document.cookie'; + public static FAILURE_STRING: string = "Forbidden call to document.cookie"; public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { return this.applyWithWalker(new NoCookiesWalker(sourceFile, this.getOptions(), program)); @@ -28,7 +27,7 @@ export class Rule extends Lint.Rules.TypedRule { } class NoCookiesWalker extends Lint.RuleWalker { - private readonly typeChecker : ts.TypeChecker; + private readonly typeChecker: ts.TypeChecker; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, program: ts.Program) { super(sourceFile, options); @@ -37,17 +36,17 @@ class NoCookiesWalker extends Lint.RuleWalker { protected visitPropertyAccessExpression(node: ts.PropertyAccessExpression): void { const propertyName = node.name.text; - if (propertyName === 'cookie') { - const leftSide : ts.Expression = node.expression; + if (propertyName === "cookie") { + const leftSide: ts.Expression = node.expression; try { const leftSideType: ts.Type = this.typeChecker.getTypeAtLocation(leftSide); const typeAsString: string = this.typeChecker.typeToString(leftSideType); - if (leftSideType.flags === ts.TypeFlags.Any || typeAsString === 'Document') { + if (leftSideType.flags === ts.TypeFlags.Any || typeAsString === "Document") { this.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING); } } catch (e) { // the error thrown seems like a tslint error - if (leftSide.getFullText().trim() === 'document') { + if (leftSide.getFullText().trim() === "document") { this.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING); } } @@ -55,5 +54,4 @@ class NoCookiesWalker extends Lint.RuleWalker { super.visitPropertyAccessExpression(node); } - } diff --git a/src/noDeleteExpressionRule.ts b/src/noDeleteExpressionRule.ts index dde38b84b..b66b3afe1 100644 --- a/src/noDeleteExpressionRule.ts +++ b/src/noDeleteExpressionRule.ts @@ -1,25 +1,24 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-delete-expression', - type: 'maintainability', - description: 'Do not delete expressions. Only properties should be deleted', + ruleName: "no-delete-expression", + type: "maintainability", + description: "Do not delete expressions. Only properties should be deleted", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security" }; - public static FAILURE_STRING: string = 'Variables should not be deleted: '; + public static FAILURE_STRING: string = "Variables should not be deleted: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const noDeleteExpression = new NoDeleteExpression(sourceFile, this.getOptions()); @@ -28,7 +27,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoDeleteExpression extends Lint.RuleWalker { - public visitExpressionStatement(node: ts.ExpressionStatement) { super.visitExpressionStatement(node); if (node.expression.kind === ts.SyntaxKind.DeleteExpression) { @@ -44,5 +42,4 @@ class NoDeleteExpression extends Lint.RuleWalker { const msg: string = Rule.FAILURE_STRING + deletedObject.getFullText().trim(); this.addFailureAt(deletedObject.getStart(), deletedObject.getWidth(), msg); } - } diff --git a/src/noDisableAutoSanitizationRule.ts b/src/noDisableAutoSanitizationRule.ts index 9889f32c7..7d6bb5e52 100644 --- a/src/noDisableAutoSanitizationRule.ts +++ b/src/noDisableAutoSanitizationRule.ts @@ -1,37 +1,36 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-disable-auto-sanitization', - type: 'maintainability', - description: 'Do not disable auto-sanitization of HTML because this opens up your page to an XSS attack. ', + ruleName: "no-disable-auto-sanitization", + type: "maintainability", + description: "Do not disable auto-sanitization of HTML because this opens up your page to an XSS attack. ", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '157, 159, 75, 79, 85, 749, 676' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "157, 159, 75, 79, 85, 749, 676" }; - public static FAILURE_STRING: string = 'Forbidden call to '; + public static FAILURE_STRING: string = "Forbidden call to "; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoDisableAutoSanitizationWalker(sourceFile, this.getOptions())); } } class NoDisableAutoSanitizationWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { - const functionName : string = AstUtils.getFunctionName(node); - if (functionName === 'execUnsafeLocalFunction' || functionName === 'setInnerHTMLUnsafe') { + const functionName: string = AstUtils.getFunctionName(node); + if (functionName === "execUnsafeLocalFunction" || functionName === "setInnerHTMLUnsafe") { this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + functionName); } super.visitCallExpression(node); diff --git a/src/noDocumentDomainRule.ts b/src/noDocumentDomainRule.ts index 1eb22cfde..ee3a5f800 100644 --- a/src/noDocumentDomainRule.ts +++ b/src/noDocumentDomainRule.ts @@ -1,26 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-document-domain', - type: 'maintainability', - description: 'Do not write to document.domain. Scripts setting document.domain to any value should be ' + - 'validated to ensure that the value is on a list of allowed sites.', + ruleName: "no-document-domain", + type: "maintainability", + description: + "Do not write to document.domain. Scripts setting document.domain to any value should be " + + "validated to ensure that the value is on a list of allowed sites.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security" }; - public static FAILURE_STRING: string = 'Forbidden write to document.domain: '; + public static FAILURE_STRING: string = "Forbidden write to document.domain: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoDocumentDomainRuleWalker(sourceFile, this.getOptions())); @@ -29,9 +29,11 @@ export class Rule extends Lint.Rules.AbstractRule { class NoDocumentDomainRuleWalker extends Lint.RuleWalker { protected visitBinaryExpression(node: ts.BinaryExpression): void { - if (node.operatorToken.getText() === '=' - && node.left.kind === ts.SyntaxKind.PropertyAccessExpression - && this.isDocumentDomainProperty(node.left)) { + if ( + node.operatorToken.getText() === "=" && + node.left.kind === ts.SyntaxKind.PropertyAccessExpression && + this.isDocumentDomainProperty(node.left) + ) { const msg: string = Rule.FAILURE_STRING + node.getFullText().trim(); this.addFailureAt(node.getStart(), node.getWidth(), msg); } @@ -39,11 +41,9 @@ class NoDocumentDomainRuleWalker extends Lint.RuleWalker { } private isDocumentDomainProperty(node: ts.PropertyAccessExpression): boolean { - if (node.name.text !== 'domain') { + if (node.name.text !== "domain") { return false; } - return node.expression.getText() === 'document' - || node.expression.getText() === 'window.document'; - + return node.expression.getText() === "document" || node.expression.getText() === "window.document"; } } diff --git a/src/noDocumentWriteRule.ts b/src/noDocumentWriteRule.ts index f3738c1bd..913cd1cf0 100644 --- a/src/noDocumentWriteRule.ts +++ b/src/noDocumentWriteRule.ts @@ -1,45 +1,42 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-document-write', - type: 'maintainability', - description: 'Do not use document.write', + ruleName: "no-document-write", + type: "maintainability", + description: "Do not use document.write", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '79, 85' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "79, 85" }; - public static WRITE_FAILURE: string = 'Forbidden call to document.write'; - public static WRITELN_FAILURE: string = 'Forbidden call to document.writeln'; + public static WRITE_FAILURE: string = "Forbidden call to document.write"; + public static WRITELN_FAILURE: string = "Forbidden call to document.writeln"; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoDocumentWriteWalker(sourceFile, this.getOptions())); } } class NoDocumentWriteWalker extends Lint.RuleWalker { - protected visitCallExpression(node: ts.CallExpression) { - const functionTarget = AstUtils.getFunctionTarget(node); - if (functionTarget === 'document' || functionTarget === 'window.document') { + if (functionTarget === "document" || functionTarget === "window.document") { if (node.arguments.length === 1) { const functionName: string = AstUtils.getFunctionName(node); - if (functionName === 'write') { + if (functionName === "write") { this.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITE_FAILURE); - } else if (functionName === 'writeln') { + } else if (functionName === "writeln") { this.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITELN_FAILURE); } } diff --git a/src/noDuplicateCaseRule.ts b/src/noDuplicateCaseRule.ts index 8d49f7439..d4cf6f32d 100644 --- a/src/noDuplicateCaseRule.ts +++ b/src/noDuplicateCaseRule.ts @@ -1,58 +1,58 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-duplicate-case', - type: 'maintainability', - description: 'Do not use duplicate case labels in switch statements.', + ruleName: "no-duplicate-case", + type: "maintainability", + description: "Do not use duplicate case labels in switch statements.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - recommendation: 'false,', - group: 'Deprecated', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + recommendation: "false,", + group: "Deprecated", + commonWeaknessEnumeration: "398, 710" }; - public static FAILURE_STRING: string = 'Duplicate case found in switch statement: '; + public static FAILURE_STRING: string = "Duplicate case found in switch statement: "; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn('Warning: no-duplicate-case rule is deprecated. ' + - 'Replace your usage with the TSLint no-duplicate-switch-case rule.'); + console.warn( + "Warning: no-duplicate-case rule is deprecated. " + "Replace your usage with the TSLint no-duplicate-switch-case rule." + ); Rule.isWarningShown = true; } return this.applyWithWalker(new NoDuplicateCaseRuleWalker(sourceFile, this.getOptions())); } - } class NoDuplicateCaseRuleWalker extends Lint.RuleWalker { protected visitSwitchStatement(node: ts.SwitchStatement): void { const seenLabels: string[] = []; - node.caseBlock.clauses.forEach((clauseOrDefault: ts.CaseOrDefaultClause): void => { - if (clauseOrDefault.kind === ts.SyntaxKind.CaseClause) { - const clause: ts.CaseClause = clauseOrDefault; - if (clause.expression !== undefined) { - const caseText = clause.expression.getText(); - if (seenLabels.indexOf(caseText) > -1) { - this.addFailureAt(clause.getStart(), clause.getWidth(), Rule.FAILURE_STRING + caseText); - } else { - seenLabels.push(caseText); + node.caseBlock.clauses.forEach( + (clauseOrDefault: ts.CaseOrDefaultClause): void => { + if (clauseOrDefault.kind === ts.SyntaxKind.CaseClause) { + const clause: ts.CaseClause = clauseOrDefault; + if (clause.expression !== undefined) { + const caseText = clause.expression.getText(); + if (seenLabels.indexOf(caseText) > -1) { + this.addFailureAt(clause.getStart(), clause.getWidth(), Rule.FAILURE_STRING + caseText); + } else { + seenLabels.push(caseText); + } } } } - }); + ); super.visitSwitchStatement(node); } - } diff --git a/src/noDuplicateParameterNamesRule.ts b/src/noDuplicateParameterNamesRule.ts index 9a0be0ba6..e0472a812 100644 --- a/src/noDuplicateParameterNamesRule.ts +++ b/src/noDuplicateParameterNamesRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-duplicate-parameter-names', - type: 'maintainability', - description: 'Deprecated - This rule is now enforced by the TypeScript compiler', + ruleName: "no-duplicate-parameter-names", + type: "maintainability", + description: "Deprecated - This rule is now enforced by the TypeScript compiler", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false, // now supported by TypeScript compiler' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false, // now supported by TypeScript compiler" }; - public static FAILURE_STRING: string = 'Duplicate parameter name: '; + public static FAILURE_STRING: string = "Duplicate parameter name: "; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoDuplicateParameterNamesWalker(sourceFile, this.getOptions())); } } @@ -53,18 +52,19 @@ class NoDuplicateParameterNamesWalker extends Lint.RuleWalker { super.visitFunctionExpression(node); } - private validateParameterNames(node : ts.SignatureDeclaration) { - const seenNames : {[index: string]: boolean} = {}; - node.parameters.forEach((parameter : ts.ParameterDeclaration) : void => { - const parameterName : string = parameter.name.getText(); // how does one check if the union type is Identifier? - if (parameterName !== undefined) { - if (seenNames[parameterName]) { - this.addFailureAt( - parameter.name.getStart(), parameterName.length, Rule.FAILURE_STRING + '\'' + parameterName + '\''); - } else { - seenNames[parameterName] = true; + private validateParameterNames(node: ts.SignatureDeclaration) { + const seenNames: { [index: string]: boolean } = {}; + node.parameters.forEach( + (parameter: ts.ParameterDeclaration): void => { + const parameterName: string = parameter.name.getText(); // how does one check if the union type is Identifier? + if (parameterName !== undefined) { + if (seenNames[parameterName]) { + this.addFailureAt(parameter.name.getStart(), parameterName.length, Rule.FAILURE_STRING + "'" + parameterName + "'"); + } else { + seenNames[parameterName] = true; + } } } - }); + ); } } diff --git a/src/noEmptyInterfacesRule.ts b/src/noEmptyInterfacesRule.ts index fed659e2a..7532c10a1 100644 --- a/src/noEmptyInterfacesRule.ts +++ b/src/noEmptyInterfacesRule.ts @@ -1,47 +1,43 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-empty-interfaces', - type: 'maintainability', - description: 'Do not use empty interfaces.', + ruleName: "no-empty-interfaces", + type: "maintainability", + description: "Do not use empty interfaces.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false, // use tslint no-empty-interface rule instead', - commonWeaknessEnumeration: '398, 710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false, // use tslint no-empty-interface rule instead", + commonWeaknessEnumeration: "398, 710" }; - public static FAILURE_STRING: string = 'Do not declare empty interfaces: '; + public static FAILURE_STRING: string = "Do not declare empty interfaces: "; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn('Warning: no-empty-interfaces rule is deprecated. Replace your usage with the TSLint no-empty-interface rule.'); + console.warn("Warning: no-empty-interfaces rule is deprecated. Replace your usage with the TSLint no-empty-interface rule."); Rule.isWarningShown = true; } return this.applyWithWalker(new NoEmptyInterfacesRuleWalker(sourceFile, this.getOptions())); } - } class NoEmptyInterfacesRuleWalker extends Lint.RuleWalker { protected visitInterfaceDeclaration(node: ts.InterfaceDeclaration): void { // do we have an empty interface? if (this.isInterfaceEmpty(node) && !this.hasMultipleParents(node)) { - this.addFailureAt( - node.getStart(), node.getWidth(), Rule.FAILURE_STRING + '\'' + node.name.getText() + '\'' - ); + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + "'" + node.name.getText() + "'"); } super.visitInterfaceDeclaration(node); } diff --git a/src/noEmptyLineAfterOpeningBraceRule.ts b/src/noEmptyLineAfterOpeningBraceRule.ts index 91be39b1c..960054833 100644 --- a/src/noEmptyLineAfterOpeningBraceRule.ts +++ b/src/noEmptyLineAfterOpeningBraceRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {forEachTokenWithTrivia} from 'tsutils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { forEachTokenWithTrivia } from "tsutils"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-empty-line-after-opening-brace', - type: 'maintainability', - description: 'Avoid an empty line after an opening brace', + ruleName: "no-empty-line-after-opening-brace", + type: "maintainability", + description: "Avoid an empty line after an opening brace", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Whitespace', - recommendation: 'false,', - commonWeaknessEnumeration: '710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Whitespace", + recommendation: "false,", + commonWeaknessEnumeration: "710" }; - public static FAILURE_STRING: string = 'Opening brace cannot be followed by empty line'; + public static FAILURE_STRING: string = "Opening brace cannot be followed by empty line"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoEmptyLineAfterOpeningBraceWalker(sourceFile, this.getOptions())); @@ -48,10 +47,11 @@ class NoEmptyLineAfterOpeningBraceWalker extends Lint.RuleWalker { let previousPrevious: ts.SyntaxKind; forEachTokenWithTrivia(node, ({}, tokenSyntaxKind, range) => { - if (previousPrevious === ts.SyntaxKind.OpenBraceToken && + if ( + previousPrevious === ts.SyntaxKind.OpenBraceToken && previous === ts.SyntaxKind.NewLineTrivia && - tokenSyntaxKind === ts.SyntaxKind.NewLineTrivia) { - + tokenSyntaxKind === ts.SyntaxKind.NewLineTrivia + ) { this.addFailureAt(range.pos, 1, Rule.FAILURE_STRING); } @@ -62,4 +62,4 @@ class NoEmptyLineAfterOpeningBraceWalker extends Lint.RuleWalker { } }); } -} \ No newline at end of file +} diff --git a/src/noExecScriptRule.ts b/src/noExecScriptRule.ts index 9287c4f23..c68ad1be3 100644 --- a/src/noExecScriptRule.ts +++ b/src/noExecScriptRule.ts @@ -1,30 +1,29 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -import {AstUtils} from './utils/AstUtils'; +import { AstUtils } from "./utils/AstUtils"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-exec-script', - type: 'maintainability', - description: 'Do not use the execScript functions', + ruleName: "no-exec-script", + type: "maintainability", + description: "Do not use the execScript functions", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95, 676' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95, 676" }; - public static FAILURE_STRING: string = 'forbidden execScript: '; + public static FAILURE_STRING: string = "forbidden execScript: "; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoEvalScriptWalker(sourceFile, this.getOptions())); } } @@ -35,11 +34,11 @@ class NoEvalScriptWalker extends Lint.RuleWalker { super.visitCallExpression(node); } - private validateExpression(node : ts.CallExpression) : void { + private validateExpression(node: ts.CallExpression): void { const expression: ts.Expression = node.expression; - const functionName : string = AstUtils.getFunctionName(node); - if (functionName === 'execScript') { - const msg : string = Rule.FAILURE_STRING + expression.getFullText().trim(); + const functionName: string = AstUtils.getFunctionName(node); + if (functionName === "execScript") { + const msg: string = Rule.FAILURE_STRING + expression.getFullText().trim(); this.addFailureAt(expression.getStart(), expression.getWidth(), msg); } } diff --git a/src/noForInRule.ts b/src/noForInRule.ts index a3f91ad17..8a825aeea 100644 --- a/src/noForInRule.ts +++ b/src/noForInRule.ts @@ -1,23 +1,22 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-for-in', - type: 'maintainability', - description: 'Avoid use of for-in statements. They can be replaced by Object.keys', + ruleName: "no-for-in", + type: "maintainability", + description: "Avoid use of for-in statements. They can be replaced by Object.keys", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; public static FAILURE_STRING_FACTORY(initializer: string, expression: string): string { diff --git a/src/noFunctionConstructorWithStringArgsRule.ts b/src/noFunctionConstructorWithStringArgsRule.ts index 9a051fee3..e00017828 100644 --- a/src/noFunctionConstructorWithStringArgsRule.ts +++ b/src/noFunctionConstructorWithStringArgsRule.ts @@ -1,41 +1,40 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-function-constructor-with-string-args', - type: 'maintainability', - description: 'Do not use the version of the Function constructor that accepts a string argument to define the body of the function', + ruleName: "no-function-constructor-with-string-args", + type: "maintainability", + description: "Do not use the version of the Function constructor that accepts a string argument to define the body of the function", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95, 676, 242, 116' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95, 676, 242, 116" }; - public static FAILURE_STRING: string = 'forbidden: Function constructor with string arguments '; + public static FAILURE_STRING: string = "forbidden: Function constructor with string arguments "; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoFunctionConstructorWithStringArgsWalker(sourceFile, this.getOptions())); } } class NoFunctionConstructorWithStringArgsWalker extends Lint.RuleWalker { - public constructor(sourceFile : ts.SourceFile, options : Lint.IOptions) { + public constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { super(sourceFile, options); } protected visitNewExpression(node: ts.NewExpression): void { - const functionName = AstUtils.getFunctionName(node); - if (functionName === 'Function' && node.arguments !== undefined && node.arguments.length > 0) { + const functionName = AstUtils.getFunctionName(node); + if (functionName === "Function" && node.arguments !== undefined && node.arguments.length > 0) { this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING); } super.visitNewExpression(node); diff --git a/src/noFunctionExpressionRule.ts b/src/noFunctionExpressionRule.ts index 7727096ec..0816e2381 100644 --- a/src/noFunctionExpressionRule.ts +++ b/src/noFunctionExpressionRule.ts @@ -1,32 +1,30 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { AstUtils } from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-function-expression', - type: 'maintainability', - description: 'Do not use function expressions; use arrow functions (lambdas) instead.', + ruleName: "no-function-expression", + type: "maintainability", + description: "Do not use function expressions; use arrow functions (lambdas) instead.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; - public static FAILURE_STRING: string = 'Use arrow function instead of function expression'; + public static FAILURE_STRING: string = "Use arrow function instead of function expression"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoFunctionExpressionRuleWalker(sourceFile, this.getOptions())); } - } class NoFunctionExpressionRuleWalker extends Lint.RuleWalker { @@ -48,9 +46,12 @@ class NoFunctionExpressionRuleWalker extends Lint.RuleWalker { const isGenericFunctionInTSX = this.allowGenericFunctionExpression && walker.isGenericFunction; // function expression that access 'this' is allowed - if (!walker.isAccessingThis && !node.asteriskToken + if ( + !walker.isAccessingThis && + !node.asteriskToken && // generic function expression in .tsx file is allowed - && !isGenericFunctionInTSX) { + !isGenericFunctionInTSX + ) { this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING); } @@ -62,7 +63,7 @@ class SingleFunctionWalker extends Lint.RuleWalker { public isAccessingThis: boolean = false; public isGenericFunction: boolean = false; protected visitNode(node: ts.Node): void { - if (node.getText() === 'this') { + if (node.getText() === "this") { this.isAccessingThis = true; } super.visitNode(node); diff --git a/src/noHttpStringRule.ts b/src/noHttpStringRule.ts index 1f5de64f3..c3e4ca554 100644 --- a/src/noHttpStringRule.ts +++ b/src/noHttpStringRule.ts @@ -1,35 +1,33 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-http-string', - type: 'maintainability', + ruleName: "no-http-string", + type: "maintainability", /* tslint:disable:no-http-string */ - description: 'Do not use strings that start with \'http:\'. URL strings should start with \'https:\'. ', + description: "Do not use strings that start with 'http:'. URL strings should start with 'https:'. ", /* tslint:enable:no-http-string */ options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", recommendation: '[true, "http://www.example.com/?.*", "http://localhost:?.*"],', - commonWeaknessEnumeration: '319' + commonWeaknessEnumeration: "319" }; - public static FAILURE_STRING: string = 'Forbidden http url in string: '; + public static FAILURE_STRING: string = "Forbidden http url in string: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoHttpStringWalker(sourceFile, this.getOptions())); } - } class NoHttpStringWalker extends Lint.RuleWalker { @@ -50,9 +48,9 @@ class NoHttpStringWalker extends Lint.RuleWalker { private visitLiteralExpression(node: ts.LiteralExpression | ts.LiteralLikeNode): void { const stringText: string = node.text; // tslint:disable-next-line no-http-string - if (stringText.indexOf('http:') === 0) { + if (stringText.indexOf("http:") === 0) { if (!this.isSuppressed(stringText)) { - const failureString = Rule.FAILURE_STRING + '\'' + stringText + '\''; + const failureString = Rule.FAILURE_STRING + "'" + stringText + "'"; this.addFailureAt(node.getStart(), node.getWidth(), failureString); } } @@ -60,9 +58,12 @@ class NoHttpStringWalker extends Lint.RuleWalker { private isSuppressed(stringText: string): boolean { const allExceptions = NoHttpStringWalker.getExceptions(this.getOptions()); - return Utils.exists(allExceptions, (exception: string): boolean => { - return new RegExp(exception).test(stringText); - }); + return Utils.exists( + allExceptions, + (exception: string): boolean => { + return new RegExp(exception).test(stringText); + } + ); } private static getExceptions(options: Lint.IOptions): string[] | undefined { diff --git a/src/noIncrementDecrementRule.ts b/src/noIncrementDecrementRule.ts index 5a5a9e67f..a4c93ee8c 100644 --- a/src/noIncrementDecrementRule.ts +++ b/src/noIncrementDecrementRule.ts @@ -1,23 +1,22 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-increment-decrement', - type: 'maintainability', - description: 'Avoid use of increment and decrement operators particularly as part of complicated expressions', + ruleName: "no-increment-decrement", + type: "maintainability", + description: "Avoid use of increment and decrement operators particularly as part of complicated expressions", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -36,12 +35,11 @@ class NoIncrementDecrementWalker extends Lint.RuleWalker { super.visitPrefixUnaryExpression(node); } - private validateUnaryExpression(node : ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) { + private validateUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) { if (node.operator === ts.SyntaxKind.PlusPlusToken) { - this.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden ++ operator'); + this.addFailureAt(node.getStart(), node.getWidth(), "Forbidden ++ operator"); } else if (node.operator === ts.SyntaxKind.MinusMinusToken) { - this.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden -- operator'); + this.addFailureAt(node.getStart(), node.getWidth(), "Forbidden -- operator"); } } - } diff --git a/src/noInnerHtmlRule.ts b/src/noInnerHtmlRule.ts index f46062bd1..ca4e9af41 100644 --- a/src/noInnerHtmlRule.ts +++ b/src/noInnerHtmlRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_INNER: string = 'Writing a string to the innerHTML property is insecure: '; -const FAILURE_OUTER: string = 'Writing a string to the outerHTML property is insecure: '; -const FAILURE_HTML_LIB: string = 'Using the html() function to write a string to innerHTML is insecure: '; +const FAILURE_INNER: string = "Writing a string to the innerHTML property is insecure: "; +const FAILURE_OUTER: string = "Writing a string to the outerHTML property is insecure: "; +const FAILURE_HTML_LIB: string = "Using the html() function to write a string to innerHTML is insecure: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-inner-html', - type: 'maintainability', - description: 'Do not write values to innerHTML, outerHTML, or set HTML using the JQuery html() function.', + ruleName: "no-inner-html", + type: "maintainability", + description: "Do not write values to innerHTML, outerHTML, or set HTML using the JQuery html() function.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '79, 85, 710' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "79, 85, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -31,14 +30,13 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoInnerHtmlRuleWalker extends Lint.RuleWalker { - private readonly htmlLibExpressionRegex: RegExp = /^(jquery|[$])/i; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { super(sourceFile, options); const opt = this.getOptions(); - if (typeof opt[1] === 'object' && opt[1]['html-lib-matcher']) { - this.htmlLibExpressionRegex = new RegExp(opt[1]['html-lib-matcher']); + if (typeof opt[1] === "object" && opt[1]["html-lib-matcher"]) { + this.htmlLibExpressionRegex = new RegExp(opt[1]["html-lib-matcher"]); } } @@ -49,9 +47,9 @@ class NoInnerHtmlRuleWalker extends Lint.RuleWalker { if (node.left.kind === ts.SyntaxKind.PropertyAccessExpression) { const propAccess: ts.PropertyAccessExpression = node.left; const propName: string = propAccess.name.text; - if (propName === 'innerHTML') { + if (propName === "innerHTML") { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_INNER + node.getText()); - } else if (propName === 'outerHTML') { + } else if (propName === "outerHTML") { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_OUTER + node.getText()); } } @@ -61,7 +59,7 @@ class NoInnerHtmlRuleWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { const functionName = AstUtils.getFunctionName(node); - if (functionName === 'html') { + if (functionName === "html") { if (node.arguments.length > 0) { const functionTarget = AstUtils.getFunctionTarget(node); if (functionTarget !== undefined && this.htmlLibExpressionRegex.test(functionTarget)) { diff --git a/src/noInvalidRegexpRule.ts b/src/noInvalidRegexpRule.ts index 6d6878f6f..87d05fdb3 100644 --- a/src/noInvalidRegexpRule.ts +++ b/src/noInvalidRegexpRule.ts @@ -1,22 +1,21 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-invalid-regexp', - type: 'maintainability', - description: 'Do not use invalid regular expression strings in the RegExp constructor.', + ruleName: "no-invalid-regexp", + type: "maintainability", + description: "Do not use invalid regular expression strings in the RegExp constructor.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -36,7 +35,7 @@ class NoInvalidRegexpRuleWalker extends Lint.RuleWalker { } private validateCall(expression: ts.CallExpression | ts.NewExpression): void { - if (expression.expression.getText() === 'RegExp' && expression.arguments !== undefined && expression.arguments.length > 0) { + if (expression.expression.getText() === "RegExp" && expression.arguments !== undefined && expression.arguments.length > 0) { const arg1: ts.Expression = expression.arguments[0]; if (arg1.kind === ts.SyntaxKind.StringLiteral) { const regexpText: string = (arg1).text; diff --git a/src/noJqueryRawElementsRule.ts b/src/noJqueryRawElementsRule.ts index 1cea35cf4..8be5c92cc 100644 --- a/src/noJqueryRawElementsRule.ts +++ b/src/noJqueryRawElementsRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import * as ts from "typescript"; +import * as Lint from "tslint"; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING_MANIPULATION: string = 'Replace HTML string manipulation with jQuery API: '; -const FAILURE_STRING_COMPLEX: string = 'Replace complex HTML strings with jQuery API: '; +const FAILURE_STRING_MANIPULATION: string = "Replace HTML string manipulation with jQuery API: "; +const FAILURE_STRING_COMPLEX: string = "Replace complex HTML strings with jQuery API: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-jquery-raw-elements', - type: 'maintainability', - description: 'Do not create HTML elements using JQuery and string concatenation. It is error prone and can hide subtle defects.', + ruleName: "no-jquery-raw-elements", + type: "maintainability", + description: "Do not create HTML elements using JQuery and string concatenation. It is error prone and can hide subtle defects.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,7 +29,6 @@ export class Rule extends Lint.Rules.AbstractRule { class NoJqueryRawElementsRuleWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { - const functionName: string = AstUtils.getFunctionName(node); if (AstUtils.isJQuery(functionName) && node.arguments.length > 0) { const firstArg: ts.Expression = node.arguments[0]; @@ -69,7 +67,7 @@ class NoJqueryRawElementsRuleWalker extends Lint.RuleWalker { const match = text.match(/^<[A-Za-z]+\s*>(.*)<\/[A-Za-z]+\s*>$/m); if (match !== null && match[1] !== undefined) { const enclosedContent: string = match[1]; // get the stuff inside the tag - if (enclosedContent.indexOf('<') === -1 && enclosedContent.indexOf('>') === -1) { + if (enclosedContent.indexOf("<") === -1 && enclosedContent.indexOf(">") === -1) { return false; // enclosed content looks like it contains no html elements } } @@ -78,7 +76,6 @@ class NoJqueryRawElementsRuleWalker extends Lint.RuleWalker { } class HtmlLikeStringLiteralFinder extends Lint.RuleWalker { - private found: boolean = false; public isFound(): boolean { @@ -86,7 +83,7 @@ class HtmlLikeStringLiteralFinder extends Lint.RuleWalker { } protected visitStringLiteral(node: ts.StringLiteral): void { - if (node.text.indexOf('<') > -1 || node.text.indexOf('>') > -1) { + if (node.text.indexOf("<") > -1 || node.text.indexOf(">") > -1) { this.found = true; } else { super.visitStringLiteral(node); diff --git a/src/noMissingVisibilityModifiersRule.ts b/src/noMissingVisibilityModifiersRule.ts index b8cab5b8b..e7a5dfd48 100644 --- a/src/noMissingVisibilityModifiersRule.ts +++ b/src/noMissingVisibilityModifiersRule.ts @@ -1,25 +1,24 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-missing-visibility-modifiers', - type: 'maintainability', - description: 'Deprecated - This rule is in the TSLint product as `member-access`', + ruleName: "no-missing-visibility-modifiers", + type: "maintainability", + description: "Deprecated - This rule is in the TSLint product as `member-access`", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false, // use tslint member-access rule instead', - commonWeaknessEnumeration: '398, 710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false, // use tslint member-access rule instead", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,7 +29,7 @@ export class Rule extends Lint.Rules.AbstractRule { class MissingVisibilityModifierWalker extends Lint.RuleWalker { protected visitPropertyDeclaration(node: ts.PropertyDeclaration): void { if (this.isMissingVisibilityModifier(node)) { - const failureString = 'Field missing visibility modifier: ' + this.getFailureCodeSnippet(node); + const failureString = "Field missing visibility modifier: " + this.getFailureCodeSnippet(node); this.addFailureAt(node.getStart(), node.getWidth(), failureString); } super.visitPropertyDeclaration(node); @@ -38,20 +37,20 @@ class MissingVisibilityModifierWalker extends Lint.RuleWalker { protected visitMethodDeclaration(node: ts.MethodDeclaration): void { if (this.isMissingVisibilityModifier(node)) { - const failureString = 'Method missing visibility modifier: ' + this.getFailureCodeSnippet(node); + const failureString = "Method missing visibility modifier: " + this.getFailureCodeSnippet(node); this.addFailureAt(node.getStart(), node.getWidth(), failureString); } super.visitMethodDeclaration(node); } - private isMissingVisibilityModifier(node: ts.Declaration) : boolean { + private isMissingVisibilityModifier(node: ts.Declaration): boolean { return !(AstUtils.isPrivate(node) || AstUtils.isProtected(node) || AstUtils.isPublic(node)); } private getFailureCodeSnippet(node: ts.Node) { const message: string = node.getText(); - if (message.indexOf('\n') > 0) { - return message.substr(0, message.indexOf('\n')); + if (message.indexOf("\n") > 0) { + return message.substr(0, message.indexOf("\n")); } return message; } diff --git a/src/noMultilineStringRule.ts b/src/noMultilineStringRule.ts index 7e7006289..c8d3a1c60 100644 --- a/src/noMultilineStringRule.ts +++ b/src/noMultilineStringRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-multiline-string', - type: 'maintainability', - description: 'Do not declare multiline strings', + ruleName: "no-multiline-string", + type: "maintainability", + description: "Do not declare multiline strings", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - recommendation: 'false,', - commonWeaknessEnumeration: '710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + recommendation: "false,", + commonWeaknessEnumeration: "710" }; - public static FAILURE_STRING: string = 'Forbidden Multiline string: '; + public static FAILURE_STRING: string = "Forbidden Multiline string: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoMultilineStringWalker(sourceFile, this.getOptions())); @@ -31,10 +30,10 @@ export class Rule extends Lint.Rules.AbstractRule { class NoMultilineStringWalker extends Lint.RuleWalker { protected visitNode(node: ts.Node): void { if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { - const fullText : string = node.getFullText(); - const firstLine : string = fullText.substring(0, fullText.indexOf('\n')); - const trimmed : string = firstLine.substring(0, 40).trim(); - this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + trimmed + '...'); + const fullText: string = node.getFullText(); + const firstLine: string = fullText.substring(0, fullText.indexOf("\n")); + const trimmed: string = firstLine.substring(0, 40).trim(); + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + trimmed + "..."); } super.visitNode(node); } diff --git a/src/noMultipleVarDeclRule.ts b/src/noMultipleVarDeclRule.ts index 574a302d1..0be9fb314 100644 --- a/src/noMultipleVarDeclRule.ts +++ b/src/noMultipleVarDeclRule.ts @@ -1,39 +1,36 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-multiple-var-decl', - type: 'maintainability', - description: 'Deprecated - This rule is now part of the base TSLint product as the rule named \'one-variable-per-declaration\'', + ruleName: "no-multiple-var-decl", + type: "maintainability", + description: "Deprecated - This rule is now part of the base TSLint product as the rule named 'one-variable-per-declaration'", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false, // use tslint one-variable-per-declaration rule instead', - commonWeaknessEnumeration: '710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false, // use tslint one-variable-per-declaration rule instead", + commonWeaknessEnumeration: "710" }; - public static FAILURE_STRING: string = 'Do not use comma separated variable declarations: '; + public static FAILURE_STRING: string = "Do not use comma separated variable declarations: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoMultipleVarDeclRuleWalker(sourceFile, this.getOptions())); } - } class NoMultipleVarDeclRuleWalker extends Lint.RuleWalker { protected visitVariableStatement(node: ts.VariableStatement): void { if (node.declarationList.declarations.length > 1) { - this.addFailureAt(node.getStart(), node.getWidth(), - Rule.FAILURE_STRING + node.declarationList.declarations[0].getText() + ','); + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + node.declarationList.declarations[0].getText() + ","); } super.visitVariableStatement(node); } diff --git a/src/noOctalLiteralRule.ts b/src/noOctalLiteralRule.ts index d28f507ba..5203ae52f 100644 --- a/src/noOctalLiteralRule.ts +++ b/src/noOctalLiteralRule.ts @@ -1,25 +1,24 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-octal-literal', - type: 'maintainability', - description: 'Do not use octal literals or escaped octal sequences', + ruleName: "no-octal-literal", + type: "maintainability", + description: "Do not use octal literals or escaped octal sequences", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security" }; - public static FAILURE_STRING: string = 'Octal literals should not be used: '; + public static FAILURE_STRING: string = "Octal literals should not be used: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const noOctalLiteral = new NoOctalLiteral(sourceFile, this.getOptions()); @@ -40,8 +39,9 @@ class NoOctalLiteral extends Lint.RuleWalker { if (match) { let octalValue: string = match[2]; // match[2] is the matched octal value. - const backslashCount: number = octalValue.lastIndexOf('\\') + 1; - if (backslashCount % 2 === 1) { // Make sure the string starts with an odd number of backslashes + const backslashCount: number = octalValue.lastIndexOf("\\") + 1; + if (backslashCount % 2 === 1) { + // Make sure the string starts with an odd number of backslashes octalValue = octalValue.substr(backslashCount - 1); const startOfMatch = node.getStart() + node.getText().indexOf(octalValue); diff --git a/src/noRegexSpacesRule.ts b/src/noRegexSpacesRule.ts index ff9d2b8ee..7ea534a66 100644 --- a/src/noRegexSpacesRule.ts +++ b/src/noRegexSpacesRule.ts @@ -1,41 +1,38 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-regex-spaces', - type: 'maintainability', - description: 'Do not use multiple spaces in a regular expression literal. Similar to the ESLint no-regex-spaces rule', + ruleName: "no-regex-spaces", + type: "maintainability", + description: "Do not use multiple spaces in a regular expression literal. Similar to the ESLint no-regex-spaces rule", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness" }; - public static FAILURE_STRING: string = 'Spaces in regular expressions are hard to count. Use '; + public static FAILURE_STRING: string = "Spaces in regular expressions are hard to count. Use "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoRegexSpacesRuleWalker(sourceFile, this.getOptions())); } - } class NoRegexSpacesRuleWalker extends Lint.RuleWalker { protected visitRegularExpressionLiteral(node: ts.Node): void { const match = /( {2,})+?/.exec(node.getText()); if (match !== null) { - const replacement: string = '{' + match[0].length + '}'; + const replacement: string = "{" + match[0].length + "}"; this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + replacement); } super.visitRegularExpressionLiteral(node); } - } diff --git a/src/noRelativeImportsRule.ts b/src/noRelativeImportsRule.ts index 228485fd6..79a2ed136 100644 --- a/src/noRelativeImportsRule.ts +++ b/src/noRelativeImportsRule.ts @@ -1,41 +1,40 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const OPTION_ALLOW_SIBLINGS = 'allow-siblings'; +const OPTION_ALLOW_SIBLINGS = "allow-siblings"; -const FAILURE_STRING_EXT: string = 'External module is being loaded from a relative path. Please use an absolute path: '; -const FAILURE_STRING_IMPORT: string = 'Imported module is being loaded from a relative path. Please use an absolute path: '; +const FAILURE_STRING_EXT: string = "External module is being loaded from a relative path. Please use an absolute path: "; +const FAILURE_STRING_IMPORT: string = "Imported module is being loaded from a relative path. Please use an absolute path: "; const FAILURE_STRING_EXT_SIBLINGS: string = - 'External module path starts with reference to parent directory. Please use an absolute path or sibling files/folders: '; + "External module path starts with reference to parent directory. Please use an absolute path or sibling files/folders: "; const FAILURE_STRING_IMPORT_SIBLINGS: string = - 'Imported module path starts with reference to parent directory. Please use an absolute path or sibling files/folders: '; + "Imported module path starts with reference to parent directory. Please use an absolute path or sibling files/folders: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-relative-imports', - type: 'maintainability', - description: 'Do not use relative paths when importing external modules or ES6 import declarations', + ruleName: "no-relative-imports", + type: "maintainability", + description: "Do not use relative paths when importing external modules or ES6 import declarations", options: { - type: 'array', + type: "array", items: { - type: 'string', - enum: [OPTION_ALLOW_SIBLINGS] + type: "string", + enum: [OPTION_ALLOW_SIBLINGS] }, minLength: 0, maxLength: 1 - }, + }, optionsDescription: `One argument may be optionally provided: \n\n' + '* \`${OPTION_ALLOW_SIBLINGS}\` allows relative imports for files in the same or nested folders.`, typescriptOnly: false, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -74,12 +73,12 @@ class NoRelativeImportsRuleWalker extends Lint.RuleWalker { const moduleName: ts.StringLiteral = expression; // when no siblings allowed path cannot start with '.' (relative) - if (!this.allowSiblings && moduleName.text[0] === '.') { + if (!this.allowSiblings && moduleName.text[0] === ".") { return false; } // when siblings allowed path cannot start '..' (reference to parrent directory) - if (this.allowSiblings && moduleName.text.indexOf('..') === 0) { + if (this.allowSiblings && moduleName.text.indexOf("..") === 0) { return false; } } diff --git a/src/noReservedKeywordsRule.ts b/src/noReservedKeywordsRule.ts index fd4ed8b14..6b9105640 100644 --- a/src/noReservedKeywordsRule.ts +++ b/src/noReservedKeywordsRule.ts @@ -1,59 +1,96 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {BannedTermWalker} from './utils/BannedTermWalker'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { BannedTermWalker } from "./utils/BannedTermWalker"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-reserved-keywords', - type: 'maintainability', - description: 'Do not use reserved keywords as names of local variables, fields, functions, or other identifiers.', + ruleName: "no-reserved-keywords", + type: "maintainability", + description: "Do not use reserved keywords as names of local variables, fields, functions, or other identifiers.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '398' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "398" }; - private static readonly FAILURE_STRING: string = 'Forbidden reference to reserved keyword: '; + private static readonly FAILURE_STRING: string = "Forbidden reference to reserved keyword: "; // taken from https://github.com/Microsoft/TypeScript/issues/2536 private static readonly BANNED_TERMS: string[] = [ // reserved keywords - 'break', 'case', 'catch', 'class', - 'const', 'continue', 'debugger', 'default', - 'delete', 'do', 'else', 'enum', 'export', - 'extends', 'false', 'finally', 'for', - 'function', 'if', 'import', 'in', - 'instanceof', 'new', 'null', 'return', - 'super', 'switch', 'this', 'throw', - 'true', 'try', 'typeof', 'var', - 'void', 'while', 'with', + "break", + "case", + "catch", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "enum", + "export", + "extends", + "false", + "finally", + "for", + "function", + "if", + "import", + "in", + "instanceof", + "new", + "null", + "return", + "super", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "var", + "void", + "while", + "with", // reserved keywords in strict mode - 'as', 'implements', 'interface', 'let', - 'package', 'private', 'protected', - 'public', 'static', 'yield', + "as", + "implements", + "interface", + "let", + "package", + "private", + "protected", + "public", + "static", + "yield", // contextual keywords - 'any', 'boolean', 'constructor', - 'declare', 'get', 'module', - 'require', 'number', 'set', - 'string', 'symbol', 'type', - 'from', 'of' + "any", + "boolean", + "constructor", + "declare", + "get", + "module", + "require", + "number", + "set", + "string", + "symbol", + "type", + "from", + "of" ]; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const walker: Lint.RuleWalker = new BannedTermWalker( - sourceFile, - this.getOptions(), - Rule.FAILURE_STRING, - Rule.BANNED_TERMS - ); + const walker: Lint.RuleWalker = new BannedTermWalker(sourceFile, this.getOptions(), Rule.FAILURE_STRING, Rule.BANNED_TERMS); return this.applyWithWalker(walker); } -} \ No newline at end of file +} diff --git a/src/noSingleLineBlockCommentRule.ts b/src/noSingleLineBlockCommentRule.ts index 808777455..8edc3a8fe 100644 --- a/src/noSingleLineBlockCommentRule.ts +++ b/src/noSingleLineBlockCommentRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {forEachTokenWithTrivia} from 'tsutils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { forEachTokenWithTrivia } from "tsutils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Replace block comment with a single-line comment'; +const FAILURE_STRING: string = "Replace block comment with a single-line comment"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-single-line-block-comment', - type: 'maintainability', - description: 'Avoid single line block comments; use single line comments instead', + ruleName: "no-single-line-block-comment", + type: "maintainability", + description: "Avoid single line block comments; use single line comments instead", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Whitespace', - commonWeaknessEnumeration: '710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Whitespace", + commonWeaknessEnumeration: "710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -29,14 +28,15 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoSingleLineBlockCommentRuleWalker extends Lint.RuleWalker { - public visitSourceFile(node: ts.SourceFile) { forEachTokenWithTrivia(node, (fullText, tokenSyntaxKind, range: ts.TextRange) => { const tokenText = fullText.substring(range.pos, range.end); - if (tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia - && this.isSingleLineComment(tokenText) - && !this.isTsLintSuppression(tokenText) - && !this.isFollowedByMoreCodeOnSameLine(fullText, range)) { + if ( + tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia && + this.isSingleLineComment(tokenText) && + !this.isTsLintSuppression(tokenText) && + !this.isFollowedByMoreCodeOnSameLine(fullText, range) + ) { this.addFailureAt(range.pos, range.end - range.pos, FAILURE_STRING); } }); diff --git a/src/noStatelessClassRule.ts b/src/noStatelessClassRule.ts index e4f91de41..c3b448c01 100644 --- a/src/noStatelessClassRule.ts +++ b/src/noStatelessClassRule.ts @@ -1,35 +1,34 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'A stateless class was found. This indicates a failure in the object model: '; +const FAILURE_STRING: string = "A stateless class was found. This indicates a failure in the object model: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-stateless-class', - type: 'maintainability', - description: 'A stateless class represents a failure in the object oriented design of the system.', + ruleName: "no-stateless-class", + type: "maintainability", + description: "A stateless class represents a failure in the object oriented design of the system.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - recommendation: 'false,', - group: 'Deprecated', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + recommendation: "false,", + group: "Deprecated", + commonWeaknessEnumeration: "398, 710" }; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn('Warning: no-stateless-class rule is deprecated. Replace your usage with the TSLint no-unnecessary-class rule.'); + console.warn("Warning: no-stateless-class rule is deprecated. Replace your usage with the TSLint no-unnecessary-class rule."); Rule.isWarningShown = true; } return this.applyWithWalker(new NoStatelessClassRuleWalker(sourceFile, this.getOptions())); @@ -39,7 +38,7 @@ export class Rule extends Lint.Rules.AbstractRule { class NoStatelessClassRuleWalker extends Lint.RuleWalker { protected visitClassDeclaration(node: ts.ClassDeclaration): void { if (!this.isClassStateful(node)) { - const className: string = node.name === undefined ? '' : node.name.text; + const className: string = node.name === undefined ? "" : node.name.text; this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING + className); } super.visitClassDeclaration(node); @@ -61,42 +60,56 @@ class NoStatelessClassRuleWalker extends Lint.RuleWalker { } private classDeclaresInstanceData(node: ts.ClassDeclaration): boolean { - return Utils.exists(node.members, (classElement: ts.ClassElement): boolean => { - if (classElement.kind === ts.SyntaxKind.Constructor) { - return false; - } - if (AstUtils.isStatic(classElement)) { - return false; + return Utils.exists( + node.members, + (classElement: ts.ClassElement): boolean => { + if (classElement.kind === ts.SyntaxKind.Constructor) { + return false; + } + if (AstUtils.isStatic(classElement)) { + return false; + } + return true; } - return true; - }); + ); } private classDeclaresConstructorProperties(node: ts.ClassDeclaration): boolean { - return Utils.exists(node.members, (element: ts.ClassElement): boolean => { - if (element.kind === ts.SyntaxKind.Constructor) { - return this.constructorDeclaresProperty(element); + return Utils.exists( + node.members, + (element: ts.ClassElement): boolean => { + if (element.kind === ts.SyntaxKind.Constructor) { + return this.constructorDeclaresProperty(element); + } + return false; } - return false; - }); + ); } private constructorDeclaresProperty(ctor: ts.ConstructorDeclaration): boolean { - return Utils.exists(ctor.parameters, (param: ts.ParameterDeclaration): boolean => { - if (param.modifiers === undefined) { - return false; - } + return Utils.exists( + ctor.parameters, + (param: ts.ParameterDeclaration): boolean => { + if (param.modifiers === undefined) { + return false; + } - return AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.PublicKeyword) - || AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.PrivateKeyword) - || AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.ProtectedKeyword) - || AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.ReadonlyKeyword); - }); + return ( + AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.PublicKeyword) || + AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.PrivateKeyword) || + AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.ProtectedKeyword) || + AstUtils.hasModifier(param.modifiers, ts.SyntaxKind.ReadonlyKeyword) + ); + } + ); } private classExtendsSomething(node: ts.ClassDeclaration): boolean { - return Utils.exists(node.heritageClauses, (clause: ts.HeritageClause): boolean => { - return clause.token === ts.SyntaxKind.ExtendsKeyword; - }); + return Utils.exists( + node.heritageClauses, + (clause: ts.HeritageClause): boolean => { + return clause.token === ts.SyntaxKind.ExtendsKeyword; + } + ); } } diff --git a/src/noStringBasedSetImmediateRule.ts b/src/noStringBasedSetImmediateRule.ts index 4b6a03f81..5fab5e5bb 100644 --- a/src/noStringBasedSetImmediateRule.ts +++ b/src/noStringBasedSetImmediateRule.ts @@ -1,34 +1,31 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {NoStringParameterToFunctionCallWalker} from './utils/NoStringParameterToFunctionCallWalker'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { NoStringParameterToFunctionCallWalker } from "./utils/NoStringParameterToFunctionCallWalker"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.OptionallyTypedRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-string-based-set-immediate', - type: 'maintainability', - description: 'Do not use the version of setImmediate that accepts code as a string argument.', + ruleName: "no-string-based-set-immediate", + type: "maintainability", + description: "Do not use the version of setImmediate that accepts code as a string argument.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95, 676, 242, 116' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95, 676, 242, 116" }; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithProgram(sourceFile, undefined); } - public applyWithProgram(sourceFile : ts.SourceFile, program : ts.Program | undefined): Lint.RuleFailure[] { - const walker : Lint.RuleWalker = new NoStringParameterToFunctionCallWalker( - sourceFile , 'setImmediate', this.getOptions(), program - ); + public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program | undefined): Lint.RuleFailure[] { + const walker: Lint.RuleWalker = new NoStringParameterToFunctionCallWalker(sourceFile, "setImmediate", this.getOptions(), program); return this.applyWithWalker(walker); } } diff --git a/src/noStringBasedSetIntervalRule.ts b/src/noStringBasedSetIntervalRule.ts index 441d33e8a..4ce4e622c 100644 --- a/src/noStringBasedSetIntervalRule.ts +++ b/src/noStringBasedSetIntervalRule.ts @@ -1,34 +1,31 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {NoStringParameterToFunctionCallWalker} from './utils/NoStringParameterToFunctionCallWalker'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { NoStringParameterToFunctionCallWalker } from "./utils/NoStringParameterToFunctionCallWalker"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.OptionallyTypedRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-string-based-set-interval', - type: 'maintainability', - description: 'Do not use the version of setInterval that accepts code as a string argument.', + ruleName: "no-string-based-set-interval", + type: "maintainability", + description: "Do not use the version of setInterval that accepts code as a string argument.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95, 676, 242, 116' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95, 676, 242, 116" }; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithProgram(sourceFile, undefined); } public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program | undefined): Lint.RuleFailure[] { - const walker : Lint.RuleWalker = new NoStringParameterToFunctionCallWalker( - sourceFile , 'setInterval', this.getOptions(), program - ); + const walker: Lint.RuleWalker = new NoStringParameterToFunctionCallWalker(sourceFile, "setInterval", this.getOptions(), program); return this.applyWithWalker(walker); } diff --git a/src/noStringBasedSetTimeoutRule.ts b/src/noStringBasedSetTimeoutRule.ts index 73063af4d..bc4de6fce 100644 --- a/src/noStringBasedSetTimeoutRule.ts +++ b/src/noStringBasedSetTimeoutRule.ts @@ -1,34 +1,31 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {NoStringParameterToFunctionCallWalker} from './utils/NoStringParameterToFunctionCallWalker'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { NoStringParameterToFunctionCallWalker } from "./utils/NoStringParameterToFunctionCallWalker"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.OptionallyTypedRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-string-based-set-timeout', - type: 'maintainability', - description: 'Do not use the version of setTimeout that accepts code as a string argument.', + ruleName: "no-string-based-set-timeout", + type: "maintainability", + description: "Do not use the version of setTimeout that accepts code as a string argument.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95, 676, 242, 116' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95, 676, 242, 116" }; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithProgram(sourceFile, undefined); } - public applyWithProgram(sourceFile : ts.SourceFile, program : ts.Program | undefined): Lint.RuleFailure[] { - const walker : Lint.RuleWalker = new NoStringParameterToFunctionCallWalker( - sourceFile , 'setTimeout', this.getOptions(), program - ); + public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program | undefined): Lint.RuleFailure[] { + const walker: Lint.RuleWalker = new NoStringParameterToFunctionCallWalker(sourceFile, "setTimeout", this.getOptions(), program); return this.applyWithWalker(walker); } } diff --git a/src/noSuspiciousCommentRule.ts b/src/noSuspiciousCommentRule.ts index 0741d18c1..a0db4953b 100644 --- a/src/noSuspiciousCommentRule.ts +++ b/src/noSuspiciousCommentRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {forEachTokenWithTrivia} from 'tsutils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { forEachTokenWithTrivia } from "tsutils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Suspicious comment found: '; -const SUSPICIOUS_WORDS = ['BUG', 'HACK', 'FIXME', 'LATER', 'LATER2', 'TODO']; +const FAILURE_STRING: string = "Suspicious comment found: "; +const SUSPICIOUS_WORDS = ["BUG", "HACK", "FIXME", "LATER", "LATER2", "TODO"]; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-suspicious-comment', - type: 'maintainability', - description: `Do not use suspicious comments, such as ${SUSPICIOUS_WORDS.join(', ')}`, + ruleName: "no-suspicious-comment", + type: "maintainability", + description: `Do not use suspicious comments, such as ${SUSPICIOUS_WORDS.join(", ")}`, options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '546' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "546" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,11 +29,9 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoSuspiciousCommentRuleWalker extends Lint.RuleWalker { - public visitSourceFile(node: ts.SourceFile) { forEachTokenWithTrivia(node, (text, tokenSyntaxKind, range) => { - if (tokenSyntaxKind === ts.SyntaxKind.SingleLineCommentTrivia || - tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia) { + if (tokenSyntaxKind === ts.SyntaxKind.SingleLineCommentTrivia || tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia) { this.scanCommentForSuspiciousWords(range.pos, text.substring(range.pos, range.end)); } }); @@ -47,8 +44,8 @@ class NoSuspiciousCommentRuleWalker extends Lint.RuleWalker { } private scanCommentForSuspiciousWord(suspiciousWord: string, commentText: string, startPosition: number) { - const regexExactCaseNoColon = new RegExp('\\b' + suspiciousWord + '\\b'); - const regexCaseInsensistiveWithColon = new RegExp('\\b' + suspiciousWord + '\\b\:', 'i'); + const regexExactCaseNoColon = new RegExp("\\b" + suspiciousWord + "\\b"); + const regexCaseInsensistiveWithColon = new RegExp("\\b" + suspiciousWord + "\\b:", "i"); if (regexExactCaseNoColon.test(commentText) || regexCaseInsensistiveWithColon.test(commentText)) { this.foundSuspiciousComment(startPosition, commentText, suspiciousWord); } diff --git a/src/noTypeofUndefinedRule.ts b/src/noTypeofUndefinedRule.ts index e9d952888..b7510a115 100644 --- a/src/noTypeofUndefinedRule.ts +++ b/src/noTypeofUndefinedRule.ts @@ -1,26 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Avoid typeof x === \'undefined\' comparisons. Prefer x == undefined or x === undefined: '; +const FAILURE_STRING: string = "Avoid typeof x === 'undefined' comparisons. Prefer x == undefined or x === undefined: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-typeof-undefined', - type: 'maintainability', - description: 'Do not use the idiom typeof `x === \'undefined\'`. You can safely use the simpler x === undefined ' + - 'or perhaps x == null if you want to check for either null or undefined.', + ruleName: "no-typeof-undefined", + type: "maintainability", + description: + "Do not use the idiom typeof `x === 'undefined'`. You can safely use the simpler x === undefined " + + "or perhaps x == null if you want to check for either null or undefined.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -29,11 +29,11 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoTypeofUndefinedRuleWalker extends Lint.RuleWalker { - protected visitBinaryExpression(node: ts.BinaryExpression): void { - if ((this.isUndefinedString(node.left) && this.isTypeOfExpression(node.right)) - || this.isUndefinedString(node.right) && this.isTypeOfExpression(node.left)) { - + if ( + (this.isUndefinedString(node.left) && this.isTypeOfExpression(node.right)) || + (this.isUndefinedString(node.right) && this.isTypeOfExpression(node.left)) + ) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING + node.getText()); } super.visitBinaryExpression(node); @@ -45,7 +45,7 @@ class NoTypeofUndefinedRuleWalker extends Lint.RuleWalker { private isUndefinedString(node: ts.Node): boolean { if (node.kind === ts.SyntaxKind.StringLiteral) { - if ((node).text === 'undefined') { + if ((node).text === "undefined") { return true; } } diff --git a/src/noUnexternalizedStringsRule.ts b/src/noUnexternalizedStringsRule.ts index f6d433fd5..d263460aa 100644 --- a/src/noUnexternalizedStringsRule.ts +++ b/src/noUnexternalizedStringsRule.ts @@ -1,23 +1,22 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unexternalized-strings', - type: 'maintainability', - description: 'Ensures that double quoted strings are passed to a localize call to provide proper strings for different locales', + ruleName: "no-unexternalized-strings", + type: "maintainability", + description: "Ensures that double quoted strings are passed to a localize call to provide proper strings for different locales", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Configurable', - recommendation: 'false, // the VS Code team has a specific localization process that this rule enforces' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Configurable", + recommendation: "false, // the VS Code team has a specific localization process that this rule enforces" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -36,7 +35,7 @@ interface UnexternalizedStringsOptions { } class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker { - private static readonly SINGLE_QUOTE: string = '\''; + private static readonly SINGLE_QUOTE: string = "'"; private readonly signatures: Map; private readonly messageIndex: number | undefined; @@ -54,10 +53,10 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker { const first: UnexternalizedStringsOptions = options && Array.isArray(options) && options.length > 0 ? options[0] : undefined; if (first) { if (Array.isArray(first.signatures)) { - first.signatures.forEach((signature: string) => this.signatures[signature] = true); + first.signatures.forEach((signature: string) => (this.signatures[signature] = true)); } if (Array.isArray(first.ignores)) { - first.ignores.forEach((ignore: string) => this.ignores[ignore] = true); + first.ignores.forEach((ignore: string) => (this.ignores[ignore] = true)); } if (first.messageIndex !== undefined) { this.messageIndex = first.messageIndex; @@ -73,8 +72,11 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker { private checkStringLiteral(node: ts.StringLiteral): void { const text = node.getText(); // The string literal is enclosed in single quotes. Treat as OK. - if (text.length >= 2 && text[0] === NoUnexternalizedStringsRuleWalker.SINGLE_QUOTE - && text[text.length - 1] === NoUnexternalizedStringsRuleWalker.SINGLE_QUOTE) { + if ( + text.length >= 2 && + text[0] === NoUnexternalizedStringsRuleWalker.SINGLE_QUOTE && + text[text.length - 1] === NoUnexternalizedStringsRuleWalker.SINGLE_QUOTE + ) { return; } const info = this.findDescribingParent(node); @@ -91,36 +93,51 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker { return; } // We have a string that is a direct argument into the localize call. - const messageArg = callInfo.argIndex === this.messageIndex - ? callInfo.callExpression.arguments[this.messageIndex] - : undefined; + const messageArg = callInfo.argIndex === this.messageIndex ? callInfo.callExpression.arguments[this.messageIndex] : undefined; if (messageArg && messageArg !== node) { this.addFailureAt( - node.getStart(), node.getWidth(), - `Message argument to '${callInfo.callExpression.expression.getText()}' must be a string literal.`); + node.getStart(), + node.getWidth(), + `Message argument to '${callInfo.callExpression.expression.getText()}' must be a string literal.` + ); return; } } - private findDescribingParent(node: ts.Node): - { callInfo?: { callExpression: ts.CallExpression, argIndex: number }, ignoreUsage?: boolean; } | undefined { + private findDescribingParent( + node: ts.Node + ): { callInfo?: { callExpression: ts.CallExpression; argIndex: number }; ignoreUsage?: boolean } | undefined { const kinds = ts.SyntaxKind; - while ((node.parent !== undefined)) { + while (node.parent !== undefined) { const parent: ts.Node = node.parent; const kind = parent.kind; if (kind === kinds.CallExpression) { const callExpression = parent; - return { callInfo: { callExpression: callExpression, argIndex: callExpression.arguments.indexOf(node) }}; + return { + callInfo: { + callExpression: callExpression, + argIndex: callExpression.arguments.indexOf(node) + } + }; } else if (kind === kinds.ImportEqualsDeclaration || kind === kinds.ImportDeclaration || kind === kinds.ExportDeclaration) { return { ignoreUsage: true }; - } else if (kind === kinds.VariableDeclaration || kind === kinds.FunctionDeclaration || kind === kinds.PropertyDeclaration - || kind === kinds.MethodDeclaration || kind === kinds.VariableDeclarationList || kind === kinds.InterfaceDeclaration - || kind === kinds.ClassDeclaration || kind === kinds.EnumDeclaration || kind === kinds.ModuleDeclaration - || kind === kinds.TypeAliasDeclaration || kind === kinds.SourceFile) { - return undefined; + } else if ( + kind === kinds.VariableDeclaration || + kind === kinds.FunctionDeclaration || + kind === kinds.PropertyDeclaration || + kind === kinds.MethodDeclaration || + kind === kinds.VariableDeclarationList || + kind === kinds.InterfaceDeclaration || + kind === kinds.ClassDeclaration || + kind === kinds.EnumDeclaration || + kind === kinds.ModuleDeclaration || + kind === kinds.TypeAliasDeclaration || + kind === kinds.SourceFile + ) { + return undefined; } node = parent; } return undefined; } -} \ No newline at end of file +} diff --git a/src/noUnnecessaryBindRule.ts b/src/noUnnecessaryBindRule.ts index 816b09c92..0d46f9979 100644 --- a/src/noUnnecessaryBindRule.ts +++ b/src/noUnnecessaryBindRule.ts @@ -1,38 +1,55 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unnecessary-bind', - type: 'maintainability', - description: 'Do not bind `this` as the context for a function literal or lambda expression.', + ruleName: "no-unnecessary-bind", + type: "maintainability", + description: "Do not bind `this` as the context for a function literal or lambda expression.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; - public static FAILURE_FUNCTION_WITH_BIND: string = 'Binding function literal with \'this\' context. Use lambdas instead'; - public static FAILURE_ARROW_WITH_BIND: string = 'Binding lambda with \'this\' context. Lambdas already have \'this\' bound'; + public static FAILURE_FUNCTION_WITH_BIND: string = "Binding function literal with 'this' context. Use lambdas instead"; + public static FAILURE_ARROW_WITH_BIND: string = "Binding lambda with 'this' context. Lambdas already have 'this' bound"; public static UNDERSCORE_BINARY_FUNCTION_NAMES: string[] = [ - 'all', 'any', 'collect', 'countBy', 'detect', 'each', - 'every', 'filter', 'find', 'forEach', 'groupBy', 'indexBy', - 'map', 'max', 'max', 'min', 'partition', 'reject', - 'select', 'some', 'sortBy', 'times', 'uniq', 'unique' - ]; - public static UNDERSCORE_TERNARY_FUNCTION_NAMES: string[] = [ - 'foldl', 'foldr', 'inject', 'reduce', 'reduceRight' + "all", + "any", + "collect", + "countBy", + "detect", + "each", + "every", + "filter", + "find", + "forEach", + "groupBy", + "indexBy", + "map", + "max", + "max", + "min", + "partition", + "reject", + "select", + "some", + "sortBy", + "times", + "uniq", + "unique" ]; + public static UNDERSCORE_TERNARY_FUNCTION_NAMES: string[] = ["foldl", "foldr", "inject", "reduce", "reduceRight"]; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoUnnecessaryBindRuleWalker(sourceFile, this.getOptions())); @@ -42,25 +59,29 @@ export class Rule extends Lint.Rules.AbstractRule { class NoUnnecessaryBindRuleWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { const analyzers: CallAnalyzer[] = [ - new TypeScriptFunctionAnalyzer(), new UnderscoreStaticAnalyzer(), new UnderscoreInstanceAnalyzer() + new TypeScriptFunctionAnalyzer(), + new UnderscoreStaticAnalyzer(), + new UnderscoreInstanceAnalyzer() ]; - analyzers.forEach((analyzer: CallAnalyzer): void => { - if (analyzer.canHandle(node)) { - const contextArgument = analyzer.getContextArgument(node); - const functionArgument = analyzer.getFunctionArgument(node); - if (contextArgument === undefined || functionArgument === undefined) { - return; - } - if (contextArgument.getText() === 'this') { - if (isArrowFunction(functionArgument)) { - this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_ARROW_WITH_BIND); - } else if (isFunctionLiteral(functionArgument)) { - this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_FUNCTION_WITH_BIND); + analyzers.forEach( + (analyzer: CallAnalyzer): void => { + if (analyzer.canHandle(node)) { + const contextArgument = analyzer.getContextArgument(node); + const functionArgument = analyzer.getFunctionArgument(node); + if (contextArgument === undefined || functionArgument === undefined) { + return; + } + if (contextArgument.getText() === "this") { + if (isArrowFunction(functionArgument)) { + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_ARROW_WITH_BIND); + } else if (isFunctionLiteral(functionArgument)) { + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_FUNCTION_WITH_BIND); + } } } } - }); + ); super.visitCallExpression(node); } } @@ -73,9 +94,11 @@ interface CallAnalyzer { class TypeScriptFunctionAnalyzer implements CallAnalyzer { public canHandle(node: ts.CallExpression): boolean { - return !!(AstUtils.getFunctionName(node) === 'bind' - && node.arguments.length === 1 - && node.expression.kind === ts.SyntaxKind.PropertyAccessExpression); + return !!( + AstUtils.getFunctionName(node) === "bind" && + node.arguments.length === 1 && + node.expression.kind === ts.SyntaxKind.PropertyAccessExpression + ); } public getContextArgument(node: ts.CallExpression): ts.Expression { @@ -89,10 +112,10 @@ class TypeScriptFunctionAnalyzer implements CallAnalyzer { class UnderscoreStaticAnalyzer implements CallAnalyzer { public canHandle(node: ts.CallExpression): boolean { - const isUnderscore: boolean = AstUtils.getFunctionTarget(node) === '_'; + const isUnderscore: boolean = AstUtils.getFunctionTarget(node) === "_"; if (isUnderscore) { const functionName: string = AstUtils.getFunctionName(node); - if (functionName === 'bind') { + if (functionName === "bind") { return node.arguments.length === 2; } } @@ -105,9 +128,9 @@ class UnderscoreStaticAnalyzer implements CallAnalyzer { return node.arguments[2]; } else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) { return node.arguments[3]; - } else if (functionName === 'sortedIndex') { + } else if (functionName === "sortedIndex") { return node.arguments[3]; - } else if (functionName === 'bind') { + } else if (functionName === "bind") { return node.arguments[1]; } return undefined; @@ -119,9 +142,9 @@ class UnderscoreStaticAnalyzer implements CallAnalyzer { return node.arguments[1]; } else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) { return node.arguments[1]; - } else if (functionName === 'sortedIndex') { + } else if (functionName === "sortedIndex") { return node.arguments[2]; - } else if (functionName === 'bind') { + } else if (functionName === "bind") { return node.arguments[0]; } return undefined; @@ -134,7 +157,7 @@ class UnderscoreInstanceAnalyzer implements CallAnalyzer { const propExpression: ts.PropertyAccessExpression = node.expression; if (propExpression.expression.kind === ts.SyntaxKind.CallExpression) { const call: ts.CallExpression = propExpression.expression; - return call.expression.getText() === '_'; + return call.expression.getText() === "_"; } } return false; @@ -146,7 +169,7 @@ class UnderscoreInstanceAnalyzer implements CallAnalyzer { return node.arguments[1]; } else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) { return node.arguments[2]; - } else if (functionName === 'sortedIndex') { + } else if (functionName === "sortedIndex") { return node.arguments[2]; } return undefined; @@ -158,12 +181,11 @@ class UnderscoreInstanceAnalyzer implements CallAnalyzer { return node.arguments[0]; } else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) { return node.arguments[0]; - } else if (functionName === 'sortedIndex') { + } else if (functionName === "sortedIndex") { return node.arguments[1]; } return undefined; } - } function isFunctionLiteral(expression: ts.Expression): boolean { @@ -184,4 +206,4 @@ function isArrowFunction(expression: ts.Expression): boolean { return isArrowFunction((expression).expression); } return false; -} \ No newline at end of file +} diff --git a/src/noUnnecessaryFieldInitializationRule.ts b/src/noUnnecessaryFieldInitializationRule.ts index d5d5218e8..571450b3a 100644 --- a/src/noUnnecessaryFieldInitializationRule.ts +++ b/src/noUnnecessaryFieldInitializationRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {AstUtils} from './utils/AstUtils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { AstUtils } from "./utils/AstUtils"; -const FAILURE_UNDEFINED_INIT: string = 'Unnecessary field initialization. Field explicitly initialized to undefined: '; -const FAILURE_UNDEFINED_DUPE: string = 'Unnecessary field initialization. Field value already initialized in declaration: '; +const FAILURE_UNDEFINED_INIT: string = "Unnecessary field initialization. Field explicitly initialized to undefined: "; +const FAILURE_UNDEFINED_DUPE: string = "Unnecessary field initialization. Field value already initialized in declaration: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unnecessary-field-initialization', - type: 'maintainability', - description: 'Do not unnecessarily initialize the fields of a class to values they already have.', + ruleName: "no-unnecessary-field-initialization", + type: "maintainability", + description: "Do not unnecessarily initialize the fields of a class to values they already have.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,18 +29,19 @@ export class Rule extends Lint.Rules.AbstractRule { } class UnnecessaryFieldInitializationRuleWalker extends Lint.RuleWalker { - private fieldInitializations: { [index: string]: string | undefined } = {}; protected visitClassDeclaration(node: ts.ClassDeclaration): void { this.fieldInitializations = {}; - node.members.forEach((member: ts.ClassElement): void => { - if (member.kind === ts.SyntaxKind.PropertyDeclaration) { - this.visitPropertyDeclaration(member); - } else if (member.kind === ts.SyntaxKind.Constructor) { - this.visitConstructorDeclaration(member); + node.members.forEach( + (member: ts.ClassElement): void => { + if (member.kind === ts.SyntaxKind.PropertyDeclaration) { + this.visitPropertyDeclaration(member); + } else if (member.kind === ts.SyntaxKind.Constructor) { + this.visitConstructorDeclaration(member); + } } - }); + ); this.fieldInitializations = {}; // do not call super.visitClass as a performance enhancement } @@ -49,7 +49,7 @@ class UnnecessaryFieldInitializationRuleWalker extends Lint.RuleWalker { protected visitPropertyDeclaration(node: ts.PropertyDeclaration): void { const initializer = node.initializer; if (node.name.kind === ts.SyntaxKind.Identifier) { - const fieldName: string = 'this.' + (node.name).getText(); + const fieldName: string = "this." + (node.name).getText(); if (initializer === undefined) { this.fieldInitializations[fieldName] = undefined; } else if (AstUtils.isConstant(initializer)) { @@ -66,41 +66,43 @@ class UnnecessaryFieldInitializationRuleWalker extends Lint.RuleWalker { protected visitConstructorDeclaration(node: ts.ConstructorDeclaration): void { if (node.body !== undefined) { - node.body.statements.forEach((statement: ts.Statement): void => { - if (statement.kind === ts.SyntaxKind.ExpressionStatement) { - const expression: ts.Expression = (statement).expression; - if (expression.kind === ts.SyntaxKind.BinaryExpression) { - const binaryExpression: ts.BinaryExpression = expression; + node.body.statements.forEach( + (statement: ts.Statement): void => { + if (statement.kind === ts.SyntaxKind.ExpressionStatement) { + const expression: ts.Expression = (statement).expression; + if (expression.kind === ts.SyntaxKind.BinaryExpression) { + const binaryExpression: ts.BinaryExpression = expression; - const property: ts.Expression = binaryExpression.left; - const propertyName: string = property.getText(); - // check to see if a field is being assigned in the constructor - if (Object.keys(this.fieldInitializations).indexOf(propertyName) > -1) { - if (AstUtils.isUndefined(binaryExpression.right)) { - // field is being assigned to undefined... create error if the field already has that value - if (Object.keys(this.fieldInitializations).indexOf(propertyName) > -1) { - // make sure the field was declared as undefined + const property: ts.Expression = binaryExpression.left; + const propertyName: string = property.getText(); + // check to see if a field is being assigned in the constructor + if (Object.keys(this.fieldInitializations).indexOf(propertyName) > -1) { + if (AstUtils.isUndefined(binaryExpression.right)) { + // field is being assigned to undefined... create error if the field already has that value + if (Object.keys(this.fieldInitializations).indexOf(propertyName) > -1) { + // make sure the field was declared as undefined + const fieldInitValue = this.fieldInitializations[propertyName]; + if (fieldInitValue === undefined) { + const start: number = property.getStart(); + const width: number = property.getWidth(); + this.addFailureAt(start, width, FAILURE_UNDEFINED_INIT + property.getText()); + } + } + } else if (AstUtils.isConstant(binaryExpression.right)) { + // field is being assigned a constant... create error if the field already has that value const fieldInitValue = this.fieldInitializations[propertyName]; - if (fieldInitValue === undefined) { - const start: number = property.getStart(); - const width: number = property.getWidth(); - this.addFailureAt(start, width, FAILURE_UNDEFINED_INIT + property.getText()); + if (fieldInitValue === binaryExpression.right.getText()) { + const start: number = binaryExpression.getStart(); + const width: number = binaryExpression.getWidth(); + const message: string = FAILURE_UNDEFINED_DUPE + binaryExpression.getText(); + this.addFailureAt(start, width, message); } } - } else if (AstUtils.isConstant(binaryExpression.right)) { - // field is being assigned a constant... create error if the field already has that value - const fieldInitValue = this.fieldInitializations[propertyName]; - if (fieldInitValue === binaryExpression.right.getText()) { - const start: number = binaryExpression.getStart(); - const width: number = binaryExpression.getWidth(); - const message: string = FAILURE_UNDEFINED_DUPE + binaryExpression.getText(); - this.addFailureAt(start, width, message); - } } } } } - }); + ); } } } diff --git a/src/noUnnecessaryLocalVariableRule.ts b/src/noUnnecessaryLocalVariableRule.ts index 6da884916..5e330740a 100644 --- a/src/noUnnecessaryLocalVariableRule.ts +++ b/src/noUnnecessaryLocalVariableRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; -import * as tsutils from 'tsutils'; +import * as ts from "typescript"; +import * as Lint from "tslint"; +import * as tsutils from "tsutils"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Unnecessary local variable: '; +const FAILURE_STRING: string = "Unnecessary local variable: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unnecessary-local-variable', - type: 'maintainability', - description: 'Do not declare a variable only to return it from the function on the next line.', + ruleName: "no-unnecessary-local-variable", + type: "maintainability", + description: "Do not declare a variable only to return it from the function on the next line.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '563, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "563, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -74,12 +73,13 @@ class UnnecessaryLocalVariableRuleWalker extends Lint.RuleWalker { const declaredVariableName: string = declaredVariableIdentifier.text; - if (returnedVariableName !== undefined - && declaredVariableName !== undefined - && returnedVariableName === declaredVariableName - && this.variableIsOnlyUsedOnce(declaredVariableIdentifier)) { - this.addFailureAt(nextToLastStatement.getStart(), nextToLastStatement.getWidth(), - FAILURE_STRING + returnedVariableName); + if ( + returnedVariableName !== undefined && + declaredVariableName !== undefined && + returnedVariableName === declaredVariableName && + this.variableIsOnlyUsedOnce(declaredVariableIdentifier) + ) { + this.addFailureAt(nextToLastStatement.getStart(), nextToLastStatement.getWidth(), FAILURE_STRING + returnedVariableName); } } diff --git a/src/noUnnecessaryOverrideRule.ts b/src/noUnnecessaryOverrideRule.ts index d48707f04..72e41cfae 100644 --- a/src/noUnnecessaryOverrideRule.ts +++ b/src/noUnnecessaryOverrideRule.ts @@ -1,25 +1,24 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Unnecessary method override. A method that only calls super can be removed: '; +const FAILURE_STRING: string = "Unnecessary method override. A method that only calls super can be removed: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unnecessary-override', - type: 'maintainability', - description: 'Do not write a method that only calls super() on the parent method with the same arguments.', + ruleName: "no-unnecessary-override", + type: "maintainability", + description: "Do not write a method that only calls super() on the parent method with the same arguments.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -62,7 +61,7 @@ class NoUnnecessaryOverrideRuleWalker extends Lint.RuleWalker { const allParameters: ReadonlyArray = node.parameters; /* tslint:disable:no-increment-decrement */ for (let i = 0; i < allParameters.length; i++) { - /* tslint:enable:no-increment-decrement */ + /* tslint:enable:no-increment-decrement */ const parameter: ts.ParameterDeclaration = allParameters[i]; const argument: ts.Expression = call.arguments[i]; if (argument.kind !== ts.SyntaxKind.Identifier) { @@ -129,6 +128,6 @@ class NoUnnecessaryOverrideRuleWalker extends Lint.RuleWalker { if (nameNode.kind === ts.SyntaxKind.Identifier) { return (nameNode).text; } - return ''; + return ""; } } diff --git a/src/noUnnecessarySemicolonsRule.ts b/src/noUnnecessarySemicolonsRule.ts index 2c3642480..5f72c12b0 100644 --- a/src/noUnnecessarySemicolonsRule.ts +++ b/src/noUnnecessarySemicolonsRule.ts @@ -1,24 +1,24 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING: string = 'unnecessary semi-colon'; + public static FAILURE_STRING: string = "unnecessary semi-colon"; public static metadata: ExtendedMetadata = { - ruleName: 'no-unnecessary-semicolons', - type: 'maintainability', - description: 'Remove unnecessary semicolons', + ruleName: "no-unnecessary-semicolons", + type: "maintainability", + description: "Remove unnecessary semicolons", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Whitespace', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Whitespace", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -27,7 +27,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoUnnecessarySemicolonsWalker extends Lint.RuleWalker { - protected visitNode(node: ts.Node): void { if (node.kind === ts.SyntaxKind.EmptyStatement) { this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING); diff --git a/src/noUnsupportedBrowserCodeRule.ts b/src/noUnsupportedBrowserCodeRule.ts index c3f65fcc2..f9abf84f3 100644 --- a/src/noUnsupportedBrowserCodeRule.ts +++ b/src/noUnsupportedBrowserCodeRule.ts @@ -1,14 +1,14 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {forEachTokenWithTrivia} from 'tsutils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { forEachTokenWithTrivia } from "tsutils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const UNSPECIFIED_BROWSER_VERSION: string = 'unspecified version'; -const JSDOC_BROWSERSPECIFIC: string = '@browserspecific'; -const COMMENT_BROWSERSPECIFIC: string = 'Browser Specific:'; -const FAILURE_BROWSER_STRING: string = 'Unsupported browser'; -const FAILURE_VERSION_STRING: string = 'Unsupported browser version'; +const UNSPECIFIED_BROWSER_VERSION: string = "unspecified version"; +const JSDOC_BROWSERSPECIFIC: string = "@browserspecific"; +const COMMENT_BROWSERSPECIFIC: string = "Browser Specific:"; +const FAILURE_BROWSER_STRING: string = "Unsupported browser"; +const FAILURE_VERSION_STRING: string = "Unsupported browser version"; interface BrowserVersion { name: string; @@ -17,19 +17,18 @@ interface BrowserVersion { } export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-unsupported-browser-code', - type: 'maintainability', - description: 'Avoid writing browser-specific code for unsupported browser versions', + ruleName: "no-unsupported-browser-code", + type: "maintainability", + description: "Avoid writing browser-specific code for unsupported browser versions", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -51,9 +50,9 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker { forEachTokenWithTrivia(node, (text, tokenSyntaxKind, range) => { let regex; if (tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia) { - regex = new RegExp(`${JSDOC_BROWSERSPECIFIC}\\s*(.*)`, 'gi'); + regex = new RegExp(`${JSDOC_BROWSERSPECIFIC}\\s*(.*)`, "gi"); } else if (tokenSyntaxKind === ts.SyntaxKind.SingleLineCommentTrivia) { - regex = new RegExp(`${COMMENT_BROWSERSPECIFIC}\\s*(.*)`, 'gi'); + regex = new RegExp(`${COMMENT_BROWSERSPECIFIC}\\s*(.*)`, "gi"); } else { return; } @@ -78,7 +77,7 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker { return { name: match[1].trim(), - comparison: match[2] || '=', + comparison: match[2] || "=", version: parseInt(match[3], 10) || UNSPECIFIED_BROWSER_VERSION }; } @@ -111,15 +110,15 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker { } switch (supportedBrowser.comparison) { - case '>': + case ">": return targetBrowser.version > supportedBrowser.version; - case '>=': + case ">=": return targetBrowser.version >= supportedBrowser.version; - case '<': + case "<": return targetBrowser.version < supportedBrowser.version; - case '<=': + case "<=": return targetBrowser.version <= supportedBrowser.version; - case '=': + case "=": return targetBrowser.version === supportedBrowser.version; default: return false; @@ -128,17 +127,9 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker { private findUnsupportedBrowserFailures(targetBrowser: BrowserVersion, startPos: number, length: number) { if (!this.isSupportedBrowser(targetBrowser)) { - this.addFailureAt( - startPos, - length, - `${FAILURE_BROWSER_STRING}: ${targetBrowser.name}` - ); + this.addFailureAt(startPos, length, `${FAILURE_BROWSER_STRING}: ${targetBrowser.name}`); } else if (!this.isSupportedBrowserVersion(targetBrowser)) { - this.addFailureAt( - startPos, - length, - `${FAILURE_VERSION_STRING}: ${targetBrowser.name} ${targetBrowser.version}` - ); + this.addFailureAt(startPos, length, `${FAILURE_VERSION_STRING}: ${targetBrowser.name} ${targetBrowser.version}`); } } } diff --git a/src/noUselessFilesRule.ts b/src/noUselessFilesRule.ts index 77a9de455..ddf08fe63 100644 --- a/src/noUselessFilesRule.ts +++ b/src/noUselessFilesRule.ts @@ -1,26 +1,25 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING_EMPTY: string = 'This file is empty and should be deleted.'; -const FAILURE_STRING_COMMENTS: string = 'This file only contains comments and should be deleted.'; +const FAILURE_STRING_EMPTY: string = "This file is empty and should be deleted."; +const FAILURE_STRING_COMMENTS: string = "This file only contains comments and should be deleted."; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-useless-files', - type: 'maintainability', - description: 'Locates files that only contain commented out code, whitespace characters, or have no content', + ruleName: "no-useless-files", + type: "maintainability", + description: "Locates files that only contain commented out code, whitespace characters, or have no content", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: false, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398' //Indicator of Poor Code Quality + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398" //Indicator of Poor Code Quality }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { diff --git a/src/noVarSelfRule.ts b/src/noVarSelfRule.ts index d382cb503..4a0fa8ecf 100644 --- a/src/noVarSelfRule.ts +++ b/src/noVarSelfRule.ts @@ -1,33 +1,32 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Assigning this reference to local variable: '; +const FAILURE_STRING: string = "Assigning this reference to local variable: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-var-self', - type: 'maintainability', - description: 'Do not use var self = this; instead, manage scope with arrow functions/lambdas.', + ruleName: "no-var-self", + type: "maintainability", + description: "Do not use var self = this; instead, manage scope with arrow functions/lambdas.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Deprecated', - recommendation: 'false,', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Deprecated", + recommendation: "false,", + commonWeaknessEnumeration: "398, 710" }; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn('Warning: no-var-self rule is deprecated. Replace your usage with the TSLint no-this-assignment rule.'); + console.warn("Warning: no-var-self rule is deprecated. Replace your usage with the TSLint no-this-assignment rule."); Rule.isWarningShown = true; } return this.applyWithWalker(new NoVarSelfRuleWalker(sourceFile, this.getOptions())); @@ -35,7 +34,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoVarSelfRuleWalker extends Lint.RuleWalker { - private readonly bannedVariableNames: RegExp = /.*/; // default is to ban everything constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { diff --git a/src/noWithStatementRule.ts b/src/noWithStatementRule.ts index b57ee5ed2..de39ae206 100644 --- a/src/noWithStatementRule.ts +++ b/src/noWithStatementRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'no-with-statement', - type: 'maintainability', - description: 'Do not use with statements. Assign the item to a new variable instead', + ruleName: "no-with-statement", + type: "maintainability", + description: "Do not use with statements. Assign the item to a new variable instead", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Correctness', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Correctness", + commonWeaknessEnumeration: "398, 710" }; - public static FAILURE_STRING: string = 'Forbidden with statement'; + public static FAILURE_STRING: string = "Forbidden with statement"; - public apply(sourceFile : ts.SourceFile): Lint.RuleFailure[] { + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoWithStatementWalker(sourceFile, this.getOptions())); } } diff --git a/src/nonLiteralFsPathRule.ts b/src/nonLiteralFsPathRule.ts index 87c2fcb29..3e3c05c1b 100644 --- a/src/nonLiteralFsPathRule.ts +++ b/src/nonLiteralFsPathRule.ts @@ -1,8 +1,8 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {AstUtils} from './utils/AstUtils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { AstUtils } from "./utils/AstUtils"; const PATH_PARAMETER_POSITIONS: { [key: string]: number[] } = { appendFile: [0], @@ -57,20 +57,19 @@ const PATH_PARAMETER_POSITIONS: { [key: string]: number[] } = { }; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'non-literal-fs-path', - type: 'functionality', - description: 'Detect calls to fs functions with a non literal filepath', + ruleName: "non-literal-fs-path", + type: "functionality", + description: "Detect calls to fs functions with a non literal filepath", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '22' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "22" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -79,16 +78,13 @@ export class Rule extends Lint.Rules.AbstractRule { } class NonLiteralFsPathRuleWalker extends Lint.RuleWalker { - protected visitCallExpression(node: ts.CallExpression): void { - if (AstUtils.getFunctionTarget(node) === 'fs' - && node.arguments.length > 0) { + if (AstUtils.getFunctionTarget(node) === "fs" && node.arguments.length > 0) { const functionName = AstUtils.getFunctionName(node); const positions = PATH_PARAMETER_POSITIONS[functionName]; - if (positions !== undefined - && node.arguments.length >= positions.length) { - positions.forEach((position) => { + if (positions !== undefined && node.arguments.length >= positions.length) { + positions.forEach(position => { const argument = node.arguments[position]; if (argument.kind !== ts.SyntaxKind.StringLiteral) { diff --git a/src/nonLiteralRequireRule.ts b/src/nonLiteralRequireRule.ts index 1b64a2d3a..7408065da 100644 --- a/src/nonLiteralRequireRule.ts +++ b/src/nonLiteralRequireRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {AstUtils} from './utils/AstUtils'; -import {Utils} from './utils/Utils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { AstUtils } from "./utils/AstUtils"; +import { Utils } from "./utils/Utils"; -const FAILURE_STRING: string = 'Non-literal (insecure) parameter passed to require(): '; +const FAILURE_STRING: string = "Non-literal (insecure) parameter passed to require(): "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'non-literal-require', - type: 'functionality', - description: 'Detect require includes that are not for string literals', + ruleName: "non-literal-require", + type: "functionality", + description: "Detect require includes that are not for string literals", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '95,676' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "95,676" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,19 +29,17 @@ export class Rule extends Lint.Rules.AbstractRule { } class NonLiteralRequireRuleWalker extends Lint.RuleWalker { - protected visitCallExpression(node: ts.CallExpression): void { - if (AstUtils.getFunctionName(node) === 'require' - && AstUtils.getFunctionTarget(node) === undefined - && node.arguments.length > 0) { - + if (AstUtils.getFunctionName(node) === "require" && AstUtils.getFunctionTarget(node) === undefined && node.arguments.length > 0) { if (node.arguments[0].kind === ts.SyntaxKind.ArrayLiteralExpression) { const arrayExp: ts.ArrayLiteralExpression = node.arguments[0]; - arrayExp.elements.forEach((initExpression: ts.Expression): void => { - if (initExpression.kind !== ts.SyntaxKind.StringLiteral) { - this.fail(initExpression); + arrayExp.elements.forEach( + (initExpression: ts.Expression): void => { + if (initExpression.kind !== ts.SyntaxKind.StringLiteral) { + this.fail(initExpression); + } } - }); + ); } else if (node.arguments[0].kind !== ts.SyntaxKind.StringLiteral) { this.fail(node.arguments[0]); } @@ -52,9 +49,8 @@ class NonLiteralRequireRuleWalker extends Lint.RuleWalker { private fail(expression: ts.Expression): void { const start: number = expression.getStart(); - const width: number = expression.getWidth(); - const message: string = FAILURE_STRING + Utils.trimTo(expression.getText(), 25); + const width: number = expression.getWidth(); + const message: string = FAILURE_STRING + Utils.trimTo(expression.getText(), 25); this.addFailureAt(start, width, message); - } } diff --git a/src/possibleTimingAttackRule.ts b/src/possibleTimingAttackRule.ts index 1b5d5339a..7a0a2e622 100644 --- a/src/possibleTimingAttackRule.ts +++ b/src/possibleTimingAttackRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {Utils} from './utils/Utils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { Utils } from "./utils/Utils"; -const FAILURE_STRING: string = 'Possible timing attack detected. Direct comparison found: '; +const FAILURE_STRING: string = "Possible timing attack detected. Direct comparison found: "; const SENSITIVE_VAR_NAME: RegExp = /^(password|secret|api|apiKey|token|auth|pass|hash)$/im; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'possible-timing-attack', - type: 'functionality', - description: 'Avoid timing attacks by not making direct comaprisons to sensitive data', + ruleName: "possible-timing-attack", + type: "functionality", + description: "Avoid timing attacks by not making direct comaprisons to sensitive data", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Security', - commonWeaknessEnumeration: '710,749' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Security", + commonWeaknessEnumeration: "710,749" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -30,16 +29,20 @@ export class Rule extends Lint.Rules.AbstractRule { } class PossibleTimingAttackRuleWalker extends Lint.RuleWalker { - protected visitBinaryExpression(node: ts.BinaryExpression): void { - if (node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken - || node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken - || node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken - || node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken) { - - if ((SENSITIVE_VAR_NAME.test(node.left.getText()) || SENSITIVE_VAR_NAME.test(node.right.getText())) - && node.left.getText() !== 'null' && node.right.getText() !== 'null' - && node.left.getText() !== 'undefined' && node.right.getText() !== 'undefined') { + if ( + node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken || + node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken || + node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken || + node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken + ) { + if ( + (SENSITIVE_VAR_NAME.test(node.left.getText()) || SENSITIVE_VAR_NAME.test(node.right.getText())) && + node.left.getText() !== "null" && + node.right.getText() !== "null" && + node.left.getText() !== "undefined" && + node.right.getText() !== "undefined" + ) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING + Utils.trimTo(node.getText(), 20)); } else { super.visitBinaryExpression(node); diff --git a/src/preferArrayLiteralRule.ts b/src/preferArrayLiteralRule.ts index eb88eb59a..7d47a3606 100644 --- a/src/preferArrayLiteralRule.ts +++ b/src/preferArrayLiteralRule.ts @@ -1,29 +1,28 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import { isObject } from './utils/TypeGuard'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { isObject } from "./utils/TypeGuard"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'prefer-array-literal', - type: 'maintainability', - description: 'Use array literal syntax when declaring or instantiating array types.', + ruleName: "prefer-array-literal", + type: "maintainability", + description: "Use array literal syntax when declaring or instantiating array types.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Clarity', - commonWeaknessEnumeration: '398, 710' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Clarity", + commonWeaknessEnumeration: "398, 710" }; - public static GENERICS_FAILURE_STRING: string = 'Replace generic-typed Array with array literal: '; - public static CONSTRUCTOR_FAILURE_STRING: string = 'Replace Array constructor with an array literal: '; + public static GENERICS_FAILURE_STRING: string = "Replace generic-typed Array with array literal: "; + public static CONSTRUCTOR_FAILURE_STRING: string = "Replace Array constructor with an array literal: "; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new NoGenericArrayWalker(sourceFile, this.getOptions())); @@ -31,21 +30,20 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoGenericArrayWalker extends Lint.RuleWalker { - private allowTypeParameters: boolean = false; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { super(sourceFile, options); this.getOptions().forEach((opt: unknown) => { if (isObject(opt)) { - this.allowTypeParameters = opt['allow-type-parameters'] === true; + this.allowTypeParameters = opt["allow-type-parameters"] === true; } }); } protected visitTypeReference(node: ts.TypeReferenceNode): void { if (this.allowTypeParameters === false) { - if ((node.typeName).text === 'Array') { + if ((node.typeName).text === "Array") { const failureString = Rule.GENERICS_FAILURE_STRING + node.getText(); this.addFailureAt(node.getStart(), node.getWidth(), failureString); } @@ -54,8 +52,8 @@ class NoGenericArrayWalker extends Lint.RuleWalker { } protected visitNewExpression(node: ts.NewExpression): void { - const functionName = AstUtils.getFunctionName(node); - if (functionName === 'Array') { + const functionName = AstUtils.getFunctionName(node); + if (functionName === "Array") { const failureString = Rule.CONSTRUCTOR_FAILURE_STRING + node.getText(); this.addFailureAt(node.getStart(), node.getWidth(), failureString); } diff --git a/src/preferTypeCastRule.ts b/src/preferTypeCastRule.ts index fa1a4eb97..d3e7f27c3 100644 --- a/src/preferTypeCastRule.ts +++ b/src/preferTypeCastRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { AstUtils } from './utils/AstUtils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_STRING: string = 'Found as-cast instead of a traditional type-cast. Please convert to a type-cast: '; +const FAILURE_STRING: string = "Found as-cast instead of a traditional type-cast. Please convert to a type-cast: "; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'prefer-type-cast', - type: 'maintainability', - description: 'Prefer the tradition type casts instead of the new \'as-cast\' syntax', + ruleName: "prefer-type-cast", + type: "maintainability", + description: "Prefer the tradition type casts instead of the new 'as-cast' syntax", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Configurable', - recommendation: 'true, // pick either type-cast format and use it consistently', - commonWeaknessEnumeration: '398, 710' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Configurable", + recommendation: "true, // pick either type-cast format and use it consistently", + commonWeaknessEnumeration: "398, 710" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { diff --git a/src/promiseMustCompleteRule.ts b/src/promiseMustCompleteRule.ts index 41758b155..40b342823 100644 --- a/src/promiseMustCompleteRule.ts +++ b/src/promiseMustCompleteRule.ts @@ -1,28 +1,28 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {AstUtils} from './utils/AstUtils'; -import {Utils} from './utils/Utils'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { AstUtils } from "./utils/AstUtils"; +import { Utils } from "./utils/Utils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'promise-must-complete', - type: 'maintainability', - description: 'When a Promise instance is created, then either the reject() or resolve() parameter must be ' + - 'called on it within all code branches in the scope.', + ruleName: "promise-must-complete", + type: "maintainability", + description: + "When a Promise instance is created, then either the reject() or resolve() parameter must be " + + "called on it within all code branches in the scope.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Opportunity for Excellence', - group: 'Correctness' + issueClass: "Non-SDL", + issueType: "Error", + severity: "Critical", + level: "Opportunity for Excellence", + group: "Correctness" }; - public static FAILURE_STRING: string = 'A Promise was found that appears to not have resolve or reject invoked on all code paths'; + public static FAILURE_STRING: string = "A Promise was found that appears to not have resolve or reject invoked on all code paths"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new PromiseAnalyzer(sourceFile, this.getOptions())); @@ -31,9 +31,12 @@ export class Rule extends Lint.Rules.AbstractRule { class PromiseAnalyzer extends Lint.RuleWalker { private isPromiseDeclaration(node: ts.NewExpression): boolean { - if (node.expression.kind === ts.SyntaxKind.Identifier - && node.expression.getText() === 'Promise' - && node.arguments !== undefined && node.arguments.length > 0) { + if ( + node.expression.kind === ts.SyntaxKind.Identifier && + node.expression.getText() === "Promise" && + node.arguments !== undefined && + node.arguments.length > 0 + ) { const firstArg: ts.Expression = node.arguments[0]; if (firstArg.kind === ts.SyntaxKind.ArrowFunction || firstArg.kind === ts.SyntaxKind.FunctionExpression) { return true; @@ -65,14 +68,14 @@ class PromiseAnalyzer extends Lint.RuleWalker { const functionBody = functionArgument.body; if (functionBody !== undefined) { - const competionIdentifiers : ts.Identifier[] = this.getCompletionIdentifiers(functionArgument); + const competionIdentifiers: ts.Identifier[] = this.getCompletionIdentifiers(functionArgument); this.validatePromiseUsage(node, functionBody, competionIdentifiers); } } super.visitNewExpression(node); } - private validatePromiseUsage(promiseInstantiation: ts.NewExpression, block: ts.Node, completionIdentifiers: ts.Identifier[]) : void { + private validatePromiseUsage(promiseInstantiation: ts.NewExpression, block: ts.Node, completionIdentifiers: ts.Identifier[]): void { const blockAnalyzer = new PromiseCompletionWalker(this.getSourceFile(), this.getOptions(), completionIdentifiers); blockAnalyzer.visitNode(block); if (!blockAnalyzer.isAlwaysCompleted()) { @@ -83,9 +86,9 @@ class PromiseAnalyzer extends Lint.RuleWalker { class PromiseCompletionWalker extends Lint.RuleWalker { private readonly completionIdentifiers: ts.Identifier[]; - private wasCompleted : boolean = false; - private allBranchesCompleted : boolean = true; // by default, there are no branches, so this is true - private hasBranches : boolean = false; + private wasCompleted: boolean = false; + private allBranchesCompleted: boolean = true; // by default, there are no branches, so this is true + private hasBranches: boolean = false; private readonly walkerOptions: Lint.IOptions; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, completionIdentifiers: ts.Identifier[]) { @@ -101,7 +104,7 @@ class PromiseCompletionWalker extends Lint.RuleWalker { } /* tslint:enable:no-unnecessary-override */ - public isAlwaysCompleted() : boolean { + public isAlwaysCompleted(): boolean { if (this.wasCompleted) { return true; // if the main code path completed then it doesn't matter what the child branches did } @@ -139,9 +142,12 @@ class PromiseCompletionWalker extends Lint.RuleWalker { } } - const referenceEscaped : boolean = Utils.exists(node.arguments, (argument: ts.Expression) : boolean => { - return this.isCompletionIdentifier(argument); - }); + const referenceEscaped: boolean = Utils.exists( + node.arguments, + (argument: ts.Expression): boolean => { + return this.isCompletionIdentifier(argument); + } + ); if (referenceEscaped) { this.wasCompleted = true; return; // this branch was completed, do not walk any more. @@ -171,23 +177,30 @@ class PromiseCompletionWalker extends Lint.RuleWalker { private getNonShadowedCompletionIdentifiers(declaration: ts.FunctionLikeDeclaration): ts.Identifier[] { const result: ts.Identifier[] = []; - this.completionIdentifiers.forEach((identifier: ts.Identifier): void => { - // if this identifier is not shadowed, then add it to result - const isShadowed: boolean = Utils.exists(declaration.parameters, (parameter: ts.ParameterDeclaration): boolean => { - return AstUtils.isSameIdentifer(identifier, parameter.name); - }); - if (!isShadowed) { - result.push(identifier); + this.completionIdentifiers.forEach( + (identifier: ts.Identifier): void => { + // if this identifier is not shadowed, then add it to result + const isShadowed: boolean = Utils.exists( + declaration.parameters, + (parameter: ts.ParameterDeclaration): boolean => { + return AstUtils.isSameIdentifer(identifier, parameter.name); + } + ); + if (!isShadowed) { + result.push(identifier); + } } - }); + ); return result; } private isCompletionIdentifier(sourceIdentifier: ts.Node): boolean { - return Utils.exists(this.completionIdentifiers, (identifier: ts.Identifier): boolean => { - return AstUtils.isSameIdentifer(sourceIdentifier, identifier); - }); - + return Utils.exists( + this.completionIdentifiers, + (identifier: ts.Identifier): boolean => { + return AstUtils.isSameIdentifer(sourceIdentifier, identifier); + } + ); } } diff --git a/src/reactA11yAnchorsRule.ts b/src/reactA11yAnchorsRule.ts index 51d9cbed6..e69c95a03 100644 --- a/src/reactA11yAnchorsRule.ts +++ b/src/reactA11yAnchorsRule.ts @@ -1,47 +1,38 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; - -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {Utils} from './utils/Utils'; -import {getImplicitRole} from './utils/getImplicitRole'; -import { - getJsxAttributesFromJsxElement, - getStringLiteral, - isEmpty -} from './utils/JsxAttribute'; -import { isObject } from './utils/TypeGuard'; - -export const OPTION_IGNORE_CASE: string = 'ignore-case'; -export const OPTION_IGNORE_WHITESPACE: string = 'ignore-whitespace'; - -const ROLE_STRING: string = 'role'; - -export const NO_HASH_FAILURE_STRING: string = - 'Do not use # as anchor href.'; -export const MISSING_HREF_FAILURE_STRING: string = - 'Do not leave href undefined or null'; +import * as ts from "typescript"; +import * as Lint from "tslint"; + +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { Utils } from "./utils/Utils"; +import { getImplicitRole } from "./utils/getImplicitRole"; +import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; +import { isObject } from "./utils/TypeGuard"; + +export const OPTION_IGNORE_CASE: string = "ignore-case"; +export const OPTION_IGNORE_WHITESPACE: string = "ignore-whitespace"; + +const ROLE_STRING: string = "role"; + +export const NO_HASH_FAILURE_STRING: string = "Do not use # as anchor href."; +export const MISSING_HREF_FAILURE_STRING: string = "Do not leave href undefined or null"; export const LINK_TEXT_TOO_SHORT_FAILURE_STRING: string = - 'Link text or the alt text of image in link should be at least 4 characters long. ' + - 'If you are not using element as anchor, please specify explicit role, e.g. role=\'button\''; + "Link text or the alt text of image in link should be at least 4 characters long. " + + "If you are not using element as anchor, please specify explicit role, e.g. role='button'"; export const UNIQUE_ALT_FAILURE_STRING: string = - 'Links with images and text content, the alt attribute should be unique to the text content or empty.'; -export const SAME_HREF_SAME_TEXT_FAILURE_STRING: string = - 'Links with the same HREF should have the same link text.'; -export const DIFFERENT_HREF_DIFFERENT_TEXT_FAILURE_STRING: string = - 'Links that point to different HREFs should have different link text.'; + "Links with images and text content, the alt attribute should be unique to the text content or empty."; +export const SAME_HREF_SAME_TEXT_FAILURE_STRING: string = "Links with the same HREF should have the same link text."; +export const DIFFERENT_HREF_DIFFERENT_TEXT_FAILURE_STRING: string = "Links that point to different HREFs should have different link text."; export const ACCESSIBLE_HIDDEN_CONTENT_FAILURE_STRING: string = - 'Link content can not be hidden for screen-readers by using aria-hidden attribute.'; + "Link content can not be hidden for screen-readers by using aria-hidden attribute."; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-anchors', - type: 'functionality', - description: 'For accessibility of your website, anchor elements must have a href different from # and a text longer than 4.', + ruleName: "react-a11y-anchors", + type: "functionality", + description: "For accessibility of your website, anchor elements must have a href different from # and a text longer than 4.", options: { - type: 'array', + type: "array", items: { - type: 'string', + type: "string", enum: [OPTION_IGNORE_CASE, OPTION_IGNORE_WHITESPACE] }, minLength: 0, @@ -54,11 +45,11 @@ export class Rule extends Lint.Rules.AbstractRule { * \`{"${OPTION_IGNORE_WHITESPACE}": "all"}\` ignore differences in all whitespace. `, typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -76,7 +67,7 @@ export class Rule extends Lint.Rules.AbstractRule { class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { private ignoreCase: boolean = false; - private ignoreWhitespace: string = ''; + private ignoreWhitespace: string = ""; private readonly anchorInfoList: IAnchorInfo[] = []; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { @@ -86,7 +77,7 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { private parseOptions(): void { this.getOptions().forEach((opt: unknown) => { - if (typeof opt === 'string' && opt === OPTION_IGNORE_CASE) { + if (typeof opt === "string" && opt === OPTION_IGNORE_CASE) { this.ignoreCase = true; } @@ -102,28 +93,38 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { while (this.anchorInfoList.length > 0) { const current: IAnchorInfo = this.anchorInfoList.shift()!; - this.anchorInfoList.forEach((anchorInfo: IAnchorInfo): void => { - if (current.href && - current.href === anchorInfo.href && - !this.compareAnchorsText(current, anchorInfo) && - !Utils.contains(sameHrefDifferentTexts, anchorInfo)) { - - // Same href - different text... - sameHrefDifferentTexts.push(anchorInfo); - this.addFailureAt(anchorInfo.start, anchorInfo.width, - SAME_HREF_SAME_TEXT_FAILURE_STRING + this.firstPosition(current)); + this.anchorInfoList.forEach( + (anchorInfo: IAnchorInfo): void => { + if ( + current.href && + current.href === anchorInfo.href && + !this.compareAnchorsText(current, anchorInfo) && + !Utils.contains(sameHrefDifferentTexts, anchorInfo) + ) { + // Same href - different text... + sameHrefDifferentTexts.push(anchorInfo); + this.addFailureAt( + anchorInfo.start, + anchorInfo.width, + SAME_HREF_SAME_TEXT_FAILURE_STRING + this.firstPosition(current) + ); + } + + if ( + current.href !== anchorInfo.href && + this.compareAnchorsText(current, anchorInfo) && + !Utils.contains(differentHrefSameText, anchorInfo) + ) { + // Different href - same text... + differentHrefSameText.push(anchorInfo); + this.addFailureAt( + anchorInfo.start, + anchorInfo.width, + DIFFERENT_HREF_DIFFERENT_TEXT_FAILURE_STRING + this.firstPosition(current) + ); + } } - - if (current.href !== anchorInfo.href && - this.compareAnchorsText(current, anchorInfo) && - !Utils.contains(differentHrefSameText, anchorInfo)) { - - // Different href - same text... - differentHrefSameText.push(anchorInfo); - this.addFailureAt(anchorInfo.start, anchorInfo.width, - DIFFERENT_HREF_DIFFERENT_TEXT_FAILURE_STRING + this.firstPosition(current)); - } - }); + ); } } @@ -140,27 +141,28 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { altText2 = altText2.toLowerCase(); } - if (this.ignoreWhitespace === 'trim') { + if (this.ignoreWhitespace === "trim") { text1 = text1.trim(); text2 = text2.trim(); altText1 = altText1.trim(); altText2 = altText2.trim(); } - if (this.ignoreWhitespace === 'all') { + if (this.ignoreWhitespace === "all") { const regex: RegExp = /\s/g; - text1 = text1.replace(regex, ''); - text2 = text2.replace(regex, ''); - altText1 = altText1.replace(regex, ''); - altText2 = altText2.replace(regex, ''); + text1 = text1.replace(regex, ""); + text2 = text2.replace(regex, ""); + altText1 = altText1.replace(regex, ""); + altText2 = altText2.replace(regex, ""); } return text1 === text2 && altText1 === altText2; } private firstPosition(anchorInfo: IAnchorInfo): string { - const startPosition: ts.LineAndCharacter = - this.createFailure(anchorInfo.start, anchorInfo.width, '').getStartPosition().getLineAndCharacter(); + const startPosition: ts.LineAndCharacter = this.createFailure(anchorInfo.start, anchorInfo.width, "") + .getStartPosition() + .getLineAndCharacter(); // Position is zero based - add 1... const character: number = startPosition.character + 1; @@ -180,11 +182,11 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { } private validateAnchor(parent: ts.Node, openingElement: ts.JsxOpeningLikeElement): void { - if (openingElement.tagName.getText() === 'a') { - const hrefAttribute = this.getAttribute(openingElement, 'href'); + if (openingElement.tagName.getText() === "a") { + const hrefAttribute = this.getAttribute(openingElement, "href"); const anchorInfo: IAnchorInfo = { - href: hrefAttribute ? getStringLiteral(hrefAttribute) || '' : '', + href: hrefAttribute ? getStringLiteral(hrefAttribute) || "" : "", text: this.anchorText(parent), altText: this.imageAlt(parent), hasAriaHiddenCount: this.jsxElementAriaHidden(parent), @@ -196,7 +198,7 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { this.addFailureAt(anchorInfo.start, anchorInfo.width, MISSING_HREF_FAILURE_STRING); } - if (anchorInfo.href === '#') { + if (anchorInfo.href === "#") { this.addFailureAt(anchorInfo.start, anchorInfo.width, NO_HASH_FAILURE_STRING); } @@ -211,11 +213,7 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { const anchorInfoTextLength: number = anchorInfo.text ? anchorInfo.text.length : 0; const anchorImageAltTextLength: number = anchorInfo.altText ? anchorInfo.altText.length : 0; - if ( - this.anchorRole(openingElement) === 'link' && - anchorInfoTextLength < 4 && - anchorImageAltTextLength < 4 - ) { + if (this.anchorRole(openingElement) === "link" && anchorInfoTextLength < 4 && anchorImageAltTextLength < 4) { this.addFailureAt(anchorInfo.start, anchorInfo.width, LINK_TEXT_TOO_SHORT_FAILURE_STRING); } @@ -232,14 +230,16 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { * Return a string which contains literal text and text in 'alt' attribute. */ private anchorText(root: ts.Node | undefined, isChild: boolean = false): string { - let title: string = ''; + let title: string = ""; if (root === undefined) { return title; } else if (root.kind === ts.SyntaxKind.JsxElement) { const jsxElement: ts.JsxElement = root; - jsxElement.children.forEach((child: ts.JsxChild): void => { - title += this.anchorText(child, true); - }); + jsxElement.children.forEach( + (child: ts.JsxChild): void => { + title += this.anchorText(child, true); + } + ); } else if (root.kind === ts.SyntaxKind.JsxText) { const jsxText: ts.JsxText = root; title += jsxText.getText(); @@ -251,11 +251,11 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { title += this.anchorText(expression.expression); } else if (isChild && root.kind === ts.SyntaxKind.JsxSelfClosingElement) { const jsxSelfClosingElement = root; - if (jsxSelfClosingElement.tagName.getText() !== 'img') { - title += ''; + if (jsxSelfClosingElement.tagName.getText() !== "img") { + title += ""; } } else if (root.kind !== ts.SyntaxKind.JsxSelfClosingElement) { - title += ''; + title += ""; } return title; @@ -270,23 +270,25 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { } private imageAltAttribute(openingElement: ts.JsxOpeningLikeElement): string { - if (openingElement.tagName.getText() === 'img') { - const altAttribute = getStringLiteral(this.getAttribute(openingElement, 'alt')); - return altAttribute === undefined ? '' : altAttribute; + if (openingElement.tagName.getText() === "img") { + const altAttribute = getStringLiteral(this.getAttribute(openingElement, "alt")); + return altAttribute === undefined ? "" : altAttribute; } - return ''; + return ""; } private imageAlt(root: ts.Node): string { - let altText: string = ''; + let altText: string = ""; if (root.kind === ts.SyntaxKind.JsxElement) { const jsxElement: ts.JsxElement = root; altText += this.imageAltAttribute(jsxElement.openingElement); - jsxElement.children.forEach((child: ts.JsxChild): void => { - altText += this.imageAlt(child); - }); + jsxElement.children.forEach( + (child: ts.JsxChild): void => { + altText += this.imageAlt(child); + } + ); } if (root.kind === ts.SyntaxKind.JsxSelfClosingElement) { @@ -298,7 +300,7 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { } private ariaHiddenAttribute(openingElement: ts.JsxOpeningLikeElement): boolean { - return this.getAttribute(openingElement, 'aria-hidden') === undefined; + return this.getAttribute(openingElement, "aria-hidden") === undefined; } private jsxElementAriaHidden(root: ts.Node): number { @@ -308,9 +310,11 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker { const jsxElement: ts.JsxElement = root; hasAriaHiddenCount += this.ariaHiddenAttribute(jsxElement.openingElement) ? 0 : 1; - jsxElement.children.forEach((child: ts.JsxChild): void => { - hasAriaHiddenCount += this.jsxElementAriaHidden(child); - }); + jsxElement.children.forEach( + (child: ts.JsxChild): void => { + hasAriaHiddenCount += this.jsxElementAriaHidden(child); + } + ); } if (root.kind === ts.SyntaxKind.JsxSelfClosingElement) { diff --git a/src/reactA11yAriaUnsupportedElementsRule.ts b/src/reactA11yAriaUnsupportedElementsRule.ts index e222e6b4c..c2d6e344d 100644 --- a/src/reactA11yAriaUnsupportedElementsRule.ts +++ b/src/reactA11yAriaUnsupportedElementsRule.ts @@ -1,37 +1,39 @@ /** * Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes. */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getJsxAttributesFromJsxElement} from './utils/JsxAttribute'; -import { IDom } from './utils/attributes/IDom'; -import { IAria } from './utils/attributes/IAria'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getJsxAttributesFromJsxElement } from "./utils/JsxAttribute"; +import { IDom } from "./utils/attributes/IDom"; +import { IAria } from "./utils/attributes/IAria"; // tslint:disable:no-require-imports no-var-requires -const DOM_SCHEMA: { [key: string]: IDom } = require('./utils/attributes/domSchema.json'); -const ARIA_SCHEMA: { [key: string]: IAria } = require('./utils/attributes/ariaSchema.json'); +const DOM_SCHEMA: { [key: string]: IDom } = require("./utils/attributes/domSchema.json"); +const ARIA_SCHEMA: { [key: string]: IAria } = require("./utils/attributes/ariaSchema.json"); // tslint:enable:no-require-imports no-var-requires export function getFailureString(tagName: string, ariaAttributeNames: string[]): string { - return `This element ${tagName} does not support ARIA roles, states and properties. ` - + `Try removing attribute(s): ${ariaAttributeNames.join(', ')}.`; + return ( + `This element ${tagName} does not support ARIA roles, states and properties. ` + + `Try removing attribute(s): ${ariaAttributeNames.join(", ")}.` + ); } export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-aria-unsupported-elements', - type: 'maintainability', - description: 'Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes.', + ruleName: "react-a11y-aria-unsupported-elements", + type: "maintainability", + description: "Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -59,18 +61,15 @@ class ReactA11yAriaUnsupportedElementsWalker extends Lint.RuleWalker { return; } - const supportAria: boolean = DOM_SCHEMA[tagName].supportAria !== undefined - ? DOM_SCHEMA[tagName].supportAria - : false; + const supportAria: boolean = DOM_SCHEMA[tagName].supportAria !== undefined ? DOM_SCHEMA[tagName].supportAria : false; if (supportAria) { return; } - const checkAttributeNames: string[] = Object.keys(ARIA_SCHEMA).concat('role'); + const checkAttributeNames: string[] = Object.keys(ARIA_SCHEMA).concat("role"); const attributes: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(node); - const invalidAttributeNames: string[] = - checkAttributeNames.filter((attributeName: string): boolean => !!attributes[attributeName]); + const invalidAttributeNames: string[] = checkAttributeNames.filter((attributeName: string): boolean => !!attributes[attributeName]); if (invalidAttributeNames.length > 0) { const message: string = getFailureString(tagName, invalidAttributeNames); diff --git a/src/reactA11yEventHasRoleRule.ts b/src/reactA11yEventHasRoleRule.ts index f8868db4e..0fbfd9d8f 100644 --- a/src/reactA11yEventHasRoleRule.ts +++ b/src/reactA11yEventHasRoleRule.ts @@ -1,34 +1,51 @@ /** * Elements with event handlers must have role attribute. */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; -import { getJsxAttributesFromJsxElement } from './utils/JsxAttribute'; -import { getImplicitRole } from './utils/getImplicitRole'; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { IDom } from './utils/attributes/IDom'; +import * as ts from "typescript"; +import * as Lint from "tslint"; +import { getJsxAttributesFromJsxElement } from "./utils/JsxAttribute"; +import { getImplicitRole } from "./utils/getImplicitRole"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { IDom } from "./utils/attributes/IDom"; // tslint:disable-next-line:no-require-imports no-var-requires -const DOM_SCHEMA: { [key: string]: IDom } = require('./utils/attributes/domSchema.json'); -const FAILURE_STRING: string = 'Elements with event handlers must have role attribute.'; -const ROLE_STRING: string = 'role'; -const TARGET_EVENTS: string[] = ['click', 'keyup', 'keydown', 'keypress', 'mousedown', 'mouseup', - 'mousemove', 'mouseout', 'mouseover', 'onclick', 'onkeyup', 'onkeydown', 'onkeypress', 'onmousedown', - 'onmouseup', 'onmousemove', 'onmouseout', 'onmouseover']; +const DOM_SCHEMA: { [key: string]: IDom } = require("./utils/attributes/domSchema.json"); +const FAILURE_STRING: string = "Elements with event handlers must have role attribute."; +const ROLE_STRING: string = "role"; +const TARGET_EVENTS: string[] = [ + "click", + "keyup", + "keydown", + "keypress", + "mousedown", + "mouseup", + "mousemove", + "mouseout", + "mouseover", + "onclick", + "onkeyup", + "onkeydown", + "onkeypress", + "onmousedown", + "onmouseup", + "onmousemove", + "onmouseout", + "onmouseover" +]; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-event-has-role', - type: 'maintainability', - description: 'Elements with event handlers must have role attribute.', + ruleName: "react-a11y-event-has-role", + type: "maintainability", + description: "Elements with event handlers must have role attribute.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -61,11 +78,7 @@ class ReactA11yEventHasRoleWalker extends Lint.RuleWalker { const hasAriaRole: boolean = !!attributes[ROLE_STRING] || !!getImplicitRole(node); if (events.length > 0 && !hasAriaRole) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - FAILURE_STRING - ); + this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING); } } } diff --git a/src/reactA11yImageButtonHasAltRule.ts b/src/reactA11yImageButtonHasAltRule.ts index dd1ffdd80..4db6b1aea 100644 --- a/src/reactA11yImageButtonHasAltRule.ts +++ b/src/reactA11yImageButtonHasAltRule.ts @@ -1,31 +1,31 @@ /** * Enforce that inputs element with type="image" must have alt attribute. */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from './utils/JsxAttribute'; -import { isStringLiteral } from './utils/TypeGuard'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; +import { isStringLiteral } from "./utils/TypeGuard"; const NO_ALT_ATTRIBUTE_FAILURE_STRING: string = 'Inputs element with type="image" must have alt attribute.'; const EMPTY_ALT_ATTRIBUTE_FAILURE_STRING: string = 'Inputs element with type="image" must have non-empty alt attribute.'; -const TYPE_STRING: string = 'type'; -const ALT_STRING: string = 'alt'; +const TYPE_STRING: string = "type"; +const ALT_STRING: string = "alt"; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-image-button-has-alt', - type: 'maintainability', + ruleName: "react-a11y-image-button-has-alt", + type: "maintainability", description: 'Enforce that inputs element with type="image" must have alt attribute.', options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -49,18 +49,20 @@ class ReactA11yImageButtonHasAltWalker extends Lint.RuleWalker { private validateOpeningElement(node: ts.JsxOpeningLikeElement): void { const tagName: string = node.tagName.getText(); - if (tagName !== 'input') { + if (tagName !== "input") { return; } const attributes: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(node); const typeAttribute: ts.JsxAttribute = attributes[TYPE_STRING]; - if (!typeAttribute - || typeAttribute.initializer === undefined - || !isStringLiteral(typeAttribute.initializer) - || getStringLiteral(typeAttribute) === undefined - || getStringLiteral(typeAttribute)!.toLowerCase() !== 'image') { + if ( + !typeAttribute || + typeAttribute.initializer === undefined || + !isStringLiteral(typeAttribute.initializer) || + getStringLiteral(typeAttribute) === undefined || + getStringLiteral(typeAttribute)!.toLowerCase() !== "image" + ) { return; } diff --git a/src/reactA11yImgHasAltRule.ts b/src/reactA11yImgHasAltRule.ts index 01924f091..c2e867721 100644 --- a/src/reactA11yImgHasAltRule.ts +++ b/src/reactA11yImgHasAltRule.ts @@ -1,19 +1,14 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; - -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { - getAllAttributesFromJsxElement, - getJsxAttributesFromJsxElement, - getStringLiteral, - isEmpty -} from './utils/JsxAttribute'; -import { isJsxSpreadAttribute } from './utils/TypeGuard'; - -const ROLE_STRING: string = 'role'; -const ALT_STRING: string = 'alt'; -const TITLE_STRING: string = 'title'; -const IMAGE_FILENAME_REGEX: RegExp = new RegExp('^.*\\.(jpg|bmp|jpeg|jfif|gif|png|tif|tiff)$', 'i'); +import * as ts from "typescript"; +import * as Lint from "tslint"; + +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getAllAttributesFromJsxElement, getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; +import { isJsxSpreadAttribute } from "./utils/TypeGuard"; + +const ROLE_STRING: string = "role"; +const ALT_STRING: string = "alt"; +const TITLE_STRING: string = "title"; +const IMAGE_FILENAME_REGEX: RegExp = new RegExp("^.*\\.(jpg|bmp|jpeg|jfif|gif|png|tif|tiff)$", "i"); export function getFailureStringNoAlt(tagName: string): string { return `<${tagName}> elements must have an non-empty alt attribute or \ @@ -45,19 +40,20 @@ export function getFailureStringAltIsImageFileName(tagName: string): string { */ export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-img-has-alt', - type: 'maintainability', - description: 'Enforce that an img element contains the non-empty alt attribute. ' + + ruleName: "react-a11y-img-has-alt", + type: "maintainability", + description: + "Enforce that an img element contains the non-empty alt attribute. " + 'For decorative images, using empty alt attribute and role="presentation".', - options: 'string[]', - optionsDescription: '', - optionExamples: ['true', '[true, ["Image"]]'], + options: "string[]", + optionsDescription: "", + optionExamples: ["true", '[true, ["Image"]]'], typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -88,7 +84,7 @@ class ImgHasAltWalker extends Lint.RuleWalker { const additionalTagNames: string[] = options.length > 0 ? options[0] : []; // The targetTagNames is the list of tag names we want to check. - const targetTagNames: string[] = ['img'].concat(additionalTagNames); + const targetTagNames: string[] = ["img"].concat(additionalTagNames); if (!tagName || targetTagNames.indexOf(tagName) === -1) { return; @@ -104,47 +100,29 @@ class ImgHasAltWalker extends Lint.RuleWalker { const altAttribute: ts.JsxAttribute = attributes[ALT_STRING]; if (!altAttribute) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureStringNoAlt(tagName) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringNoAlt(tagName)); } else { const roleAttribute: ts.JsxAttribute = attributes[ROLE_STRING]; - const roleAttributeValue = roleAttribute ? getStringLiteral(roleAttribute) : ''; + const roleAttributeValue = roleAttribute ? getStringLiteral(roleAttribute) : ""; const titleAttribute: ts.JsxAttribute = attributes[TITLE_STRING]; - const isPresentationRole: boolean = !!String(roleAttributeValue).toLowerCase().match(/\bpresentation\b/); - const isEmptyAlt: boolean = isEmpty(altAttribute) || getStringLiteral(altAttribute) === ''; - const isEmptyTitle: boolean = isEmpty(titleAttribute) || getStringLiteral(titleAttribute) === ''; - const allowNonEmptyAltWithRolePresentation: boolean = options.length > 1 - ? options[1].allowNonEmptyAltWithRolePresentation - : false; - const isAltImageFileName: boolean = !isEmptyAlt && IMAGE_FILENAME_REGEX.test(getStringLiteral(altAttribute) || ''); + const isPresentationRole: boolean = !!String(roleAttributeValue) + .toLowerCase() + .match(/\bpresentation\b/); + const isEmptyAlt: boolean = isEmpty(altAttribute) || getStringLiteral(altAttribute) === ""; + const isEmptyTitle: boolean = isEmpty(titleAttribute) || getStringLiteral(titleAttribute) === ""; + const allowNonEmptyAltWithRolePresentation: boolean = + options.length > 1 ? options[1].allowNonEmptyAltWithRolePresentation : false; + const isAltImageFileName: boolean = !isEmptyAlt && IMAGE_FILENAME_REGEX.test(getStringLiteral(altAttribute) || ""); // altValue if (!isEmptyAlt && isPresentationRole && !allowNonEmptyAltWithRolePresentation && !titleAttribute) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureStringNonEmptyAltAndPresentationRole(tagName) - ); - } else if (isEmptyAlt && !isPresentationRole && !titleAttribute) { // - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureStringEmptyAltAndNotPresentationRole(tagName) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringNonEmptyAltAndPresentationRole(tagName)); + } else if (isEmptyAlt && !isPresentationRole && !titleAttribute) { + // + this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringEmptyAltAndNotPresentationRole(tagName)); } else if (isEmptyAlt && titleAttribute && !isEmptyTitle) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureStringEmptyAltAndNotEmptyTitle(tagName) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringEmptyAltAndNotEmptyTitle(tagName)); } else if (isAltImageFileName) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureStringAltIsImageFileName(tagName) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringAltIsImageFileName(tagName)); } } } diff --git a/src/reactA11yInputElementsRule.ts b/src/reactA11yInputElementsRule.ts index 136581025..9e1bf3017 100644 --- a/src/reactA11yInputElementsRule.ts +++ b/src/reactA11yInputElementsRule.ts @@ -1,31 +1,29 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {getJsxAttributesFromJsxElement, isEmpty} from './utils/JsxAttribute'; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { getJsxAttributesFromJsxElement, isEmpty } from "./utils/JsxAttribute"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -export const MISSING_PLACEHOLDER_INPUT_FAILURE_STRING: string - = 'Input elements must include default, place-holding characters if empty'; -export const MISSING_PLACEHOLDER_TEXTAREA_FAILURE_STRING: string - = 'Textarea elements must include default, place-holding characters if empty'; +export const MISSING_PLACEHOLDER_INPUT_FAILURE_STRING: string = "Input elements must include default, place-holding characters if empty"; +export const MISSING_PLACEHOLDER_TEXTAREA_FAILURE_STRING: string = + "Textarea elements must include default, place-holding characters if empty"; /** * Implementation of the react-a11y-input-elements rule. */ export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-input-elements', - type: 'functionality', - description: 'For accessibility of your website, HTML input boxes and text areas must include default, place-holding characters.', + ruleName: "react-a11y-input-elements", + type: "functionality", + description: "For accessibility of your website, HTML input boxes and text areas must include default, place-holding characters.", options: undefined, - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -38,16 +36,15 @@ export class Rule extends Lint.Rules.AbstractRule { } class ReactA11yInputElementsRuleWalker extends Lint.RuleWalker { - protected visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void { const tagName = node.tagName.getText(); - if (tagName === 'input') { + if (tagName === "input") { const attributes = getJsxAttributesFromJsxElement(node); if (isEmpty(attributes.value) && isEmpty(attributes.placeholder)) { this.addFailureAt(node.getStart(), node.getWidth(), MISSING_PLACEHOLDER_INPUT_FAILURE_STRING); } - } else if (tagName === 'textarea') { + } else if (tagName === "textarea") { const attributes = getJsxAttributesFromJsxElement(node); if (isEmpty(attributes.placeholder)) { this.addFailureAt(node.getStart(), node.getWidth(), MISSING_PLACEHOLDER_TEXTAREA_FAILURE_STRING); @@ -60,7 +57,7 @@ class ReactA11yInputElementsRuleWalker extends Lint.RuleWalker { const tagName = node.openingElement.tagName.getText(); const attributes: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(node); - if (tagName === 'textarea') { + if (tagName === "textarea") { if (node.children.length === 0 && isEmpty(attributes.placeholder)) { this.addFailureAt(node.getStart(), node.getWidth(), MISSING_PLACEHOLDER_TEXTAREA_FAILURE_STRING); } diff --git a/src/reactA11yLangRule.ts b/src/reactA11yLangRule.ts index e4e711955..65371ab91 100644 --- a/src/reactA11yLangRule.ts +++ b/src/reactA11yLangRule.ts @@ -1,39 +1,177 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_MISSING_LANG: string = 'An html element is missing the lang attribute'; -const FAILURE_WRONG_LANG_CODE: string = 'Lang attribute does not have a valid value. Found: '; +const FAILURE_MISSING_LANG: string = "An html element is missing the lang attribute"; +const FAILURE_WRONG_LANG_CODE: string = "Lang attribute does not have a valid value. Found: "; const LANGUAGE_CODES: string[] = [ - 'ab', 'aa', 'af', 'sq', 'am', 'ar', 'an', 'hy', 'as', 'ay', 'az', 'ba', 'eu', 'bn', - 'dz', 'bh', 'bi', 'br', 'bg', 'my', 'be', 'km', 'ca', 'zh', 'zh-Hans', 'zh-Hant', - 'co', 'hr', 'cs', 'da', 'nl', 'en', 'eo', 'et', 'fo', 'fa', 'fj', 'fi', 'fr', 'fy', - 'gl', 'gd', 'gv', 'ka', 'de', 'el', 'kl', 'gn', 'gu', 'ht', 'ha', 'he', 'iw', 'hi', - 'hu', 'is', 'io', 'id', 'in', 'ia', 'ie', 'iu', 'ik', 'ga', 'it', 'ja', 'jv', 'kn', - 'ks', 'kk', 'rw', 'ky', 'rn', 'ko', 'ku', 'lo', 'la', 'lv', 'li', 'ln', 'lt', 'mk', - 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mo', 'mn', 'na', 'ne', 'no', 'oc', 'or', 'om', - 'ps', 'pl', 'pt', 'pa', 'qu', 'rm', 'ro', 'ru', 'sm', 'sg', 'sa', 'sr', 'sh', 'st', - 'tn', 'sn', 'ii', 'sd', 'si', 'ss', 'sk', 'sl', 'so', 'es', 'su', 'sw', 'sv', 'tl', - 'tg', 'ta', 'tt', 'te', 'th', 'bo', 'ti', 'to', 'ts', 'tr', 'tk', 'tw', 'ug', 'uk', - 'ur', 'uz', 'vi', 'vo', 'wa', 'cy', 'wo', 'xh', 'yi', 'ji', 'yo', 'zu' + "ab", + "aa", + "af", + "sq", + "am", + "ar", + "an", + "hy", + "as", + "ay", + "az", + "ba", + "eu", + "bn", + "dz", + "bh", + "bi", + "br", + "bg", + "my", + "be", + "km", + "ca", + "zh", + "zh-Hans", + "zh-Hant", + "co", + "hr", + "cs", + "da", + "nl", + "en", + "eo", + "et", + "fo", + "fa", + "fj", + "fi", + "fr", + "fy", + "gl", + "gd", + "gv", + "ka", + "de", + "el", + "kl", + "gn", + "gu", + "ht", + "ha", + "he", + "iw", + "hi", + "hu", + "is", + "io", + "id", + "in", + "ia", + "ie", + "iu", + "ik", + "ga", + "it", + "ja", + "jv", + "kn", + "ks", + "kk", + "rw", + "ky", + "rn", + "ko", + "ku", + "lo", + "la", + "lv", + "li", + "ln", + "lt", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mo", + "mn", + "na", + "ne", + "no", + "oc", + "or", + "om", + "ps", + "pl", + "pt", + "pa", + "qu", + "rm", + "ro", + "ru", + "sm", + "sg", + "sa", + "sr", + "sh", + "st", + "tn", + "sn", + "ii", + "sd", + "si", + "ss", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tl", + "tg", + "ta", + "tt", + "te", + "th", + "bo", + "ti", + "to", + "ts", + "tr", + "tk", + "tw", + "ug", + "uk", + "ur", + "uz", + "vi", + "vo", + "wa", + "cy", + "wo", + "xh", + "yi", + "ji", + "yo", + "zu" ]; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-lang', - type: 'functionality', - description: 'For accessibility of your website, html elements must have a valid lang attribute.', + ruleName: "react-a11y-lang", + type: "functionality", + description: "For accessibility of your website, html elements must have a valid lang attribute.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -46,7 +184,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class ReactA11yLangRuleWalker extends Lint.RuleWalker { - protected visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void { this.validateOpeningElement(node, node); super.visitJsxSelfClosingElement(node); @@ -58,27 +195,25 @@ class ReactA11yLangRuleWalker extends Lint.RuleWalker { } private validateOpeningElement(parent: ts.Node, openingElement: ts.JsxOpeningLikeElement): void { - if (openingElement.tagName.getText() === 'html') { + if (openingElement.tagName.getText() === "html") { const attributes: ts.JsxAttributes = openingElement.attributes; let langFound: boolean = false; - attributes.properties.forEach((attribute: ts.JsxAttributeLike): void => { - if (attribute.kind === ts.SyntaxKind.JsxAttribute) { - if (attribute.name.getText() === 'lang') { - langFound = true; - if (attribute.initializer!.kind === ts.SyntaxKind.StringLiteral) { - const langText: string = ((attribute).initializer).text; - if ((LANGUAGE_CODES.indexOf(langText)) === -1) { - this.addFailureAt( - parent.getStart(), - parent.getWidth(), - FAILURE_WRONG_LANG_CODE + langText - ); + attributes.properties.forEach( + (attribute: ts.JsxAttributeLike): void => { + if (attribute.kind === ts.SyntaxKind.JsxAttribute) { + if (attribute.name.getText() === "lang") { + langFound = true; + if (attribute.initializer!.kind === ts.SyntaxKind.StringLiteral) { + const langText: string = ((attribute).initializer).text; + if (LANGUAGE_CODES.indexOf(langText) === -1) { + this.addFailureAt(parent.getStart(), parent.getWidth(), FAILURE_WRONG_LANG_CODE + langText); + } } } } } - }); + ); if (!langFound) { this.addFailureAt(parent.getStart(), parent.getWidth(), FAILURE_MISSING_LANG); } diff --git a/src/reactA11yMetaRule.ts b/src/reactA11yMetaRule.ts index a8b686954..76053aa84 100644 --- a/src/reactA11yMetaRule.ts +++ b/src/reactA11yMetaRule.ts @@ -1,24 +1,23 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; const FAILURE_STRING: string = 'Do not use http-equiv="refresh"'; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-meta', - type: 'functionality', + ruleName: "react-a11y-meta", + type: "functionality", description: 'For accessibility of your website, HTML meta elements must not have http-equiv="refresh".', options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Ignored', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Ignored", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -31,7 +30,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class ReactA11yMetaRuleWalker extends Lint.RuleWalker { - protected visitJsxElement(node: ts.JsxElement): void { this.validateOpeningElement(node, node.openingElement); super.visitJsxElement(node); @@ -42,18 +40,20 @@ class ReactA11yMetaRuleWalker extends Lint.RuleWalker { } private validateOpeningElement(parent: ts.Node, openElement: ts.JsxOpeningLikeElement): void { - if (openElement.tagName.getText() === 'meta') { + if (openElement.tagName.getText() === "meta") { const attributes: ts.JsxAttributes = openElement.attributes; - attributes.properties.forEach((parameter: ts.JsxAttributeLike): void => { - if (parameter.kind === ts.SyntaxKind.JsxAttribute) { - const attribute: ts.JsxAttribute = parameter; - if (attribute.name.getText() === 'http-equiv') { - if (attribute.initializer !== undefined && this.isStringLiteral(attribute.initializer, 'refresh')) { - this.addFailureAt(parent.getStart(), openElement.getWidth(), FAILURE_STRING); + attributes.properties.forEach( + (parameter: ts.JsxAttributeLike): void => { + if (parameter.kind === ts.SyntaxKind.JsxAttribute) { + const attribute: ts.JsxAttribute = parameter; + if (attribute.name.getText() === "http-equiv") { + if (attribute.initializer !== undefined && this.isStringLiteral(attribute.initializer, "refresh")) { + this.addFailureAt(parent.getStart(), openElement.getWidth(), FAILURE_STRING); + } } } } - }); + ); } } diff --git a/src/reactA11yNoOnchangeRule.ts b/src/reactA11yNoOnchangeRule.ts index 8984383db..8db1c12d8 100644 --- a/src/reactA11yNoOnchangeRule.ts +++ b/src/reactA11yNoOnchangeRule.ts @@ -1,33 +1,32 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {getJsxAttributesFromJsxElement} from './utils/JsxAttribute'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getJsxAttributesFromJsxElement } from "./utils/JsxAttribute"; /** * Implementation of the react-a11y-no-onchange rule. */ export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-no-onchange', - type: 'functionality', - description: 'For accessibility of your website, enforce usage of onBlur over onChange on select menus.', - options: 'string[]', - optionsDescription: 'Additional tag names to validate.', - optionExamples: ['true', '[true, ["Select"]]'], + ruleName: "react-a11y-no-onchange", + type: "functionality", + description: "For accessibility of your website, enforce usage of onBlur over onChange on select menus.", + options: "string[]", + optionsDescription: "Additional tag names to validate.", + optionExamples: ["true", '[true, ["Select"]]'], typescriptOnly: false, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return sourceFile.languageVariant === ts.LanguageVariant.JSX ? - this.applyWithWalker(new ReactA11yNoOnchangeRuleWalker(sourceFile, this.getOptions())) : - []; + return sourceFile.languageVariant === ts.LanguageVariant.JSX + ? this.applyWithWalker(new ReactA11yNoOnchangeRuleWalker(sourceFile, this.getOptions())) + : []; } } @@ -48,14 +47,14 @@ class ReactA11yNoOnchangeRuleWalker extends Lint.RuleWalker { const additionalTagNames: string[] = Array.isArray(options) && options.length > 0 ? options[0] : []; - const targetTagNames: string[] = ['select', ...additionalTagNames]; + const targetTagNames: string[] = ["select", ...additionalTagNames]; if (!tagName || targetTagNames.indexOf(tagName) === -1) { return; } const attributes = getJsxAttributesFromJsxElement(node); - if (attributes.hasOwnProperty('onchange')) { + if (attributes.hasOwnProperty("onchange")) { const errorMessage = `onChange event handler should not be used with the <${tagName}>. Please use onBlur instead.`; this.addFailureAt(node.getStart(), node.getWidth(), errorMessage); } diff --git a/src/reactA11yPropsRule.ts b/src/reactA11yPropsRule.ts index 924dae02e..59a6b844d 100644 --- a/src/reactA11yPropsRule.ts +++ b/src/reactA11yPropsRule.ts @@ -2,15 +2,15 @@ * Enforce all `aria-*` attributes are valid. */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getPropName } from './utils/JsxAttribute'; -import { IAria } from './utils/attributes/IAria'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getPropName } from "./utils/JsxAttribute"; +import { IAria } from "./utils/attributes/IAria"; // tslint:disable-next-line:no-require-imports no-var-requires -const ARIA_SCHEMA: { [attributeName: string]: IAria } = require('./utils/attributes/ariaSchema.json'); +const ARIA_SCHEMA: { [attributeName: string]: IAria } = require("./utils/attributes/ariaSchema.json"); export function getFailureString(name: string): string { return `This attribute name '${name}' is an invalid ARIA attribute. \ @@ -20,17 +20,17 @@ https://www.w3.org/TR/2014/REC-wai-aria-20140320/states_and_properties#state_pro export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-props', - type: 'maintainability', - description: 'Enforce all `aria-*` attributes are valid. Elements cannot use an invalid `aria-*` attribute.', + ruleName: "react-a11y-props", + type: "maintainability", + description: "Enforce all `aria-*` attributes are valid. Elements cannot use an invalid `aria-*` attribute.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -48,11 +48,7 @@ class A11yPropsWalker extends Lint.RuleWalker { } if (!ARIA_SCHEMA[name.toLowerCase()]) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureString(name) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureString(name)); } } } diff --git a/src/reactA11yProptypesRule.ts b/src/reactA11yProptypesRule.ts index 1fa4a380a..22f5ffa61 100644 --- a/src/reactA11yProptypesRule.ts +++ b/src/reactA11yProptypesRule.ts @@ -2,59 +2,49 @@ * Enforce ARIA state and property values are valid. */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; - -import { AstUtils } from './utils/AstUtils'; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { - getPropName, - getStringLiteral, - getBooleanLiteral -} from './utils/JsxAttribute'; -import { IAria } from './utils/attributes/IAria'; -import { - isStringLiteral, - isNumericLiteral, - isJsxExpression, - isFalseKeyword, - isTrueKeyword, - isNullKeyword -} from './utils/TypeGuard'; +import * as ts from "typescript"; +import * as Lint from "tslint"; + +import { AstUtils } from "./utils/AstUtils"; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getPropName, getStringLiteral, getBooleanLiteral } from "./utils/JsxAttribute"; +import { IAria } from "./utils/attributes/IAria"; +import { isStringLiteral, isNumericLiteral, isJsxExpression, isFalseKeyword, isTrueKeyword, isNullKeyword } from "./utils/TypeGuard"; // tslint:disable-next-line:no-require-imports no-var-requires -const aria: { [attributeName: string]: IAria } = require('./utils/attributes/ariaSchema.json'); +const aria: { [attributeName: string]: IAria } = require("./utils/attributes/ariaSchema.json"); export function getFailureString(propName: string, expectedType: string, permittedValues: string[]): string { switch (expectedType) { - case 'tristate': + case "tristate": return `The value for ${propName} must be a boolean or the string 'mixed'.`; - case 'token': + case "token": return `The value for ${propName} must be a single token from the following: ${permittedValues}.`; - case 'tokenlist': + case "tokenlist": return `The value for ${propName} must be a list of one or more tokens from the following: ${permittedValues}.`; - case 'boolean': - case 'string': - case 'integer': - case 'number': - default: // tslint:disable-line:no-switch-case-fall-through + case "boolean": + case "string": + case "integer": + case "number": + default: + // tslint:disable-line:no-switch-case-fall-through return `The value for ${propName} must be a ${expectedType}.`; } } export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-proptypes', - type: 'maintainability', - description: 'Enforce ARIA state and property values are valid.', + ruleName: "react-a11y-proptypes", + type: "maintainability", + description: "Enforce ARIA state and property values are valid.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -78,18 +68,14 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { return; } - const allowUndefined: boolean = aria[propName].allowUndefined !== undefined - ? aria[propName].allowUndefined - : false; + const allowUndefined: boolean = aria[propName].allowUndefined !== undefined ? aria[propName].allowUndefined : false; const expectedType: string = aria[propName].type; const permittedValues: string[] = aria[propName].values; const propValue: string = getStringLiteral(node) || String(getBooleanLiteral(node)); if (this.isUndefined(node.initializer)) { if (!allowUndefined) { - this.addFailureAt( - node.getStart(), node.getWidth(), getFailureString(propName, expectedType, permittedValues) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureString(propName, expectedType, permittedValues)); } return; } else if (this.isComplexType(node.initializer)) { @@ -97,11 +83,7 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { } if (!this.validityCheck(node.initializer, propValue, expectedType, permittedValues)) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - getFailureString(propName, expectedType, permittedValues) - ); + this.addFailureAt(node.getStart(), node.getWidth(), getFailureString(propName, expectedType, permittedValues)); } } @@ -116,17 +98,26 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { } switch (expectedType) { - case 'boolean': return this.isBoolean(propValueExpression); - case 'tristate': return this.isBoolean(propValueExpression) || this.isMixed(propValueExpression); - case 'integer': return this.isInteger(propValueExpression); - case 'number': return this.isNumber(propValueExpression); - case 'string': return this.isString(propValueExpression); - case 'token': - return (this.isString(propValueExpression) || this.isBoolean(propValueExpression)) && - permittedValues.indexOf(propValue.toLowerCase()) > -1; - case 'tokenlist': - return (this.isString(propValueExpression) || this.isBoolean(propValueExpression)) && - propValue.split(' ').every(token => permittedValues.indexOf(token.toLowerCase()) > -1); + case "boolean": + return this.isBoolean(propValueExpression); + case "tristate": + return this.isBoolean(propValueExpression) || this.isMixed(propValueExpression); + case "integer": + return this.isInteger(propValueExpression); + case "number": + return this.isNumber(propValueExpression); + case "string": + return this.isString(propValueExpression); + case "token": + return ( + (this.isString(propValueExpression) || this.isBoolean(propValueExpression)) && + permittedValues.indexOf(propValue.toLowerCase()) > -1 + ); + case "tokenlist": + return ( + (this.isString(propValueExpression) || this.isBoolean(propValueExpression)) && + propValue.split(" ").every(token => permittedValues.indexOf(token.toLowerCase()) > -1) + ); default: return false; } @@ -161,7 +152,7 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { if (isStringLiteral(node)) { const propValue: string = node.text.toLowerCase(); - return propValue === 'true' || propValue === 'false'; + return propValue === "true" || propValue === "false"; } else if (isJsxExpression(node)) { const expression = node.expression; if (expression === undefined) { @@ -171,7 +162,7 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { if (isStringLiteral(expression)) { const propValue: string = expression.text.toLowerCase(); - return propValue === 'true' || propValue === 'false'; + return propValue === "true" || propValue === "false"; } else { return isFalseKeyword(expression) || isTrueKeyword(expression); } @@ -182,14 +173,14 @@ class ReactA11yProptypesWalker extends Lint.RuleWalker { private isMixed(node: ts.Expression): boolean { if (isStringLiteral(node)) { - return node.text.toLowerCase() === 'mixed'; + return node.text.toLowerCase() === "mixed"; } else if (isJsxExpression(node)) { const expression = node.expression; if (expression === undefined) { return false; } - return isStringLiteral(expression) && expression.text.toLowerCase() === 'mixed'; + return isStringLiteral(expression) && expression.text.toLowerCase() === "mixed"; } return false; diff --git a/src/reactA11yRequiredRule.ts b/src/reactA11yRequiredRule.ts index bec00b31d..152681c64 100644 --- a/src/reactA11yRequiredRule.ts +++ b/src/reactA11yRequiredRule.ts @@ -1,27 +1,26 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import { getJsxAttributesFromJsxElement, isEmpty, getBooleanLiteral } from './utils/JsxAttribute'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getJsxAttributesFromJsxElement, isEmpty, getBooleanLiteral } from "./utils/JsxAttribute"; -const FAILURE_STRING: string = 'Required input elements must have an aria-required set to true'; -const REQUIRED_STRING: string = 'required'; -const ARIA_REQUIRED_STRING = 'aria-required'; +const FAILURE_STRING: string = "Required input elements must have an aria-required set to true"; +const REQUIRED_STRING: string = "required"; +const ARIA_REQUIRED_STRING = "aria-required"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-required', - type: 'functionality', - description: 'Enforce that required input elements must have aria-required set to true', + ruleName: "react-a11y-required", + type: "functionality", + description: "Enforce that required input elements must have aria-required set to true", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Low', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Low", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -45,7 +44,7 @@ class ReactA11yRequiredRuleWalker extends Lint.RuleWalker { private validateOpeningElement(node: ts.JsxOpeningLikeElement): void { const tagName: string = node.tagName.getText(); - if (tagName !== 'input') { + if (tagName !== "input") { return; } @@ -58,11 +57,8 @@ class ReactA11yRequiredRuleWalker extends Lint.RuleWalker { const ariaRequiredAttribute: ts.JsxAttribute = attributes[ARIA_REQUIRED_STRING]; - if (!ariaRequiredAttribute || - isEmpty(ariaRequiredAttribute) || - !getBooleanLiteral(ariaRequiredAttribute)) { + if (!ariaRequiredAttribute || isEmpty(ariaRequiredAttribute) || !getBooleanLiteral(ariaRequiredAttribute)) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING); } } - } diff --git a/src/reactA11yRoleHasRequiredAriaPropsRule.ts b/src/reactA11yRoleHasRequiredAriaPropsRule.ts index 37c155cb8..59ca92306 100644 --- a/src/reactA11yRoleHasRequiredAriaPropsRule.ts +++ b/src/reactA11yRoleHasRequiredAriaPropsRule.ts @@ -2,57 +2,51 @@ * Elements with aria roles must have all required attributes according to the role */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; - -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getImplicitRole } from './utils/getImplicitRole'; -import { - getJsxAttributesFromJsxElement, - getStringLiteral -} from './utils/JsxAttribute'; -import { IRole, IRoleSchema } from './utils/attributes/IRole'; -import { IAria } from './utils/attributes/IAria'; +import * as ts from "typescript"; +import * as Lint from "tslint"; + +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getImplicitRole } from "./utils/getImplicitRole"; +import { getJsxAttributesFromJsxElement, getStringLiteral } from "./utils/JsxAttribute"; +import { IRole, IRoleSchema } from "./utils/attributes/IRole"; +import { IAria } from "./utils/attributes/IAria"; // tslint:disable-next-line:no-require-imports no-var-requires -const ROLES_SCHEMA: IRoleSchema = require('./utils/attributes/roleSchema.json'); +const ROLES_SCHEMA: IRoleSchema = require("./utils/attributes/roleSchema.json"); const ROLES: { [key: string]: IRole } = ROLES_SCHEMA.roles; // tslint:disable-next-line:no-require-imports no-var-requires -const ARIA_ATTRIBUTES: { [attributeName: string]: IAria } = require('./utils/attributes/ariaSchema.json'); -const ROLE_STRING: string = 'role'; +const ARIA_ATTRIBUTES: { [attributeName: string]: IAria } = require("./utils/attributes/ariaSchema.json"); +const ROLE_STRING: string = "role"; // h1-h6 tags have implicit role heading with aria-level attribute. -const TAGS_WITH_ARIA_LEVEL: string[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; +const TAGS_WITH_ARIA_LEVEL: string[] = ["h1", "h2", "h3", "h4", "h5", "h6"]; -export function getFailureStringForNotImplicitRole(roleNamesInElement: string[], - missingProps: string[]): string { - return `Element with ARIA role(s) '${roleNamesInElement.join(', ')}' \ -are missing required attribute(s): ${missingProps.join(', ')}. \ +export function getFailureStringForNotImplicitRole(roleNamesInElement: string[], missingProps: string[]): string { + return `Element with ARIA role(s) '${roleNamesInElement.join(", ")}' \ +are missing required attribute(s): ${missingProps.join(", ")}. \ A reference to role definitions can be found at https://www.w3.org/TR/wai-aria/roles#role_definitions.`; } -export function getFailureStringForImplicitRole(tagName: string, - roleNamesInElement: string, - missingProps: string[]): string { +export function getFailureStringForImplicitRole(tagName: string, roleNamesInElement: string, missingProps: string[]): string { return `Tag '${tagName}' has implicit role '${roleNamesInElement}'. \ -It requires aria-* attributes: ${missingProps.join(', ')} that are missing in the element. \ +It requires aria-* attributes: ${missingProps.join(", ")} that are missing in the element. \ A reference to role definitions can be found at https://www.w3.org/TR/wai-aria/roles#role_definitions.`; } export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-role-has-required-aria-props', - type: 'maintainability', - description: 'Elements with aria roles must have all required attributes according to the role.', + ruleName: "react-a11y-role-has-required-aria-props", + type: "maintainability", + description: "Elements with aria roles must have all required attributes according to the role.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -81,7 +75,9 @@ class A11yRoleHasRequiredAriaPropsWalker extends Lint.RuleWalker { // If role attribute is specified, get the role value. Otherwise get the implicit role from tag name. const roleValue = roleProp ? getStringLiteral(roleProp) : getImplicitRole(node); const isImplicitRole: boolean = !roleProp && !!roleValue; - const normalizedRoles: string[] = (roleValue || '').toLowerCase().split(' ') + const normalizedRoles: string[] = (roleValue || "") + .toLowerCase() + .split(" ") .filter((role: string) => !!ROLES[role]); if (normalizedRoles.length === 0) { @@ -97,19 +93,20 @@ class A11yRoleHasRequiredAriaPropsWalker extends Lint.RuleWalker { const attributeNamesInElement: string[] = Object.keys(attributesInElement) .filter((attributeName: string) => !!ARIA_ATTRIBUTES[attributeName.toLowerCase()]) // h1-h6 tags have aria-level - .concat(TAGS_WITH_ARIA_LEVEL.indexOf(tagName) === -1 ? [] : ['aria-level']); + .concat(TAGS_WITH_ARIA_LEVEL.indexOf(tagName) === -1 ? [] : ["aria-level"]); // Get the list of missing required aria-* attributes in current element. - const missingAttributes: string[] = requiredAttributeNames - .filter((attributeName: string) => attributeNamesInElement.indexOf(attributeName) === -1); + const missingAttributes: string[] = requiredAttributeNames.filter( + (attributeName: string) => attributeNamesInElement.indexOf(attributeName) === -1 + ); if (missingAttributes.length > 0) { this.addFailureAt( node.getStart(), node.getWidth(), - isImplicitRole ? - getFailureStringForImplicitRole(node.tagName.getText(), normalizedRoles[0], missingAttributes) : - getFailureStringForNotImplicitRole(normalizedRoles, missingAttributes) + isImplicitRole + ? getFailureStringForImplicitRole(node.tagName.getText(), normalizedRoles[0], missingAttributes) + : getFailureStringForNotImplicitRole(normalizedRoles, missingAttributes) ); } } diff --git a/src/reactA11yRoleRule.ts b/src/reactA11yRoleRule.ts index d0003f3c3..29f9dfc3d 100644 --- a/src/reactA11yRoleRule.ts +++ b/src/reactA11yRoleRule.ts @@ -2,23 +2,25 @@ * Elements with aria roles must use a **valid**, **non-abstract** aria role */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getPropName, getStringLiteral, isEmpty } from './utils/JsxAttribute'; -import { IRole, IRoleSchema } from './utils/attributes/IRole'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getPropName, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; +import { IRole, IRoleSchema } from "./utils/attributes/IRole"; // tslint:disable-next-line:no-require-imports no-var-requires -const ROLE_SCHEMA: IRoleSchema = require('./utils/attributes/roleSchema.json'); +const ROLE_SCHEMA: IRoleSchema = require("./utils/attributes/roleSchema.json"); const ROLES: { [key: string]: IRole } = ROLE_SCHEMA.roles; // The array of non-abstract valid rules. const VALID_ROLES: string[] = Object.keys(ROLES).filter(role => ROLES[role].isAbstract === false); export function getFailureStringUndefinedRole(): string { - return '\'role\' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role_definitions, ' + - 'or simply remove this attribute'; + return ( + "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role_definitions, " + + "or simply remove this attribute" + ); } export function getFailureStringInvalidRole(invalidRoleName: string): string { @@ -29,17 +31,17 @@ https://www.w3.org/TR/wai-aria/roles#role_definitions.`; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-role', - type: 'maintainability', - description: 'Elements with aria roles must use a **valid**, **non-abstract** aria role.', + ruleName: "react-a11y-role", + type: "maintainability", + description: "Elements with aria roles must use a **valid**, **non-abstract** aria role.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -53,7 +55,7 @@ class A11yRoleRuleWalker extends Lint.RuleWalker { public visitJsxAttribute(node: ts.JsxAttribute): void { const name = getPropName(node); - if (!name || name.toLowerCase() !== 'role') { + if (!name || name.toLowerCase() !== "role") { return; } @@ -62,12 +64,12 @@ class A11yRoleRuleWalker extends Lint.RuleWalker { if (roleValue) { // Splitted by space doesn't mean the multiple role definition is correct, // just because this rule is not checking if it is using multiple role definition. - const normalizedValues: string[] = roleValue.toLowerCase().split(' '); + const normalizedValues: string[] = roleValue.toLowerCase().split(" "); if (normalizedValues.some(value => !!(value && VALID_ROLES.indexOf(value) === -1))) { this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringInvalidRole(roleValue)); } - } else if (roleValue === '' || isEmpty(node)) { + } else if (roleValue === "" || isEmpty(node)) { this.addFailureAt(node.getStart(), node.getWidth(), getFailureStringUndefinedRole()); } diff --git a/src/reactA11yRoleSupportsAriaPropsRule.ts b/src/reactA11yRoleSupportsAriaPropsRule.ts index e5c16dec3..1d2b3edf3 100644 --- a/src/reactA11yRoleSupportsAriaPropsRule.ts +++ b/src/reactA11yRoleSupportsAriaPropsRule.ts @@ -2,30 +2,30 @@ * Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getImplicitRole } from './utils/getImplicitRole'; -import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from './utils/JsxAttribute'; -import { IRole, IRoleSchema } from './utils/attributes/IRole'; -import { IAria } from './utils/attributes/IAria'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getImplicitRole } from "./utils/getImplicitRole"; +import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; +import { IRole, IRoleSchema } from "./utils/attributes/IRole"; +import { IAria } from "./utils/attributes/IAria"; // tslint:disable:no-require-imports no-var-requires -const ROLE_SCHEMA: IRoleSchema = require('./utils/attributes/roleSchema.json'); -const ARIA_ATTRIBUTES: { [attributeName: string]: IAria } = require('./utils/attributes/ariaSchema.json'); +const ROLE_SCHEMA: IRoleSchema = require("./utils/attributes/roleSchema.json"); +const ARIA_ATTRIBUTES: { [attributeName: string]: IAria } = require("./utils/attributes/ariaSchema.json"); // tslint:enable:no-require-imports no-var-requires const ROLES: { [key: string]: IRole } = ROLE_SCHEMA.roles; -const ROLE_STRING: string = 'role'; +const ROLE_STRING: string = "role"; export function getFailureStringForNotImplicitRole(roleNamesInElement: string[], invalidPropNames: string[]): string { - return `Attribute(s) ${invalidPropNames.join(', ')} are not supported by role(s) ${roleNamesInElement.join(', ')}. \ + return `Attribute(s) ${invalidPropNames.join(", ")} are not supported by role(s) ${roleNamesInElement.join(", ")}. \ You are using incorrect role or incorrect aria-* attribute`; } export function getFailureStringForImplicitRole(tagName: string, roleName: string, invalidPropNames: string[]): string { - return `Attribute(s) ${invalidPropNames.join(', ')} not supported \ + return `Attribute(s) ${invalidPropNames.join(", ")} not supported \ by role ${roleName} which is implicitly set by the HTML tag ${tagName}.`; } @@ -37,18 +37,18 @@ A reference about no corresponding role: https://www.w3.org/TR/html-aria/#dfn-no export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-role-supports-aria-props', - type: 'maintainability', - description: 'Enforce that elements with explicit or implicit roles defined contain ' + - 'only `aria-*` properties supported by that `role`.', + ruleName: "react-a11y-role-supports-aria-props", + type: "maintainability", + description: + "Enforce that elements with explicit or implicit roles defined contain " + "only `aria-*` properties supported by that `role`.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -80,7 +80,8 @@ class A11yRoleSupportsAriaPropsWalker extends Lint.RuleWalker { } if (roleProp !== undefined) { roleValue = getStringLiteral(roleProp); - if (!isEmpty(roleProp) && roleValue === undefined) { // Do NOT check if can't retrieve the right role. + if (!isEmpty(roleProp) && roleValue === undefined) { + // Do NOT check if can't retrieve the right role. return; } } else { @@ -88,41 +89,37 @@ class A11yRoleSupportsAriaPropsWalker extends Lint.RuleWalker { } const isImplicitRole: boolean = !roleProp && !!roleValue; - const normalizedRoles = (roleValue || '').toLowerCase().split(' ') + const normalizedRoles = (roleValue || "") + .toLowerCase() + .split(" ") .filter((role: string) => role in ROLES); let supportedAttributeNames: string[] = ROLE_SCHEMA.globalSupportedProps; - normalizedRoles.forEach((role) => { + normalizedRoles.forEach(role => { supportedAttributeNames = supportedAttributeNames.concat(ROLES[role].additionalSupportedProps || []); }); - const attributeNamesInElement: string[] = Object.keys(attributesInElement) - .filter((attributeName: string) => !!ARIA_ATTRIBUTES[attributeName.toLowerCase()]); + const attributeNamesInElement: string[] = Object.keys(attributesInElement).filter( + (attributeName: string) => !!ARIA_ATTRIBUTES[attributeName.toLowerCase()] + ); // Get the list of not-supported aria-* attributes in current element. - const invalidAttributeNamesInElement: string[] = attributeNamesInElement - .filter((attributeName: string) => supportedAttributeNames.indexOf(attributeName) === -1); + const invalidAttributeNamesInElement: string[] = attributeNamesInElement.filter( + (attributeName: string) => supportedAttributeNames.indexOf(attributeName) === -1 + ); let failureString: string; if (normalizedRoles.length === 0) { failureString = getFailureStringForNoRole(node.tagName.getText(), invalidAttributeNamesInElement); } else if (isImplicitRole) { - failureString = getFailureStringForImplicitRole( - node.tagName.getText(), - normalizedRoles[0], - invalidAttributeNamesInElement - ); + failureString = getFailureStringForImplicitRole(node.tagName.getText(), normalizedRoles[0], invalidAttributeNamesInElement); } else { failureString = getFailureStringForNotImplicitRole(normalizedRoles, invalidAttributeNamesInElement); } if (invalidAttributeNamesInElement.length > 0) { - this.addFailureAt( - node.getStart(), - node.getWidth(), - failureString - ); + this.addFailureAt(node.getStart(), node.getWidth(), failureString); } } } diff --git a/src/reactA11yTabindexNoPositiveRule.ts b/src/reactA11yTabindexNoPositiveRule.ts index 691a60431..31c8cdc69 100644 --- a/src/reactA11yTabindexNoPositiveRule.ts +++ b/src/reactA11yTabindexNoPositiveRule.ts @@ -2,29 +2,29 @@ * Enforce tabindex value is **not greater than zero** */ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { getPropName, getStringLiteral, getNumericLiteral, isEmpty } from './utils/JsxAttribute'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { getPropName, getStringLiteral, getNumericLiteral, isEmpty } from "./utils/JsxAttribute"; export function getFailureString(): string { - return 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.'; + return "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0."; } export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-tabindex-no-positive', - type: 'maintainability', - description: 'Enforce tabindex value is **not greater than zero**.', + ruleName: "react-a11y-tabindex-no-positive", + type: "maintainability", + description: "Enforce tabindex value is **not greater than zero**.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Important', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Important", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -38,16 +38,16 @@ class A11yTabindexNoPositiveWalker extends Lint.RuleWalker { public visitJsxAttribute(node: ts.JsxAttribute): void { const name = getPropName(node); - if (!name || name.toLowerCase() !== 'tabindex') { + if (!name || name.toLowerCase() !== "tabindex") { return; } const literalString = getNumericLiteral(node) || getStringLiteral(node); // In case the attribute has no value of empty value. - if (literalString === '') { + if (literalString === "") { this.addFailureAt(node.getStart(), node.getWidth(), getFailureString()); - } else if (literalString && literalString !== '-1' && literalString !== '0') { + } else if (literalString && literalString !== "-1" && literalString !== "0") { this.addFailureAt(node.getStart(), node.getWidth(), getFailureString()); } else if (isEmpty(node)) { this.addFailureAt(node.getStart(), node.getWidth(), getFailureString()); diff --git a/src/reactA11yTitlesRule.ts b/src/reactA11yTitlesRule.ts index 394b82b81..b58aefa5a 100644 --- a/src/reactA11yTitlesRule.ts +++ b/src/reactA11yTitlesRule.ts @@ -1,28 +1,27 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; -import {Utils} from './utils/Utils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { Utils } from "./utils/Utils"; -const EMPTY_TITLE_FAILURE_STRING: string = 'Title elements must not be empty'; -const LONG_TITLE_FAILURE_STRING: string = 'Title length must not be longer than 60 characters'; -const WORD_TITLE_FAILURE_STRING: string = 'Title must contain more than one word'; +const EMPTY_TITLE_FAILURE_STRING: string = "Title elements must not be empty"; +const LONG_TITLE_FAILURE_STRING: string = "Title length must not be longer than 60 characters"; +const WORD_TITLE_FAILURE_STRING: string = "Title must contain more than one word"; const MAX_TITLE_LENGTH: number = 60; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-a11y-titles', - type: 'functionality', - description: 'For accessibility of your website, HTML title elements must be concise and non-empty.', + ruleName: "react-a11y-titles", + type: "functionality", + description: "For accessibility of your website, HTML title elements must be concise and non-empty.", options: null, // tslint:disable-line:no-null-keyword - optionsDescription: '', + optionsDescription: "", typescriptOnly: true, - issueClass: 'Non-SDL', - issueType: 'Warning', - severity: 'Moderate', - level: 'Opportunity for Excellence', - group: 'Accessibility' + issueClass: "Non-SDL", + issueType: "Warning", + severity: "Moderate", + level: "Opportunity for Excellence", + group: "Accessibility" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -35,21 +34,18 @@ export class Rule extends Lint.Rules.AbstractRule { } class ReactA11yTitlesRuleWalker extends Lint.RuleWalker { - protected visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void { - if (node.tagName.getText() === 'title') { - this.addFailureAt(node.getStart(), - node.getWidth(), EMPTY_TITLE_FAILURE_STRING); + if (node.tagName.getText() === "title") { + this.addFailureAt(node.getStart(), node.getWidth(), EMPTY_TITLE_FAILURE_STRING); } super.visitJsxSelfClosingElement(node); } protected visitJsxElement(node: ts.JsxElement): void { const openingElement: ts.JsxOpeningElement = node.openingElement; - if (openingElement.tagName.getText() === 'title') { + if (openingElement.tagName.getText() === "title") { if (node.children.length === 0) { - this.addFailureAt(node.getStart(), - node.getWidth(), EMPTY_TITLE_FAILURE_STRING); + this.addFailureAt(node.getStart(), node.getWidth(), EMPTY_TITLE_FAILURE_STRING); } else if (node.children.length === 1) { if (node.children[0].kind === ts.SyntaxKind.JsxText) { const value: ts.JsxText = node.children[0]; @@ -67,15 +63,9 @@ class ReactA11yTitlesRuleWalker extends Lint.RuleWalker { private validateTitleText(text: string, titleNode: ts.Node): void { if (text.length > MAX_TITLE_LENGTH) { - this.addFailureAt( - titleNode.getStart(), - titleNode.getWidth(), - LONG_TITLE_FAILURE_STRING + ': ' + Utils.trimTo(text, 20)); - } else if (!(text.indexOf(' ') > 0)) { - this.addFailureAt( - titleNode.getStart(), - titleNode.getWidth(), - WORD_TITLE_FAILURE_STRING + ': ' + Utils.trimTo(text, 20)); + this.addFailureAt(titleNode.getStart(), titleNode.getWidth(), LONG_TITLE_FAILURE_STRING + ": " + Utils.trimTo(text, 20)); + } else if (!(text.indexOf(" ") > 0)) { + this.addFailureAt(titleNode.getStart(), titleNode.getWidth(), WORD_TITLE_FAILURE_STRING + ": " + Utils.trimTo(text, 20)); } } } diff --git a/src/reactAnchorBlankNoopenerRule.ts b/src/reactAnchorBlankNoopenerRule.ts index be719bcf0..37b359497 100644 --- a/src/reactAnchorBlankNoopenerRule.ts +++ b/src/reactAnchorBlankNoopenerRule.ts @@ -1,41 +1,38 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import { ExtendedMetadata } from './utils/ExtendedMetadata'; -import { Utils } from './utils/Utils'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { Utils } from "./utils/Utils"; -import { getJsxAttributesFromJsxElement, - getStringLiteral, - isEmpty } from './utils/JsxAttribute'; +import { getJsxAttributesFromJsxElement, getStringLiteral, isEmpty } from "./utils/JsxAttribute"; -const OPTION_FORCE_REL_REDUNDANCY = 'force-rel-redundancy'; +const OPTION_FORCE_REL_REDUNDANCY = "force-rel-redundancy"; export class Rule extends Lint.Rules.AbstractRule { - public static metadata: ExtendedMetadata = { - ruleName: 'react-anchor-blank-noopener', - type: 'functionality', + ruleName: "react-anchor-blank-noopener", + type: "functionality", description: 'Anchor tags with target="_blank" should also include rel="noreferrer"', options: { - type: 'array', + type: "array", items: { - type: 'string', - enum: [OPTION_FORCE_REL_REDUNDANCY] + type: "string", + enum: [OPTION_FORCE_REL_REDUNDANCY] }, minLength: 0, maxLength: 1 - }, + }, optionsDescription: `One argument may be optionally provided: \n\n' + '* \`${OPTION_FORCE_REL_REDUNDANCY}\` ignores the default \`rel="noreferrer"\` behaviour which implies \`rel="noreferrer noopener"\`. Instead, force redundancy for \`rel\` attribute.`, typescriptOnly: true, - issueClass: 'SDL', - issueType: 'Error', - severity: 'Critical', - level: 'Mandatory', - group: 'Security', - commonWeaknessEnumeration: '242,676' + issueClass: "SDL", + issueType: "Error", + severity: "Critical", + level: "Mandatory", + group: "Security", + commonWeaknessEnumeration: "242,676" }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -48,7 +45,6 @@ export class Rule extends Lint.Rules.AbstractRule { } class ReactAnchorBlankNoopenerRuleWalker extends Lint.RuleWalker { - private readonly forceRelRedundancy: boolean = false; private readonly failureString: string = 'Anchor tags with target="_blank" should also include rel="noreferrer"'; @@ -74,14 +70,13 @@ class ReactAnchorBlankNoopenerRuleWalker extends Lint.RuleWalker { } private validateOpeningElement(openingElement: ts.JsxOpeningLikeElement): void { - if (openingElement.tagName.getText() === 'a') { - + if (openingElement.tagName.getText() === "a") { const allAttributes: { [propName: string]: ts.JsxAttribute } = getJsxAttributesFromJsxElement(openingElement); /* tslint:disable:no-string-literal */ - const target: ts.JsxAttribute = allAttributes['target']; - const rel: ts.JsxAttribute = allAttributes['rel']; + const target: ts.JsxAttribute = allAttributes["target"]; + const rel: ts.JsxAttribute = allAttributes["rel"]; /* tslint:enable:no-string-literal */ - if (target !== undefined && getStringLiteral(target) === '_blank' && !isRelAttributeValue(rel, this.forceRelRedundancy)) { + if (target !== undefined && getStringLiteral(target) === "_blank" && !isRelAttributeValue(rel, this.forceRelRedundancy)) { this.addFailureAt(openingElement.getStart(), openingElement.getWidth(), this.failureString); } } @@ -107,7 +102,7 @@ function isRelAttributeValue(attribute: ts.JsxAttribute, forceRedundancy: boolea const relValues: string[] = stringValue.split(/\s+/); - return forceRedundancy ? - Utils.contains(relValues, 'noreferrer') && Utils.contains(relValues, 'noopener') : - Utils.contains(relValues, 'noreferrer'); + return forceRedundancy + ? Utils.contains(relValues, "noreferrer") && Utils.contains(relValues, "noopener") + : Utils.contains(relValues, "noreferrer"); } diff --git a/src/reactIframeMissingSandboxRule.ts b/src/reactIframeMissingSandboxRule.ts index 082c161be..ae08d9405 100644 --- a/src/reactIframeMissingSandboxRule.ts +++ b/src/reactIframeMissingSandboxRule.ts @@ -1,44 +1,43 @@ -import * as ts from 'typescript'; -import * as Lint from 'tslint'; +import * as ts from "typescript"; +import * as Lint from "tslint"; -import {ExtendedMetadata} from './utils/ExtendedMetadata'; +import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -const FAILURE_NOT_FOUND: string = 'An iframe element requires a sandbox attribute'; -const FAILURE_INVALID_ENTRY: string = 'An iframe element defines an invalid sandbox attribute: '; -const FAILURE_INVALID_COMBINATION: string = 'An iframe element defines a sandbox with both allow-scripts and allow-same-origin'; +const FAILURE_NOT_FOUND: string = "An iframe element requires a sandbox attribute"; +const FAILURE_INVALID_ENTRY: string = "An iframe element defines an invalid sandbox attribute: "; +const FAILURE_INVALID_COMBINATION: string = "An iframe element defines a sandbox with both allow-scripts and allow-same-origin"; // If specified as an empty string, this attribute enables extra restrictions on the content that can // appear in the inline frame. The value of the attribute can either be an empty string (all the restrictions // are applied), or a space-separated list of tokens that lift particular restrictions. // Setting both 'allow-scripts'; and 'allow-same-origin' for a single @@ -39,11 +38,11 @@ describe('reactIframeMissingSandboxRule', () : void => { `; - TestHelper.assertViolations(ruleName, script, [ ]); + TestHelper.assertViolations(ruleName, script, []); }); - it('should pass on empty single attribute - self closing tag', () : void => { - const script : string = ` + it("should pass on empty single attribute - self closing tag", (): void => { + const script: string = ` import React = require('react'); @@ -68,11 +67,11 @@ describe('reactIframeMissingSandboxRule', () : void => { `; - TestHelper.assertViolations(ruleName, script, [ ]); + TestHelper.assertViolations(ruleName, script, []); }); - it('should fail on missing attribute', () : void => { - const script : string = ` + it("should fail on missing attribute", (): void => { + const script: string = ` import React = require('react'); @@ -41,7 +41,7 @@ describe("reactIframeMissingSandboxRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass on empty single attribute - self closing tag", (): void => { + it('should pass on empty single attribute - self closing tag', (): void => { const script: string = ` import React = require('react'); @@ -70,7 +70,7 @@ describe("reactIframeMissingSandboxRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should fail on missing attribute", (): void => { + it('should fail on missing attribute', (): void => { const script: string = ` import React = require('react'); @@ -79,21 +79,21 @@ describe("reactIframeMissingSandboxRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "An iframe element requires a sandbox attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element requires a sandbox attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 13, line: 3 } }, { - failure: "An iframe element requires a sandbox attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element requires a sandbox attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 13, line: 4 } } ]); }); - it("should fail on invalid attribute", (): void => { + it('should fail on invalid attribute', (): void => { const script: string = ` import React = require('react'); @@ -104,27 +104,27 @@ describe("reactIframeMissingSandboxRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "An iframe element defines an invalid sandbox attribute: __unknown__", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines an invalid sandbox attribute: __unknown__', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 3 } }, { - failure: "An iframe element defines an invalid sandbox attribute: __unknown__", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines an invalid sandbox attribute: __unknown__', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 4 } }, { - failure: "An iframe element defines an invalid sandbox attribute: __unknown__", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines an invalid sandbox attribute: __unknown__', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 5 } }, { - failure: "An iframe element defines an invalid sandbox attribute: __unknown__", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines an invalid sandbox attribute: __unknown__', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 6 } } ]); @@ -139,15 +139,15 @@ describe("reactIframeMissingSandboxRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "An iframe element defines a sandbox with both allow-scripts and allow-same-origin", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines a sandbox with both allow-scripts and allow-same-origin', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 3 } }, { - failure: "An iframe element defines a sandbox with both allow-scripts and allow-same-origin", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-iframe-missing-sandbox", + failure: 'An iframe element defines a sandbox with both allow-scripts and allow-same-origin', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-iframe-missing-sandbox', startPosition: { character: 29, line: 4 } } ]); diff --git a/src/tests/ReactNoDangerousHtmlRuleTests.ts b/src/tests/ReactNoDangerousHtmlRuleTests.ts index a42a2c7ad..05dec3560 100644 --- a/src/tests/ReactNoDangerousHtmlRuleTests.ts +++ b/src/tests/ReactNoDangerousHtmlRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("reactNoDangerousHtmlRule", (): void => { - const ruleName: string = "react-no-dangerous-html"; +describe('reactNoDangerousHtmlRule', (): void => { + const ruleName: string = 'react-no-dangerous-html'; - it("should find violations in .tsx files", (): void => { + it('should find violations in .tsx files', (): void => { TestHelper.assertViolations( ruleName, `import React = require('react'); @@ -23,25 +23,25 @@ function someFunction() { { failure: 'Invalid call to dangerouslySetInnerHTML in method ""\n of source file ' + - Utils.absolutePath("file.tsx") + + Utils.absolutePath('file.tsx') + '"\n Do *NOT* add a suppression for this warning. ' + - "If you absolutely must use this API then you need\n to review the usage with a security expert/QE " + - "representative. If they decide that this is an\n acceptable usage then add the exception " + - "to xss_exceptions.json", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-no-dangerous-html", + 'If you absolutely must use this API then you need\n to review the usage with a security expert/QE ' + + 'representative. If they decide that this is an\n acceptable usage then add the exception ' + + 'to xss_exceptions.json', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-no-dangerous-html', startPosition: { character: 1, line: 5 } }, { failure: 'Invalid call to dangerouslySetInnerHTML in method ""\n of source file ' + - Utils.absolutePath("file.tsx") + + Utils.absolutePath('file.tsx') + '"\n Do *NOT* add a suppression for this warning. ' + - "If you absolutely must use this API then you need\n to review the usage with a security expert/QE " + - "representative. If they decide that this is an\n acceptable usage then add the exception " + - "to xss_exceptions.json", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-no-dangerous-html", + 'If you absolutely must use this API then you need\n to review the usage with a security expert/QE ' + + 'representative. If they decide that this is an\n acceptable usage then add the exception ' + + 'to xss_exceptions.json', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-no-dangerous-html', startPosition: { character: 12, line: 10 } } ] diff --git a/src/tests/ReactThisBindingIssueRuleTests.ts b/src/tests/ReactThisBindingIssueRuleTests.ts index 0b0432fb2..39525f8ed 100644 --- a/src/tests/ReactThisBindingIssueRuleTests.ts +++ b/src/tests/ReactThisBindingIssueRuleTests.ts @@ -1,142 +1,142 @@ -import { TestHelper } from "./TestHelper"; +import { TestHelper } from './TestHelper'; -describe("reactThisBindingIssueRule", (): void => { - const ruleName: string = "react-this-binding-issue"; +describe('reactThisBindingIssueRule', (): void => { + const ruleName: string = 'react-this-binding-issue'; - it("should pass on passing input", (): void => { - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx"; + it('should pass on passing input', (): void => { + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx'; TestHelper.assertViolations(ruleName, file, []); - const fileWithDecorator: string = "test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx"; - TestHelper.assertNoViolationWithOptions(ruleName, [true, { "bind-decorators": ["autobind"] }], fileWithDecorator); + const fileWithDecorator: string = 'test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx'; + TestHelper.assertNoViolationWithOptions(ruleName, [true, { 'bind-decorators': ['autobind'] }], fileWithDecorator); }); - it("should fail if decorator is not whitelisted in config", () => { - const fileWithDecorator: string = "test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx"; + it('should fail if decorator is not whitelisted in config', () => { + const fileWithDecorator: string = 'test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx'; const expectedMsg = `A class method is passed as a JSX attribute without having the 'this' reference bound: `; TestHelper.assertViolationsWithOptions(ruleName, [true], fileWithDecorator, [ { - ruleName: "react-this-binding-issue", + ruleName: 'react-this-binding-issue', name: fileWithDecorator, - failure: expectedMsg + "this.listener1", - startPosition: { line: 24, character: 22 } + failure: expectedMsg + 'this.listener1', + startPosition: { line: 20, character: 27 } } ]); }); - it("should fail on double binding", (): void => { - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx"; + it('should fail on double binding', (): void => { + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx'; TestHelper.assertViolations(ruleName, file, [ { failure: "A function is having its 'this' reference bound twice in the constructor: " + - "this.listener = this.listener.bind(this)", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx", - ruleName: "react-this-binding-issue", - startPosition: { character: 9, line: 8 } + 'this.listener = this.listener.bind(this)', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx', + ruleName: 'react-this-binding-issue', + startPosition: { character: 9, line: 7 } } ]); }); - it("should fail on unbound listener", (): void => { - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx"; + it('should fail on unbound listener', (): void => { + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx'; TestHelper.assertViolations(ruleName, file, [ { failure: "A class method is passed as a JSX attribute without having the 'this' reference bound: this.listener", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx", - ruleName: "react-this-binding-issue", - startPosition: { character: 22, line: 11 } + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx', + ruleName: 'react-this-binding-issue', + startPosition: { character: 27, line: 9 } }, { failure: "A class method is passed as a JSX attribute without having the 'this' reference bound: this.listener", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx", - ruleName: "react-this-binding-issue", + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 28, line: 14 } } ]); }); - it("should fail on anonymous listeners", (): void => { - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx"; + it('should fail on anonymous listeners', (): void => { + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx'; TestHelper.assertViolations(ruleName, file, [ { - failure: "A new instance of an anonymous method is passed as a JSX attribute: this.listener.bind(this)", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx", - ruleName: "react-this-binding-issue", - startPosition: { character: 35, line: 11 } + failure: 'A new instance of an anonymous method is passed as a JSX attribute: this.listener.bind(this)', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx', + ruleName: 'react-this-binding-issue', + startPosition: { character: 32, line: 10 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: _.bind(this.listener, this)", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: _.bind(this.listener, this)', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 35, line: 12 } }, { failure: "A new instance of an anonymous method is passed as a JSX attribute: this.listener.bind(this, 'so...", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx", - ruleName: "react-this-binding-issue", + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 35, line: 13 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: () => {}", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: () => {}', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 35, line: 16 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: function() {}", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: function() {}', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 35, line: 17 } } ]); }); - it("should fail on locally instantiated listeners", (): void => { - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx"; + it('should fail on locally instantiated listeners', (): void => { + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx'; TestHelper.assertViolations(ruleName, file, [ { - failure: "A new instance of an anonymous method is passed as a JSX attribute: listener1", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx", - ruleName: "react-this-binding-issue", - startPosition: { character: 22, line: 14 } + failure: 'A new instance of an anonymous method is passed as a JSX attribute: listener1', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx', + ruleName: 'react-this-binding-issue', + startPosition: { character: 30, line: 12 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: listener2", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: listener2', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 26, line: 15 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: listener3", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: listener3', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 26, line: 16 } }, { - failure: "A new instance of an anonymous method is passed as a JSX attribute: listener4", - name: "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx", - ruleName: "react-this-binding-issue", + failure: 'A new instance of an anonymous method is passed as a JSX attribute: listener4', + name: 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx', + ruleName: 'react-this-binding-issue', startPosition: { character: 25, line: 17 } } ]); }); - it("should pass on anonymous listeners when allow-anonymous-listeners is true", (): void => { - const options = [true, { "allow-anonymous-listeners": true }]; - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx"; + it('should pass on anonymous listeners when allow-anonymous-listeners is true', (): void => { + const options = [true, { 'allow-anonymous-listeners': true }]; + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx'; TestHelper.assertViolationsWithOptions(ruleName, options, file, []); }); - it("should pass on locally instantiated listeners when allow-anonymous-listeners is true", (): void => { - const options = [true, { "allow-anonymous-listeners": true }]; - const file: string = "test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx"; + it('should pass on locally instantiated listeners when allow-anonymous-listeners is true', (): void => { + const options = [true, { 'allow-anonymous-listeners': true }]; + const file: string = 'test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx'; TestHelper.assertViolationsWithOptions(ruleName, options, file, []); }); diff --git a/src/tests/ReactTsxCurlySpacingRuleTests.ts b/src/tests/ReactTsxCurlySpacingRuleTests.ts index 4fd9efcab..0cd57570c 100644 --- a/src/tests/ReactTsxCurlySpacingRuleTests.ts +++ b/src/tests/ReactTsxCurlySpacingRuleTests.ts @@ -1,12 +1,12 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("reactTsxCurlySpacing", () => { - const ruleName: string = "react-tsx-curly-spacing"; +describe('reactTsxCurlySpacing', () => { + const ruleName: string = 'react-tsx-curly-spacing'; - describe("should pass", () => { - describe("on single line expressions", () => { - it("when always set", () => { + describe('should pass', () => { + describe('on single line expressions', () => { + it('when always set', () => { const script: string = ` import React = require('react'); const a = ; @@ -14,42 +14,42 @@ describe("reactTsxCurlySpacing", () => { TestHelper.assertNoViolation(ruleName, script); }); - it("when never set", () => { + it('when never set', () => { const script: string = ` import React = require('react'); const a = ; const b =
{/* comment */}
; `; - TestHelper.assertViolationsWithOptions(ruleName, ["never"], script, []); + TestHelper.assertViolationsWithOptions(ruleName, ['never'], script, []); }); }); - describe("on multi-line expressions", () => { - it("when always set", () => { + describe('on multi-line expressions', () => { + it('when always set', () => { const script: string = ` import React = require('react'); `; - TestHelper.assertViolationsWithOptions(ruleName, ["always", { allowMultiline: true }], script, []); + TestHelper.assertViolationsWithOptions(ruleName, ['always', { allowMultiline: true }], script, []); }); - it("when never set", () => { + it('when never set', () => { const script: string = ` import React = require('react'); `; - TestHelper.assertViolationsWithOptions(ruleName, ["never", { allowMultiline: true }], script, []); + TestHelper.assertViolationsWithOptions(ruleName, ['never', { allowMultiline: true }], script, []); }); }); }); - describe("should fail", () => { - describe("on single line expressions", () => { - it("when always set", () => { + describe('should fail', () => { + describe('on single line expressions', () => { + it('when always set', () => { const script: string = ` import React = require('react'); @@ -60,103 +60,103 @@ describe("reactTsxCurlySpacing", () => { TestHelper.assertViolations(ruleName, script, [ { failure: "A space is required after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 4 } }, { failure: "A space is required before '}'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 4 } }, { failure: "A space is required before '}'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 5 } }, { failure: "A space is required after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 6 } } ]); }); - it("when never set", () => { + it('when never set', () => { const script: string = ` import React = require('react'); const a = ; const b = ; const c = ; `; - TestHelper.assertViolationsWithOptions(ruleName, ["never"], script, [ + TestHelper.assertViolationsWithOptions(ruleName, ['never'], script, [ { failure: "There should be no space after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 3 } }, { failure: "There should be no space before '}'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 4 } }, { failure: "There should be no space after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 43, line: 5 } } ]); }); }); - describe("on multi-line expressions", () => { - it("when always set", () => { + describe('on multi-line expressions', () => { + it('when always set', () => { const script: string = ` import React = require('react'); `; - TestHelper.assertViolationsWithOptions(ruleName, ["always", { allowMultiline: false }], script, [ + TestHelper.assertViolationsWithOptions(ruleName, ['always', { allowMultiline: false }], script, [ { failure: "There should be no newline after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 33, line: 3 } }, { failure: "There should be no newline before '}'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 33, line: 3 } } ]); }); - it("when never set", () => { + it('when never set', () => { const script: string = ` import React = require('react'); `; - TestHelper.assertViolationsWithOptions(ruleName, ["never"], script, [ + TestHelper.assertViolationsWithOptions(ruleName, ['never'], script, [ { failure: "There should be no newline after '{'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 33, line: 3 } }, { failure: "There should be no newline before '}'", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-tsx-curly-spacing", + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-tsx-curly-spacing', startPosition: { character: 33, line: 3 } } ]); diff --git a/src/tests/ReactUnusedPropsAndStateRuleTests.ts b/src/tests/ReactUnusedPropsAndStateRuleTests.ts index a4a61b822..a9e81aca8 100644 --- a/src/tests/ReactUnusedPropsAndStateRuleTests.ts +++ b/src/tests/ReactUnusedPropsAndStateRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("reactUnusedPropsAndStateRule", (): void => { - const ruleName: string = "react-unused-props-and-state"; +describe('reactUnusedPropsAndStateRule', (): void => { + const ruleName: string = 'react-unused-props-and-state'; - it("should pass on referenced Props and State", (): void => { + it('should pass on referenced Props and State', (): void => { const script: string = ` import React = require('react'); @@ -39,7 +39,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass on referenced Props and State functions", (): void => { + it('should pass on referenced Props and State functions', (): void => { const script: string = ` import React = require('react'); @@ -65,7 +65,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props and state escape the class/function", (): void => { + it('should pass when props and state escape the class/function', (): void => { const script: string = ` import React = require('react'); @@ -91,7 +91,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props referenced from constructor parameter", (): void => { + it('should pass when props referenced from constructor parameter', (): void => { const script: string = ` import React = require('react'); @@ -116,7 +116,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props referenced from constructor parameter", (): void => { + it('should pass when props referenced from constructor parameter', (): void => { const script: string = ` import React = require('react'); @@ -141,7 +141,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props referenced from lifecycle method ", (): void => { + it('should pass when props referenced from lifecycle method ', (): void => { const script: string = ` import React = require('react'); @@ -179,7 +179,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when state referenced from lifecycle method ", (): void => { + it('should pass when state referenced from lifecycle method ', (): void => { const script: string = ` import React = require('react'); @@ -213,7 +213,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when state escapes from shouldComponentUpdate", (): void => { + it('should pass when state escapes from shouldComponentUpdate', (): void => { const script: string = ` import React = require('react'); @@ -239,7 +239,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when state escapes from componentWillUpdate", (): void => { + it('should pass when state escapes from componentWillUpdate', (): void => { const script: string = ` import React = require('react'); @@ -264,7 +264,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when state escapes from componentDidUpdate", (): void => { + it('should pass when state escapes from componentDidUpdate', (): void => { const script: string = ` import React = require('react'); @@ -289,7 +289,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props escapes from componentWillReceiveProps ", (): void => { + it('should pass when props escapes from componentWillReceiveProps ', (): void => { const script: string = ` import React = require('react'); @@ -314,7 +314,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props escapes from shouldComponentUpdate ", (): void => { + it('should pass when props escapes from shouldComponentUpdate ', (): void => { const script: string = ` import React = require('react'); @@ -340,7 +340,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props escapes from componentWillUpdate", (): void => { + it('should pass when props escapes from componentWillUpdate', (): void => { const script: string = ` import React = require('react'); @@ -365,7 +365,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass when props escapes from componentDidUpdate ", (): void => { + it('should pass when props escapes from componentDidUpdate ', (): void => { const script: string = ` import React = require('react'); @@ -390,7 +390,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass on referenced Props and State even when interfaces defined at end", (): void => { + it('should pass on referenced Props and State even when interfaces defined at end', (): void => { const script: string = ` module SomeModule { export class SomeComponent extends SomeBaseComponent { @@ -415,7 +415,7 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should fail on unused Props and State", (): void => { + it('should fail on unused Props and State', (): void => { const script: string = ` import React = require('react'); @@ -444,33 +444,33 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unused React property defined in interface: myProp1", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProp1', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 6 } }, { - failure: "Unused React property defined in interface: myProp2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProp2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 7 } }, { - failure: "Unused React state defined in interface: myState1", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState1', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 10 } }, { - failure: "Unused React state defined in interface: myState2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 11 } } ]); }); - it("should fail on unused Props and State with custom names", (): void => { + it('should fail on unused Props and State with custom names', (): void => { const script: string = ` import React = require('react'); @@ -500,40 +500,40 @@ describe("reactUnusedPropsAndStateRule", (): void => { const options = [ true, { - "props-interface-regex": "Props$", - "state-interface-regex": "State$" + 'props-interface-regex': 'Props$', + 'state-interface-regex': 'State$' } ]; TestHelper.assertViolationsWithOptions(ruleName, options, script, [ { - failure: "Unused React property defined in interface: myProp1", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProp1', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 6 } }, { - failure: "Unused React property defined in interface: myProp2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProp2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 7 } }, { - failure: "Unused React state defined in interface: myState1", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState1', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 10 } }, { - failure: "Unused React state defined in interface: myState2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 11 } } ]); }); - it("should fail on unused Props and State functions", (): void => { + it('should fail on unused Props and State functions', (): void => { const script: string = ` import React = require('react'); @@ -556,21 +556,21 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unused React property defined in interface: myProp", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProp', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 6 } }, { - failure: "Unused React state defined in interface: myState", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 9 } } ]); }); - it("should fail when props are referenced in a ternary expression", (): void => { + it('should fail when props are referenced in a ternary expression', (): void => { const script: string = ` import React = require('react'); @@ -601,15 +601,15 @@ describe("reactUnusedPropsAndStateRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unused React property defined in interface: myProps2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React property defined in interface: myProps2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 13 } }, { - failure: "Unused React state defined in interface: myState2", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-unused-props-and-state", + failure: 'Unused React state defined in interface: myState2', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-unused-props-and-state', startPosition: { character: 21, line: 8 } } ]); diff --git a/src/tests/TestHelper.ts b/src/tests/TestHelper.ts index ed3a521c2..96cc0ffae 100644 --- a/src/tests/TestHelper.ts +++ b/src/tests/TestHelper.ts @@ -1,8 +1,8 @@ -import * as Lint from "tslint"; -import * as fs from "fs"; -import * as chai from "chai"; -import { Utils } from "../utils/Utils"; -import * as ts from "typescript"; +import * as Lint from 'tslint'; +import * as fs from 'fs'; +import * as chai from 'chai'; +import { Utils } from '../utils/Utils'; +import * as ts from 'typescript'; /** * Test Utilities. @@ -14,17 +14,17 @@ export namespace TestHelper { /** * This setting must point to your rule .js files. 3rd party libraries may reuse this class and change value. */ - export let RULES_DIRECTORY: string = "dist/src/"; + export let RULES_DIRECTORY: string = 'dist/src/'; /** * This setting must point to your formatter .js files. 3rd party libraries may reuse this class and change value. */ - export let FORMATTER_DIRECTORY: string = "customFormatters/"; + export let FORMATTER_DIRECTORY: string = 'customFormatters/'; /** * You must specify an encoding for file read/writes. 3rd party libraries may reuse this class and change value. */ - export let FILE_ENCODING: string = "utf8"; + export let FILE_ENCODING: string = 'utf8'; /* tslint:enable:prefer-const */ export interface FailurePosition { @@ -106,7 +106,7 @@ export namespace TestHelper { } const options: Lint.ILinterOptions = { - formatter: "json", + formatter: 'json', fix: false, rulesDirectory: RULES_DIRECTORY, formattersDirectory: FORMATTER_DIRECTORY @@ -125,10 +125,10 @@ export namespace TestHelper { result = linter.getResult(); } else { let filename: string; - if (inputFileOrScript.indexOf("import React") > -1) { - filename = Utils.absolutePath("file.tsx"); + if (inputFileOrScript.indexOf('import React') > -1) { + filename = Utils.absolutePath('file.tsx'); } else { - filename = Utils.absolutePath("file.ts"); + filename = Utils.absolutePath('file.ts'); } const linter = new Lint.Linter(options, useTypeChecker ? program : undefined); @@ -166,7 +166,7 @@ export namespace TestHelper { delete expected.startPosition.position; delete expected.endPosition; if (!expected.ruleSeverity) { - expected.ruleSeverity = "ERROR"; + expected.ruleSeverity = 'ERROR'; } } ); diff --git a/src/tests/TypeGuardTests.ts b/src/tests/TypeGuardTests.ts index bd18aa00d..69c958bcc 100644 --- a/src/tests/TypeGuardTests.ts +++ b/src/tests/TypeGuardTests.ts @@ -1,36 +1,36 @@ -import * as chai from "chai"; -import * as ts from "typescript"; -import { isNamed, isObject } from "../utils/TypeGuard"; +import * as chai from 'chai'; +import * as ts from 'typescript'; +import { isNamed, isObject } from '../utils/TypeGuard'; /** * Unit tests. */ -describe("TypeGuards", (): void => { - describe("isObject", (): void => { - it("should handle objects.", (): void => { - chai.expect(isObject({ x: 1 })).to.equal(true, "object type is not considered object"); +describe('TypeGuards', (): void => { + describe('isObject', (): void => { + it('should handle objects.', (): void => { + chai.expect(isObject({ x: 1 })).to.equal(true, 'object type is not considered object'); }); - it("should handle non-objects.", (): void => { - chai.expect(isObject(true)).to.equal(false, "boolean type is considered object"); + it('should handle non-objects.', (): void => { + chai.expect(isObject(true)).to.equal(false, 'boolean type is considered object'); }); - it("should handle undefined.", (): void => { - chai.expect(isObject(undefined)).to.equal(false, "undefined is considered object"); + it('should handle undefined.', (): void => { + chai.expect(isObject(undefined)).to.equal(false, 'undefined is considered object'); }); - it("should handle arrays.", (): void => { - chai.expect(isObject([])).to.equal(false, "array is considered object"); + it('should handle arrays.', (): void => { + chai.expect(isObject([])).to.equal(false, 'array is considered object'); }); }); - describe("isNamed", (): void => { - it("should return true for nodes with a name.", (): void => { - const node = ts.createClassDeclaration([], [], "foo", [], [], []); - chai.expect(isNamed(node)).to.equal(true, "named node is not considered named"); + describe('isNamed', (): void => { + it('should return true for nodes with a name.', (): void => { + const node = ts.createClassDeclaration([], [], 'foo', [], [], []); + chai.expect(isNamed(node)).to.equal(true, 'named node is not considered named'); }); - it("should return false for nodes with undefined name.", (): void => { + it('should return false for nodes with undefined name.', (): void => { const node = ts.createFunctionDeclaration( [], [], @@ -41,12 +41,12 @@ describe("TypeGuards", (): void => { undefined, undefined ); - chai.expect(isNamed(node)).to.equal(false, "unnamed node is considered named"); + chai.expect(isNamed(node)).to.equal(false, 'unnamed node is considered named'); }); - it("should return false for nodes without a name.", (): void => { + it('should return false for nodes without a name.', (): void => { const node = ts.createArrayLiteral([], false); - chai.expect(isNamed(node)).to.equal(false, "unnamed node is considered named"); + chai.expect(isNamed(node)).to.equal(false, 'unnamed node is considered named'); }); }); }); diff --git a/src/tests/UnderscoreConsistentInvocationRuleTests.ts b/src/tests/UnderscoreConsistentInvocationRuleTests.ts index ecfabe9ba..67719173d 100644 --- a/src/tests/UnderscoreConsistentInvocationRuleTests.ts +++ b/src/tests/UnderscoreConsistentInvocationRuleTests.ts @@ -1,13 +1,13 @@ /* tslint:disable:max-line-length */ /* tslint:disable:max-func-body-length */ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("underscoreConsistentInvocationRule", (): void => { - const ruleName: string = "underscore-consistent-invocation"; +describe('underscoreConsistentInvocationRule', (): void => { + const ruleName: string = 'underscore-consistent-invocation'; - it("should pass on wrapping functions in a new instance when style is instance", (): void => { + it('should pass on wrapping functions in a new instance when style is instance', (): void => { const script: string = ` _(list).each(() => { return undefined; }); _(list).forEach(() => { return undefined; }); @@ -74,7 +74,7 @@ describe("underscoreConsistentInvocationRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should pass on invoking the underscore methods statically when style is static", (): void => { + it('should pass on invoking the underscore methods statically when style is static', (): void => { const script: string = ` _.each(list, () => { return undefined; }); _.forEach(list, () => { return undefined; }); @@ -138,10 +138,10 @@ describe("underscoreConsistentInvocationRule", (): void => { _.range(list, () => { return undefined; }); `; - TestHelper.assertViolationsWithOptions(ruleName, [true, { style: "static" }], script, []); + TestHelper.assertViolationsWithOptions(ruleName, [true, { style: 'static' }], script, []); }); - it("should fail on invoking the underscore methods statically when style is instance", (): void => { + it('should fail on invoking the underscore methods statically when style is instance', (): void => { const script: string = ` _.each(list, () => { return undefined; }); _.forEach(list, () => { return undefined; }); @@ -207,369 +207,369 @@ describe("underscoreConsistentInvocationRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.each", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.each', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 2 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.forEach", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.forEach', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 3 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.map", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.map', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 4 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.collect", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.collect', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 5 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.reduce", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.reduce', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 6 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.inject", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.inject', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 7 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.foldl", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.foldl', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 8 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.reduceRight", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.reduceRight', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 9 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.foldr", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.foldr', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 10 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.find", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.find', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 11 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.detect", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.detect', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 12 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.filter", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.filter', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 13 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.select", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.select', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 14 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.where", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.where', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 15 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.findWhere", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.findWhere', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 16 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.reject", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.reject', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 17 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.every", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.every', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 18 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.all", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.all', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 19 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.some", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.some', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 20 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.any", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.any', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 21 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.contains", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.contains', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 22 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.include", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.include', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 23 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.invoke", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.invoke', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 24 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.pluck", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.pluck', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 25 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.max", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.max', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 26 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.min", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.min', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 27 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.sortBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.sortBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 28 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.groupBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.groupBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 29 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.indexBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.indexBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 30 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.countBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.countBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 31 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.shuffle", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.shuffle', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 32 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.sample", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.sample', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 33 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.toArray", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.toArray', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 34 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.size", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.size', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 35 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.partition", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.partition', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 36 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.first", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.first', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 37 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.head", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.head', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 38 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.take", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.take', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 39 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.initial", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.initial', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 40 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.last", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.last', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 41 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.rest", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.rest', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 42 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.tail", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.tail', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 43 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.drop", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.drop', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 44 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.compact", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.compact', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 45 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.flatten", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.flatten', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 46 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.without", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.without', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 47 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.union", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.union', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 48 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.intersection", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.intersection', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 49 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.difference", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.difference', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 50 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.uniq", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.uniq', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 51 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.unique", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.unique', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 52 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.object", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.object', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 53 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.zip", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.zip', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 54 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.unzip", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.unzip', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 55 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.indexOf", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.indexOf', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 56 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.findIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.findIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 57 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.lastIndexOf", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.lastIndexOf', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 58 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.findLastIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.findLastIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 59 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.sortedIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.sortedIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 60 } }, { - failure: "Static invocation of underscore function found. Prefer instance version instead: _.range", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Static invocation of underscore function found. Prefer instance version instead: _.range', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 61 } } ]); }); - it("should fail on wrapping functions in a new instance when style is static", (): void => { + it('should fail on wrapping functions in a new instance when style is static', (): void => { const script: string = ` _(list).each(() => { return undefined; }); _(list).forEach(() => { return undefined; }); @@ -633,366 +633,366 @@ describe("underscoreConsistentInvocationRule", (): void => { _(list).range(() => { return undefined; }); `; - TestHelper.assertViolationsWithOptions(ruleName, [true, { style: "static" }], script, [ + TestHelper.assertViolationsWithOptions(ruleName, [true, { style: 'static' }], script, [ { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).each", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).each', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 2 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).forEach", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).forEach', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 3 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).map", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).map', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 4 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).collect", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).collect', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 5 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reduce", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reduce', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 6 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).inject", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).inject', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 7 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).foldl", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).foldl', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 8 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reduceRight", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reduceRight', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 9 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).foldr", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).foldr', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 10 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).find", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).find', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 11 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).detect", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).detect', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 12 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).filter", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).filter', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 13 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).select", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).select', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 14 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).where", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).where', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 15 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findWhere", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findWhere', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 16 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reject", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).reject', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 17 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).every", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).every', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 18 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).all", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).all', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 19 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).some", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).some', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 20 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).any", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).any', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 21 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).contains", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).contains', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 22 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).include", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).include', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 23 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).invoke", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).invoke', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 24 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).pluck", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).pluck', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 25 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).max", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).max', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 26 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).min", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).min', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 27 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sortBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sortBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 28 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).groupBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).groupBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 29 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).indexBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).indexBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 30 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).countBy", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).countBy', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 31 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).shuffle", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).shuffle', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 32 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sample", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sample', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 33 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).toArray", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).toArray', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 34 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).size", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).size', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 35 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).partition", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).partition', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 36 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).first", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).first', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 37 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).head", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).head', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 38 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).take", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).take', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 39 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).initial", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).initial', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 40 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).last", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).last', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 41 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).rest", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).rest', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 42 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).tail", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).tail', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 43 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).drop", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).drop', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 44 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).compact", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).compact', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 45 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).flatten", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).flatten', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 46 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).without", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).without', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 47 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).union", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).union', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 48 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).intersection", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).intersection', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 49 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).difference", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).difference', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 50 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).uniq", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).uniq', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 51 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).unique", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).unique', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 52 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).object", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).object', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 53 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).zip", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).zip', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 54 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).unzip", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).unzip', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 55 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).indexOf", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).indexOf', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 56 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 57 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).lastIndexOf", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).lastIndexOf', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 58 } }, { failure: - "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findLastIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).findLastIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 59 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sortedIndex", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).sortedIndex', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 60 } }, { - failure: "Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).range", - name: Utils.absolutePath("file.ts"), - ruleName: "underscore-consistent-invocation", + failure: 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: _(list).range', + name: Utils.absolutePath('file.ts'), + ruleName: 'underscore-consistent-invocation', startPosition: { character: 13, line: 61 } } ]); diff --git a/src/tests/UnnecessaryLocalVariableRuleTests.ts b/src/tests/UnnecessaryLocalVariableRuleTests.ts index a40c7cf94..e70db1793 100644 --- a/src/tests/UnnecessaryLocalVariableRuleTests.ts +++ b/src/tests/UnnecessaryLocalVariableRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("unnecessaryLocalVariableRule", (): void => { - const ruleName: string = "no-unnecessary-local-variable"; +describe('unnecessaryLocalVariableRule', (): void => { + const ruleName: string = 'no-unnecessary-local-variable'; - it("should pass on good usages", (): void => { + it('should pass on good usages', (): void => { const script: string = ` class MyClass { private myMethod1() { @@ -22,7 +22,7 @@ describe("unnecessaryLocalVariableRule", (): void => { }); // issue #381 - it("should pass on recursive variables", (): void => { + it('should pass on recursive variables', (): void => { const script: string = ` const balls = { foo: 'foo', @@ -34,7 +34,7 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should fail on class function", (): void => { + it('should fail on class function', (): void => { const script: string = ` class MyClass { private myMethod() { @@ -46,15 +46,15 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 21, line: 4 } } ]); }); - it("should fail on if statement inside function", (): void => { + it('should fail on if statement inside function', (): void => { const script: string = ` class MyClass { private myMethod() { @@ -69,15 +69,15 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 25, line: 5 } } ]); }); - it("should fail on statements inside source file", (): void => { + it('should fail on statements inside source file', (): void => { const script: string = ` let x = 1; return x; @@ -85,15 +85,15 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 13, line: 2 } } ]); }); - it("should fail on statements inside module", (): void => { + it('should fail on statements inside module', (): void => { const script: string = ` module MyModule { let x = 1; @@ -103,15 +103,15 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 17, line: 3 } } ]); }); - it("should fail on statements inside case clause", (): void => { + it('should fail on statements inside case clause', (): void => { const script: string = ` switch (whatever) { case 1: @@ -122,15 +122,15 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 21, line: 4 } } ]); }); - it("should fail on statements inside default clause of switch statement", (): void => { + it('should fail on statements inside default clause of switch statement', (): void => { const script: string = ` switch (whatever) { default: @@ -141,9 +141,9 @@ describe("unnecessaryLocalVariableRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary local variable: x", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-local-variable", + failure: 'Unnecessary local variable: x', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-local-variable', startPosition: { character: 21, line: 4 } } ]); diff --git a/src/tests/UseNamedParameterRuleTests.ts b/src/tests/UseNamedParameterRuleTests.ts index d50f25369..611122374 100644 --- a/src/tests/UseNamedParameterRuleTests.ts +++ b/src/tests/UseNamedParameterRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("useNamedParameterRule", (): void => { - const ruleName: string = "use-named-parameter"; +describe('useNamedParameterRule', (): void => { + const ruleName: string = 'use-named-parameter'; - it("should ban referencing arguments by numeric index", (): void => { + it('should ban referencing arguments by numeric index', (): void => { const inputScript: string = ` function add() { return arguments[0] + arguments[1]; @@ -13,20 +13,20 @@ function add() { TestHelper.assertViolations(ruleName, inputScript, [ { failure: "Use a named parameter instead: 'arguments[0]'", - name: Utils.absolutePath("file.ts"), - ruleName: "use-named-parameter", + name: Utils.absolutePath('file.ts'), + ruleName: 'use-named-parameter', startPosition: { character: 12, line: 3 } }, { failure: "Use a named parameter instead: 'arguments[1]'", - name: Utils.absolutePath("file.ts"), - ruleName: "use-named-parameter", + name: Utils.absolutePath('file.ts'), + ruleName: 'use-named-parameter', startPosition: { character: 27, line: 3 } } ]); }); - it("should allow referencing arguments by variable index", (): void => { + it('should allow referencing arguments by variable index', (): void => { const inputScript: string = ` function add() { return arguments[whatever()] + arguments[n]; diff --git a/src/tests/UtilsTests.ts b/src/tests/UtilsTests.ts index 86c74c712..681da9c40 100644 --- a/src/tests/UtilsTests.ts +++ b/src/tests/UtilsTests.ts @@ -1,77 +1,77 @@ -import { Utils } from "../utils/Utils"; -import * as chai from "chai"; +import { Utils } from '../utils/Utils'; +import * as chai from 'chai'; -describe("Utils", (): void => { - describe("contains", (): void => { - it("should handle empty states", (): void => { +describe('Utils', (): void => { + describe('contains', (): void => { + it('should handle empty states', (): void => { // tslint:disable-next-line:no-null-keyword - chai.expect(Utils.contains([], null)).to.equal(false, "empty array should not contain false"); - chai.expect(Utils.contains([], undefined)).to.equal(false, "empty array should not contain undefined"); - chai.expect(Utils.contains(undefined, undefined)).to.equal(false, "undefined should not contain undefined"); + chai.expect(Utils.contains([], null)).to.equal(false, 'empty array should not contain false'); + chai.expect(Utils.contains([], undefined)).to.equal(false, 'empty array should not contain undefined'); + chai.expect(Utils.contains(undefined, undefined)).to.equal(false, 'undefined should not contain undefined'); }); - it("should handle numbers", (): void => { - chai.expect(Utils.contains([1, 2, 3], 1)).to.equal(true, "array containing 1 should contain 1"); - chai.expect(Utils.contains([1, 2, 3], 0)).to.equal(false, "array containing 1 should not contain 0"); + it('should handle numbers', (): void => { + chai.expect(Utils.contains([1, 2, 3], 1)).to.equal(true, 'array containing 1 should contain 1'); + chai.expect(Utils.contains([1, 2, 3], 0)).to.equal(false, 'array containing 1 should not contain 0'); }); - it("should handle strings", (): void => { - chai.expect(Utils.contains(["a", "b", "c"], "a")).to.equal(true, "array containing 'a' should contain 'a'"); - chai.expect(Utils.contains(["a", "b", "c"], "z")).to.equal(false, "array containing 'a' should not contain 'z'"); + it('should handle strings', (): void => { + chai.expect(Utils.contains(['a', 'b', 'c'], 'a')).to.equal(true, "array containing 'a' should contain 'a'"); + chai.expect(Utils.contains(['a', 'b', 'c'], 'z')).to.equal(false, "array containing 'a' should not contain 'z'"); }); - it("should handle objects", (): void => { + it('should handle objects', (): void => { const obj1: Object = {}; const obj2: Object = {}; const obj3: Object = {}; const objList = [obj1, obj2]; - chai.expect(Utils.contains(objList, obj1)).to.equal(true, "object equality test for obj1"); - chai.expect(Utils.contains(objList, obj2)).to.equal(true, "object equality test for obj2"); - chai.expect(Utils.contains(objList, obj3)).to.equal(false, "object equality test for obj3"); + chai.expect(Utils.contains(objList, obj1)).to.equal(true, 'object equality test for obj1'); + chai.expect(Utils.contains(objList, obj2)).to.equal(true, 'object equality test for obj2'); + chai.expect(Utils.contains(objList, obj3)).to.equal(false, 'object equality test for obj3'); }); }); - describe("removeAll", (): void => { - it("should handle empty states", (): void => { - chai.expect(Utils.removeAll([], undefined)).to.deep.equal([], "remove undefined from empty array"); - chai.expect(Utils.removeAll(undefined, undefined)).to.deep.equal([], "remove undefined from undefined"); + describe('removeAll', (): void => { + it('should handle empty states', (): void => { + chai.expect(Utils.removeAll([], undefined)).to.deep.equal([], 'remove undefined from empty array'); + chai.expect(Utils.removeAll(undefined, undefined)).to.deep.equal([], 'remove undefined from undefined'); }); - it("should handle numbers", (): void => { - chai.expect(Utils.removeAll([1, 2, 3], [1])).to.deep.equal([2, 3], "removing number"); - chai.expect(Utils.removeAll([1, 2, 3], [1, 2])).to.deep.equal([3], "removing two numbers"); - chai.expect(Utils.removeAll([1, 2, 3], [1, 2, 3])).to.deep.equal([], "removing all numbers"); - chai.expect(Utils.removeAll([1, 2, 3], [4, 5, 6])).to.deep.equal([1, 2, 3], "removing non-contained numbers"); + it('should handle numbers', (): void => { + chai.expect(Utils.removeAll([1, 2, 3], [1])).to.deep.equal([2, 3], 'removing number'); + chai.expect(Utils.removeAll([1, 2, 3], [1, 2])).to.deep.equal([3], 'removing two numbers'); + chai.expect(Utils.removeAll([1, 2, 3], [1, 2, 3])).to.deep.equal([], 'removing all numbers'); + chai.expect(Utils.removeAll([1, 2, 3], [4, 5, 6])).to.deep.equal([1, 2, 3], 'removing non-contained numbers'); }); - it("should handle strings", (): void => { - chai.expect(Utils.removeAll(["a", "b", "c"], ["a"])).to.deep.equal(["b", "c"], "removing string"); - chai.expect(Utils.removeAll(["a", "b", "c"], ["a", "b"])).to.deep.equal(["c"], "removing two string"); - chai.expect(Utils.removeAll(["a", "b", "c"], ["a", "b", "c"])).to.deep.equal([], "removing all strings"); - chai.expect(Utils.removeAll(["a", "b", "c"], ["x", "y", "z"])).to.deep.equal(["a", "b", "c"], "removing non-contained strings"); + it('should handle strings', (): void => { + chai.expect(Utils.removeAll(['a', 'b', 'c'], ['a'])).to.deep.equal(['b', 'c'], 'removing string'); + chai.expect(Utils.removeAll(['a', 'b', 'c'], ['a', 'b'])).to.deep.equal(['c'], 'removing two string'); + chai.expect(Utils.removeAll(['a', 'b', 'c'], ['a', 'b', 'c'])).to.deep.equal([], 'removing all strings'); + chai.expect(Utils.removeAll(['a', 'b', 'c'], ['x', 'y', 'z'])).to.deep.equal(['a', 'b', 'c'], 'removing non-contained strings'); }); - it("should handle objects", (): void => { + it('should handle objects', (): void => { const obj1: Object = {}; const obj2: Object = {}; const obj3: Object = {}; const objList: Object[] = [obj1, obj2, obj3]; - chai.expect(Utils.removeAll(objList, [obj1])).to.deep.equal([obj2, obj2], "removing object"); - chai.expect(Utils.removeAll(objList, [obj1, obj3])).to.deep.equal([obj2], "removing two objects"); - chai.expect(Utils.removeAll(objList, [obj1, obj2, obj3])).to.deep.equal([], "removing all objects"); - chai.expect(Utils.removeAll(objList, [{}, {}, {}])).to.deep.equal([obj1, obj2, obj3], "removing non-contained objects"); + chai.expect(Utils.removeAll(objList, [obj1])).to.deep.equal([obj2, obj2], 'removing object'); + chai.expect(Utils.removeAll(objList, [obj1, obj3])).to.deep.equal([obj2], 'removing two objects'); + chai.expect(Utils.removeAll(objList, [obj1, obj2, obj3])).to.deep.equal([], 'removing all objects'); + chai.expect(Utils.removeAll(objList, [{}, {}, {}])).to.deep.equal([obj1, obj2, obj3], 'removing non-contained objects'); }); }); - it("should trim strings properly", (): void => { - chai.expect(Utils.trimTo(undefined, 10)).to.equal(""); - chai.expect(Utils.trimTo("", 10)).to.equal(""); - chai.expect(Utils.trimTo("123456789", 10)).to.equal("123456789"); - chai.expect(Utils.trimTo("1234567890", 10)).to.equal("1234567890"); - chai.expect(Utils.trimTo("12345678901", 10)).to.equal("12345678..."); - chai.expect(Utils.trimTo("123456789012", 10)).to.equal("12345678..."); - chai.expect(Utils.trimTo("12345678901234567890", 10)).to.equal("12345678..."); + it('should trim strings properly', (): void => { + chai.expect(Utils.trimTo(undefined, 10)).to.equal(''); + chai.expect(Utils.trimTo('', 10)).to.equal(''); + chai.expect(Utils.trimTo('123456789', 10)).to.equal('123456789'); + chai.expect(Utils.trimTo('1234567890', 10)).to.equal('1234567890'); + chai.expect(Utils.trimTo('12345678901', 10)).to.equal('12345678...'); + chai.expect(Utils.trimTo('123456789012', 10)).to.equal('12345678...'); + chai.expect(Utils.trimTo('12345678901234567890', 10)).to.equal('12345678...'); }); }); diff --git a/src/tests/ValidTypeofRuleTests.ts b/src/tests/ValidTypeofRuleTests.ts index cb6f58532..c10965758 100644 --- a/src/tests/ValidTypeofRuleTests.ts +++ b/src/tests/ValidTypeofRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("validTypeofRule", (): void => { - const ruleName: string = "valid-typeof"; +describe('validTypeofRule', (): void => { + const ruleName: string = 'valid-typeof'; - it("should pass on valid typeofs", (): void => { + it('should pass on valid typeofs', (): void => { const script: string = ` typeof bar === "undefined" typeof bar == "undefined" @@ -26,7 +26,7 @@ describe("validTypeofRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should fail on invalid string with ===", (): void => { + it('should fail on invalid string with ===', (): void => { const script: string = ` typeof foo === "strnig" "strnig" === typeof foo @@ -34,15 +34,15 @@ describe("validTypeofRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Invalid comparison in typeof. Did you mean string?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean string?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 28, line: 2 } }, { - failure: "Invalid comparison in typeof. Did you mean string?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean string?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 13, line: 3 @@ -51,7 +51,7 @@ describe("validTypeofRule", (): void => { ]); }); - it("should fail on invalid string with ==", (): void => { + it('should fail on invalid string with ==', (): void => { const script: string = ` typeof foo == "funcion" "fction" == typeof foo @@ -59,21 +59,21 @@ describe("validTypeofRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Invalid comparison in typeof. Did you mean function?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean function?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 27, line: 2 } }, { - failure: "Invalid comparison in typeof. Did you mean function?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean function?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 13, line: 3 } } ]); }); - it("should fail on invalid string with !==", (): void => { + it('should fail on invalid string with !==', (): void => { const script: string = ` typeof foo !== "undfind" "ndefined" !== typeof foo @@ -81,21 +81,21 @@ describe("validTypeofRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Invalid comparison in typeof. Did you mean undefined?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean undefined?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 28, line: 2 } }, { - failure: "Invalid comparison in typeof. Did you mean undefined?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean undefined?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 13, line: 3 } } ]); }); - it("should fail on invalid string with !=", (): void => { + it('should fail on invalid string with !=', (): void => { const script: string = ` typeof foo != "bollean" "bollen" != typeof foo @@ -103,15 +103,15 @@ describe("validTypeofRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Invalid comparison in typeof. Did you mean boolean?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean boolean?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 27, line: 2 } }, { - failure: "Invalid comparison in typeof. Did you mean boolean?", - name: Utils.absolutePath("file.ts"), - ruleName: "valid-typeof", + failure: 'Invalid comparison in typeof. Did you mean boolean?', + name: Utils.absolutePath('file.ts'), + ruleName: 'valid-typeof', startPosition: { character: 13, line: 3 } } ]); diff --git a/src/tests/jqueryDeferredMustCompleteRuleTests.ts b/src/tests/jqueryDeferredMustCompleteRuleTests.ts index 43f657530..ab434d5aa 100644 --- a/src/tests/jqueryDeferredMustCompleteRuleTests.ts +++ b/src/tests/jqueryDeferredMustCompleteRuleTests.ts @@ -1,11 +1,11 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("jquery-deferred-must-complete", (): void => { - const ruleName: string = "jquery-deferred-must-complete"; +describe('jquery-deferred-must-complete', (): void => { + const ruleName: string = 'jquery-deferred-must-complete'; - describe("should pass", (): void => { - it("when deferred named jquery completes", (): void => { + describe('should pass', (): void => { + it('when deferred named jquery completes', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -24,7 +24,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when deferred named jquery completes - let declaration", (): void => { + it('when deferred named jquery completes - let declaration', (): void => { const script: string = ` function myMethod() : JQueryPromise { let deferred: JQueryDeferred = jquery.Deferred(); @@ -43,7 +43,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when deferred named $ completes", (): void => { + it('when deferred named $ completes', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = $.Deferred(); @@ -63,7 +63,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("on resolve", (): void => { + it('on resolve', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = $.Deferred(); @@ -75,7 +75,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("on reject", (): void => { + it('on reject', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = $.Deferred(); @@ -87,7 +87,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when single branch is completed - with if-statement", (): void => { + it('when single branch is completed - with if-statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -101,7 +101,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when single branch is completed - with if-else-statement", (): void => { + it('when single branch is completed - with if-else-statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -116,7 +116,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when single branch is completed - with if-else-statement", (): void => { + it('when single branch is completed - with if-else-statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -138,7 +138,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("with nested if-else statement", (): void => { + it('with nested if-else statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -161,7 +161,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a function", (): void => { + it('when resolved within a function', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -173,7 +173,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a lambda", (): void => { + it('when resolved within a lambda', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -185,7 +185,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a function", (): void => { + it('when resolved within a function', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -197,7 +197,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a lambda", (): void => { + it('when resolved within a lambda', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -209,7 +209,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a for loop", (): void => { + it('when resolved within a for loop', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -221,7 +221,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a for in loop", (): void => { + it('when resolved within a for in loop', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -233,7 +233,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when resolved within a while loop", (): void => { + it('when resolved within a while loop', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -245,7 +245,7 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("when deferred reference escaped into a function call", (): void => { + it('when deferred reference escaped into a function call', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -256,8 +256,8 @@ describe("jquery-deferred-must-complete", (): void => { }); }); - describe("should fail", (): void => { - it("when has no complete", (): void => { + describe('should fail', (): void => { + it('when has no complete', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = $.Deferred(); @@ -268,16 +268,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = $.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); }); - it("when has no complete - var declared on two lines", (): void => { + it('when has no complete - var declared on two lines', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred; @@ -289,16 +289,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred = $.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 17, line: 4 } } ]); }); - it("when single branch is missing complete - with if-statement", (): void => { + it('when single branch is missing complete - with if-statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -311,16 +311,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = jquery.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); }); - it("when single branch is missing complete - with if-else-statement", (): void => { + it('when single branch is missing complete - with if-else-statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -335,16 +335,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = jquery.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); }); - it("with nested if-else statement", (): void => { + it('with nested if-else statement', (): void => { const script: string = ` function myMethod() : JQueryPromise { let deferred: JQueryDeferred = jquery.Deferred(); @@ -366,16 +366,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = jquery.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); }); - it("when shadowed parameter resolved within a function", (): void => { + it('when shadowed parameter resolved within a function', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -387,16 +387,16 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = jquery.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); }); - it("when shadowed parameter resolved within a lambda", (): void => { + it('when shadowed parameter resolved within a lambda', (): void => { const script: string = ` function myMethod() : JQueryPromise { var deferred: JQueryDeferred = jquery.Deferred(); @@ -408,10 +408,10 @@ describe("jquery-deferred-must-complete", (): void => { TestHelper.assertViolations(ruleName, script, [ { failure: - "A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: " + + 'A JQuery deferred was found that appears to not have resolve or reject invoked on all code paths: ' + "'deferred: JQueryDeferred = jquery.Deferred()'", - name: Utils.absolutePath("file.ts"), - ruleName: "jquery-deferred-must-complete", + name: Utils.absolutePath('file.ts'), + ruleName: 'jquery-deferred-must-complete', startPosition: { character: 21, line: 3 } } ]); diff --git a/src/tests/noUnnecessaryFieldInitializationRuleTests.ts b/src/tests/noUnnecessaryFieldInitializationRuleTests.ts index 6919e71b0..fb2cac08b 100644 --- a/src/tests/noUnnecessaryFieldInitializationRuleTests.ts +++ b/src/tests/noUnnecessaryFieldInitializationRuleTests.ts @@ -1,10 +1,10 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("unnecessaryFieldInitializationRule", (): void => { - const ruleName: string = "no-unnecessary-field-initialization"; +describe('unnecessaryFieldInitializationRule', (): void => { + const ruleName: string = 'no-unnecessary-field-initialization'; - it("should pass on settings fields to different values", (): void => { + it('should pass on settings fields to different values', (): void => { const script: string = ` class MyClass { private myField1; @@ -22,7 +22,7 @@ describe("unnecessaryFieldInitializationRule", (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it("should fail on initializing to undefined", (): void => { + it('should fail on initializing to undefined', (): void => { const script: string = ` class MyClass { private myField = undefined; @@ -31,15 +31,15 @@ describe("unnecessaryFieldInitializationRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary field initialization. Field explicitly initialized to undefined: myField", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field explicitly initialized to undefined: myField', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 35, line: 3 } } ]); }); - it("should fail on setting to undefined", (): void => { + it('should fail on setting to undefined', (): void => { const script: string = ` class MyClass { private myField; @@ -51,15 +51,15 @@ describe("unnecessaryFieldInitializationRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary field initialization. Field explicitly initialized to undefined: this.myField", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field explicitly initialized to undefined: this.myField', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 5 } } ]); }); - it("should fail on initializing and setting to same values", (): void => { + it('should fail on initializing and setting to same values', (): void => { const script: string = ` class MyClass { private myField1 = null; @@ -80,33 +80,33 @@ describe("unnecessaryFieldInitializationRule", (): void => { TestHelper.assertViolations(ruleName, script, [ { - failure: "Unnecessary field initialization. Field value already initialized in declaration: this.myField1 = null", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field value already initialized in declaration: this.myField1 = null', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 10 } }, { failure: "Unnecessary field initialization. Field value already initialized in declaration: this.myField2 = 'value'", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 11 } }, { - failure: "Unnecessary field initialization. Field value already initialized in declaration: this.myField3 = 12345", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field value already initialized in declaration: this.myField3 = 12345', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 12 } }, { - failure: "Unnecessary field initialization. Field value already initialized in declaration: this.myField4 = true", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field value already initialized in declaration: this.myField4 = true', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 13 } }, { - failure: "Unnecessary field initialization. Field value already initialized in declaration: this.myField5 = false", - name: Utils.absolutePath("file.ts"), - ruleName: "no-unnecessary-field-initialization", + failure: 'Unnecessary field initialization. Field value already initialized in declaration: this.myField5 = false', + name: Utils.absolutePath('file.ts'), + ruleName: 'no-unnecessary-field-initialization', startPosition: { character: 21, line: 14 } } ]); diff --git a/src/tests/preferArrayLiteralRuleTests.ts b/src/tests/preferArrayLiteralRuleTests.ts index e5f5e2c84..aa8a5eb86 100644 --- a/src/tests/preferArrayLiteralRuleTests.ts +++ b/src/tests/preferArrayLiteralRuleTests.ts @@ -1,79 +1,79 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; -describe("preferArrayLiteralRule", (): void => { - const ruleName: string = "prefer-array-literal"; +describe('preferArrayLiteralRule', (): void => { + const ruleName: string = 'prefer-array-literal'; - it("should allow string[] as variable type", (): void => { - const inputScript: string = "var x : string[];"; + it('should allow string[] as variable type', (): void => { + const inputScript: string = 'var x : string[];'; TestHelper.assertViolations(ruleName, inputScript, []); }); - it("should allow Array type parameters when options say to ignore type params", (): void => { + it('should allow Array type parameters when options say to ignore type params', (): void => { const inputScript: string = ` let myArray: Array = []; interface MyInterface { myArray: Array; } `; - TestHelper.assertViolationsWithOptions(ruleName, [true, { "allow-type-parameters": true }], inputScript, []); + TestHelper.assertViolationsWithOptions(ruleName, [true, { 'allow-type-parameters': true }], inputScript, []); }); - it("should ban Array as variable type", (): void => { - const inputScript: string = "var x : Array;"; + it('should ban Array as variable type', (): void => { + const inputScript: string = 'var x : Array;'; TestHelper.assertViolations(ruleName, inputScript, [ { - failure: "Replace generic-typed Array with array literal: Array", - name: Utils.absolutePath("file.ts"), - ruleName: "prefer-array-literal", + failure: 'Replace generic-typed Array with array literal: Array', + name: Utils.absolutePath('file.ts'), + ruleName: 'prefer-array-literal', startPosition: { character: 9, line: 1 } } ]); }); - it("should ban Array as parameter type", (): void => { - const inputScript: string = "function (parm: Array) {}"; + it('should ban Array as parameter type', (): void => { + const inputScript: string = 'function (parm: Array) {}'; TestHelper.assertViolations(ruleName, inputScript, [ { - failure: "Replace generic-typed Array with array literal: Array", - name: Utils.absolutePath("file.ts"), - ruleName: "prefer-array-literal", + failure: 'Replace generic-typed Array with array literal: Array', + name: Utils.absolutePath('file.ts'), + ruleName: 'prefer-array-literal', startPosition: { character: 17, line: 1 } } ]); }); - it("should ban new Array() constructor", (): void => { - const inputScript: string = "new Array()"; - TestHelper.assertViolationsWithOptions(ruleName, [true, { "allow-type-parameters": true }], inputScript, [ + it('should ban new Array() constructor', (): void => { + const inputScript: string = 'new Array()'; + TestHelper.assertViolationsWithOptions(ruleName, [true, { 'allow-type-parameters': true }], inputScript, [ { - failure: "Replace Array constructor with an array literal: new Array()", - name: Utils.absolutePath("file.ts"), - ruleName: "prefer-array-literal", + failure: 'Replace Array constructor with an array literal: new Array()', + name: Utils.absolutePath('file.ts'), + ruleName: 'prefer-array-literal', startPosition: { character: 1, line: 1 } } ]); }); - it("should ban new Array(4, 5) constructor", (): void => { - const inputScript: string = "new Array(4, 5)"; + it('should ban new Array(4, 5) constructor', (): void => { + const inputScript: string = 'new Array(4, 5)'; TestHelper.assertViolations(ruleName, inputScript, [ { - failure: "Replace Array constructor with an array literal: new Array(4, 5)", - name: Utils.absolutePath("file.ts"), - ruleName: "prefer-array-literal", + failure: 'Replace Array constructor with an array literal: new Array(4, 5)', + name: Utils.absolutePath('file.ts'), + ruleName: 'prefer-array-literal', startPosition: { character: 1, line: 1 } } ]); }); - it("should ban new Array(4) constructor", (): void => { - const inputScript: string = "new Array(4)"; + it('should ban new Array(4) constructor', (): void => { + const inputScript: string = 'new Array(4)'; TestHelper.assertViolations(ruleName, inputScript, [ { - failure: "Replace Array constructor with an array literal: new Array(4)", - name: Utils.absolutePath("file.ts"), - ruleName: "prefer-array-literal", + failure: 'Replace Array constructor with an array literal: new Array(4)', + name: Utils.absolutePath('file.ts'), + ruleName: 'prefer-array-literal', startPosition: { character: 1, line: 1 } } ]); diff --git a/src/tests/reactA11yImgHasAltRuleTests.ts b/src/tests/reactA11yImgHasAltRuleTests.ts index f7dc1d93a..59737b6db 100644 --- a/src/tests/reactA11yImgHasAltRuleTests.ts +++ b/src/tests/reactA11yImgHasAltRuleTests.ts @@ -1,39 +1,39 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; import { getFailureStringEmptyAltAndNotEmptyTitle, getFailureStringEmptyAltAndNotPresentationRole, getFailureStringNoAlt, getFailureStringNonEmptyAltAndPresentationRole, getFailureStringAltIsImageFileName -} from "../reactA11yImgHasAltRule"; +} from '../reactA11yImgHasAltRule'; /** * Unit test for react-a11y-img-has-alt rule */ -describe("reactA11yImgHasAlt", () => { - const ruleName: string = "react-a11y-img-has-alt"; +describe('reactA11yImgHasAlt', () => { + const ruleName: string = 'react-a11y-img-has-alt'; - describe("default tests", () => { - describe("should pass", () => { - const fileDirectory: string = "test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/"; + describe('default tests', () => { + describe('should pass', () => { + const fileDirectory: string = 'test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/'; - it("when the element name is not img", () => { - const fileName: string = fileDirectory + "ElementNotImg.tsx"; + it('when the element name is not img', () => { + const fileName: string = fileDirectory + 'ElementNotImg.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img tag name is not lower case", () => { - const fileName: string = fileDirectory + "ImgElementNotLowerCase.tsx"; + it('when the img tag name is not lower case', () => { + const fileName: string = fileDirectory + 'ImgElementNotLowerCase.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img element has spread attribute", () => { - const fileName: string = fileDirectory + "ImgElementHasSpreadAttribute.tsx"; + it('when the img element has spread attribute', () => { + const fileName: string = fileDirectory + 'ImgElementHasSpreadAttribute.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img element has empty alt value and presentation role", () => { + it('when the img element has empty alt value and presentation role', () => { const fileName: string = ` import React = require('react'); @@ -44,23 +44,23 @@ describe("reactA11yImgHasAlt", () => { TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img element has non-empty alt value and not presentation role", () => { - const fileName: string = fileDirectory + "ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx"; + it('when the img element has non-empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img element has non-empty alt value and undefined presentation role", () => { - const fileName: string = fileDirectory + "ImgElementHasNonEmptyAltValueAndUndefinedPresentationRole.tsx"; + it('when the img element has non-empty alt value and undefined presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndUndefinedPresentationRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the img element has non-empty alt value and presentation role when option is enabled", () => { - const fileName: string = fileDirectory + "ImgElementHasNonEmptyAltValueAndPresentationRole.tsx"; + it('when the img element has non-empty alt value and presentation role when option is enabled', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndPresentationRole.tsx'; const ruleOptions = [[], { allowNonEmptyAltWithRolePresentation: true }]; TestHelper.assertNoViolationWithOptions(ruleName, ruleOptions, fileName); }); - it("when the img element has empty alt value, empty title, and presentation role", () => { + it('when the img element has empty alt value, empty title, and presentation role', () => { const fileName: string = ` import React = require('react'); @@ -73,29 +73,29 @@ describe("reactA11yImgHasAlt", () => { }); }); - describe("should fail", () => { - const fileDirectory: string = "test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/"; + describe('should fail', () => { + const fileDirectory: string = 'test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/'; - it("when the img element has no alt prop", () => { - const fileName: string = fileDirectory + "ImgElementHasNoAlt.tsx"; + it('when the img element has no alt prop', () => { + const fileName: string = fileDirectory + 'ImgElementHasNoAlt.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringNoAlt("img") + failure: getFailureStringNoAlt('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringNoAlt("img") + failure: getFailureStringNoAlt('img') } ]); }); - it("when the img element has empty alt value and not presentation role", () => { + it('when the img element has empty alt value and not presentation role', () => { const fileName: string = `import React = require('react'); const a = @@ -105,64 +105,64 @@ const d = {''} `; TestHelper.assertViolations(ruleName, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') } ]); }); - it("when the img element has non-empty alt value and presentation role", () => { - const fileName: string = fileDirectory + "ImgElementHasNonEmptyAltValueAndPresentationRole.tsx"; + it('when the img element has non-empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'ImgElementHasNonEmptyAltValueAndPresentationRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 8 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') } ]); }); - it("when the img tag has empty attribute alt but not-empty attribute title", () => { + it('when the img tag has empty attribute alt but not-empty attribute title', () => { const fileName: string = `import React = require('react'); const a = ; @@ -172,22 +172,22 @@ const c = {''}; TestHelper.assertViolations(ruleName, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("img") + failure: getFailureStringEmptyAltAndNotEmptyTitle('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("img") + failure: getFailureStringEmptyAltAndNotEmptyTitle('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("img") + failure: getFailureStringEmptyAltAndNotEmptyTitle('img') } ]); }); @@ -200,40 +200,40 @@ const c = {''}; TestHelper.assertViolations(ruleName, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 19, line: 2 }, - failure: getFailureStringAltIsImageFileName("img") + failure: getFailureStringAltIsImageFileName('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 19, line: 3 }, - failure: getFailureStringAltIsImageFileName("img") + failure: getFailureStringAltIsImageFileName('img') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 19, line: 4 }, - failure: getFailureStringAltIsImageFileName("img") + failure: getFailureStringAltIsImageFileName('img') } ]); }); }); }); - describe("custom element tests", () => { - const options = [["Picture"]]; + describe('custom element tests', () => { + const options = [['Picture']]; - describe("should pass", () => { - const fileDirectory: string = "test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/"; + describe('should pass', () => { + const fileDirectory: string = 'test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/'; - it("when the element is neither img nor custom element", () => { - const fileName: string = fileDirectory + "ElementNeitherImgNorCustomElement.tsx"; + it('when the element is neither img nor custom element', () => { + const fileName: string = fileDirectory + 'ElementNeitherImgNorCustomElement.tsx'; TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); - it("when custom element or img has empty alt value and presentation role", () => { + it('when custom element or img has empty alt value and presentation role', () => { const fileName: string = ` import React = require('react'); @@ -249,16 +249,16 @@ const c = {''}; TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); - it("when custom element or img has non-empty alt value and not presentation role", () => { - const fileName: string = fileDirectory + "CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx"; + it('when custom element or img has non-empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertNoViolationWithOptions(ruleName, options, fileName); }); }); - describe("should fail", () => { - const fileDirectory: string = "test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/"; + describe('should fail', () => { + const fileDirectory: string = 'test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/'; - it("when the custom element has empty attribute alt but not-empty attribute title", () => { + it('when the custom element has empty attribute alt but not-empty attribute title', () => { const fileName: string = `import React = require('react'); let Picture; @@ -270,139 +270,139 @@ const c = ; TestHelper.assertViolationsWithOptions(ruleName, options, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("Picture") + failure: getFailureStringEmptyAltAndNotEmptyTitle('Picture') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("Picture") + failure: getFailureStringEmptyAltAndNotEmptyTitle('Picture') }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringEmptyAltAndNotEmptyTitle("Picture") + failure: getFailureStringEmptyAltAndNotEmptyTitle('Picture') } ]); }); - it("when custom element or img has no alt prop", () => { - const fileName: string = fileDirectory + "CustomElementHasNoAltProp.tsx"; + it('when custom element or img has no alt prop', () => { + const fileName: string = fileDirectory + 'CustomElementHasNoAltProp.tsx'; TestHelper.assertViolationsWithOptions(ruleName, options, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringNoAlt("Picture") + failure: getFailureStringNoAlt('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringNoAlt("Picture") + failure: getFailureStringNoAlt('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringNoAlt("img") + failure: getFailureStringNoAlt('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 8 }, - failure: getFailureStringNoAlt("img") + failure: getFailureStringNoAlt('img') } ]); }); - it("when custom element or img has non-empty alt value and presentation role", () => { - const fileName: string = fileDirectory + "CustomElementHasNonEmptyAltValueAndPresentationRole.tsx"; + it('when custom element or img has non-empty alt value and presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasNonEmptyAltValueAndPresentationRole.tsx'; TestHelper.assertViolationsWithOptions(ruleName, options, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("Picture") + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("Picture") + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 8 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("Picture") + failure: getFailureStringNonEmptyAltAndPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 9 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 10 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 11 }, - failure: getFailureStringNonEmptyAltAndPresentationRole("img") + failure: getFailureStringNonEmptyAltAndPresentationRole('img') } ]); }); - it("when custom element or img has empty alt value and not presentation role", () => { - const fileName: string = fileDirectory + "CustomElementHasEmptyAltValueAndNotPresentationRole.tsx"; + it('when custom element or img has empty alt value and not presentation role', () => { + const fileName: string = fileDirectory + 'CustomElementHasEmptyAltValueAndNotPresentationRole.tsx'; TestHelper.assertViolationsWithOptions(ruleName, options, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("Picture") + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("Picture") + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("Picture") + failure: getFailureStringEmptyAltAndNotPresentationRole('Picture') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 8 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 9 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 10 }, - failure: getFailureStringEmptyAltAndNotPresentationRole("img") + failure: getFailureStringEmptyAltAndNotPresentationRole('img') } ]); }); diff --git a/src/tests/reactA11yPropsRuleTests.ts b/src/tests/reactA11yPropsRuleTests.ts index 71247aa0d..9c30f707d 100644 --- a/src/tests/reactA11yPropsRuleTests.ts +++ b/src/tests/reactA11yPropsRuleTests.ts @@ -1,63 +1,63 @@ -import { TestHelper } from "./TestHelper"; -import { getFailureString } from "../reactA11yPropsRule"; +import { TestHelper } from './TestHelper'; +import { getFailureString } from '../reactA11yPropsRule'; /** * Unit tests for aria-props rule. */ -describe("a11yPropsRule", () => { - const ruleName: string = "react-a11y-props"; +describe('a11yPropsRule', () => { + const ruleName: string = 'react-a11y-props'; - describe("should pass", () => { - it("when the aria-* attribute name is correct", () => { - const fileName: string = "test-data/a11yProps/PassingTestInputs/CorrectAriaAttributeName.tsx"; + describe('should pass', () => { + it('when the aria-* attribute name is correct', () => { + const fileName: string = 'test-data/a11yProps/PassingTestInputs/CorrectAriaAttributeName.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the attribute name is not aria-*", () => { - const fileName: string = "test-data/a11yProps/PassingTestInputs/AttributeNotAria.tsx"; + it('when the attribute name is not aria-*', () => { + const fileName: string = 'test-data/a11yProps/PassingTestInputs/AttributeNotAria.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); - describe("should fail", () => { - it("when the aria-* attribute name is not defined", () => { - const fileName: string = "test-data/a11yProps/FailingTestInputs/InvalidAriaAttributeName.tsx"; + describe('should fail', () => { + it('when the aria-* attribute name is not defined', () => { + const fileName: string = 'test-data/a11yProps/FailingTestInputs/InvalidAriaAttributeName.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 3 }, - failure: getFailureString("aria-") + failure: getFailureString('aria-') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 4 }, - failure: getFailureString("Aria-") + failure: getFailureString('Aria-') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 5 }, - failure: getFailureString("aria-a") + failure: getFailureString('aria-a') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 6 }, - failure: getFailureString("aria-lable") + failure: getFailureString('aria-lable') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 7 }, - failure: getFailureString("aria-la") + failure: getFailureString('aria-la') }, { name: fileName, ruleName: ruleName, startPosition: { character: 29, line: 7 }, - failure: getFailureString("aria-unchecked") + failure: getFailureString('aria-unchecked') } ]); }); diff --git a/src/tests/reactA11yRoleHasRequiredAriaPropsRuleTests.ts b/src/tests/reactA11yRoleHasRequiredAriaPropsRuleTests.ts index 68d3373ae..b2ee42e1f 100644 --- a/src/tests/reactA11yRoleHasRequiredAriaPropsRuleTests.ts +++ b/src/tests/reactA11yRoleHasRequiredAriaPropsRuleTests.ts @@ -1,72 +1,72 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; -import { getFailureStringForNotImplicitRole, getFailureStringForImplicitRole } from "../reactA11yRoleHasRequiredAriaPropsRule"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; +import { getFailureStringForNotImplicitRole, getFailureStringForImplicitRole } from '../reactA11yRoleHasRequiredAriaPropsRule'; /** * Unit test for a11y-role-has-required-aria-props rule */ -describe("a11yRoleHasRequiredAriaPropsRule", () => { - const ruleName: string = "react-a11y-role-has-required-aria-props"; +describe('a11yRoleHasRequiredAriaPropsRule', () => { + const ruleName: string = 'react-a11y-role-has-required-aria-props'; - describe("should pass", () => { - const fileDirectory: string = "test-data/a11yRoleHasRequiredAriaProps/PassingTestInputs/"; + describe('should pass', () => { + const fileDirectory: string = 'test-data/a11yRoleHasRequiredAriaProps/PassingTestInputs/'; - it("when the attribute has no valid role", () => { - const fileName: string = fileDirectory + "AttributeHasNoValidRole.tsx"; + it('when the attribute has no valid role', () => { + const fileName: string = fileDirectory + 'AttributeHasNoValidRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the role value is not string", () => { - const fileName: string = fileDirectory + "RoleValueNotLiteralString.tsx"; + it('when the role value is not string', () => { + const fileName: string = fileDirectory + 'RoleValueNotLiteralString.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the role value has no required props", () => { - const fileName: string = fileDirectory + "RoleHasNoRequiredProps.tsx"; + it('when the role value has no required props', () => { + const fileName: string = fileDirectory + 'RoleHasNoRequiredProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the role value and attributes have required props", () => { - const fileName: string = fileDirectory + "RoleValueAndAttributesHaveRequiredProps.tsx"; + it('when the role value and attributes have required props', () => { + const fileName: string = fileDirectory + 'RoleValueAndAttributesHaveRequiredProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); - describe("should fail", () => { - const fileDirectory: string = "test-data/a11yRoleHasRequiredAriaProps/FailingTestInputs/"; + describe('should fail', () => { + const fileDirectory: string = 'test-data/a11yRoleHasRequiredAriaProps/FailingTestInputs/'; - it("when explcit role missing required props", () => { - const fileName: string = fileDirectory + "ExplicitRoleMissingRequiredProps.tsx"; + it('when explcit role missing required props', () => { + const fileName: string = fileDirectory + 'ExplicitRoleMissingRequiredProps.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringForNotImplicitRole(["checkbox"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['checkbox'], ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringForNotImplicitRole(["menuitemcheckbox"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['menuitemcheckbox'], ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringForNotImplicitRole(["radio"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['radio'], ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 6 }, - failure: getFailureStringForNotImplicitRole(["spinbutton"], ["aria-valuemax", "aria-valuemin", "aria-valuenow"]) + failure: getFailureStringForNotImplicitRole(['spinbutton'], ['aria-valuemax', 'aria-valuemin', 'aria-valuenow']) } ]); }); - it("when implicit role missing required props", () => { + it('when implicit role missing required props', () => { const fileName: string = `import React = require('react'); const a = @@ -74,16 +74,16 @@ const b = `; TestHelper.assertViolations(ruleName, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringForImplicitRole("input", "combobox", ["aria-expanded", "aria-controls"]) + failure: getFailureStringForImplicitRole('input', 'combobox', ['aria-expanded', 'aria-controls']) }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringForImplicitRole("menuitem", "menuitemradio", ["aria-checked"]) + failure: getFailureStringForImplicitRole('menuitem', 'menuitemradio', ['aria-checked']) } ]); }); diff --git a/src/tests/reactA11yRoleRuleTests.ts b/src/tests/reactA11yRoleRuleTests.ts index e8a502ba1..b18a33dd5 100644 --- a/src/tests/reactA11yRoleRuleTests.ts +++ b/src/tests/reactA11yRoleRuleTests.ts @@ -1,89 +1,89 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; -import { getFailureStringInvalidRole } from "../reactA11yRoleRule"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; +import { getFailureStringInvalidRole } from '../reactA11yRoleRule'; /** * Unit tests for a11y-role */ // tslint:disable:no-empty -describe("a11yRoleRule", () => { - const ruleName: string = "react-a11y-role"; +describe('a11yRoleRule', () => { + const ruleName: string = 'react-a11y-role'; - describe("should pass", () => { - it("when the role name is correct", () => { - const fileName: string = "test-data/a11yRole/PassingTestInputs/CorrectName.tsx"; + describe('should pass', () => { + it('when the role name is correct', () => { + const fileName: string = 'test-data/a11yRole/PassingTestInputs/CorrectName.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the attribute name is not role", () => { - const fileName: string = "test-data/a11yRole/PassingTestInputs/AttributeNotRole.tsx"; + it('when the attribute name is not role', () => { + const fileName: string = 'test-data/a11yRole/PassingTestInputs/AttributeNotRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the role name is not string literal", () => { - const fileName: string = "test-data/a11yRole/PassingTestInputs/RoleNameNotStringLiteral.tsx"; + it('when the role name is not string literal', () => { + const fileName: string = 'test-data/a11yRole/PassingTestInputs/RoleNameNotStringLiteral.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("for multiple correct role names", () => { - const fileName: string = "test-data/a11yRole/PassingTestInputs/MultipleCorrectRole.tsx"; + it('for multiple correct role names', () => { + const fileName: string = 'test-data/a11yRole/PassingTestInputs/MultipleCorrectRole.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); - describe("should fail", () => { - it("for role name not existant", () => { - const fileName: string = "test-data/a11yRole/FailingTestInputs/InvalidRole.tsx"; + describe('should fail', () => { + it('for role name not existant', () => { + const fileName: string = 'test-data/a11yRole/FailingTestInputs/InvalidRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 3 }, - failure: getFailureStringInvalidRole("myRoleName") + failure: getFailureStringInvalidRole('myRoleName') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 4 }, - failure: getFailureStringInvalidRole("wrong") + failure: getFailureStringInvalidRole('wrong') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 5 }, - failure: getFailureStringInvalidRole("role") + failure: getFailureStringInvalidRole('role') } ]); }); - it("for role name that is abstract", () => { - const fileName: string = "test-data/a11yRole/FailingTestInputs/AbstractRole.tsx"; + it('for role name that is abstract', () => { + const fileName: string = 'test-data/a11yRole/FailingTestInputs/AbstractRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 3 }, - failure: getFailureStringInvalidRole("input") + failure: getFailureStringInvalidRole('input') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 4 }, - failure: getFailureStringInvalidRole("landmark") + failure: getFailureStringInvalidRole('landmark') }, { name: fileName, ruleName: ruleName, startPosition: { character: 16, line: 5 }, - failure: getFailureStringInvalidRole("structure") + failure: getFailureStringInvalidRole('structure') } ]); }); - it("when the role name is not defined", () => { + it('when the role name is not defined', () => { const fileName: string = `import React = require('react'); /** @@ -99,41 +99,41 @@ const e =
`; { failure: "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role" + - "_definitions, or simply remove this attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-role", + '_definitions, or simply remove this attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-role', startPosition: { character: 16, line: 6 } }, { failure: "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role" + - "_definitions, or simply remove this attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-role", + '_definitions, or simply remove this attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-role', startPosition: { character: 16, line: 7 } }, { failure: "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role" + - "_definitions, or simply remove this attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-role", + '_definitions, or simply remove this attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-role', startPosition: { character: 16, line: 8 } }, { failure: "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role" + - "_definitions, or simply remove this attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-role", + '_definitions, or simply remove this attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-role', startPosition: { character: 16, line: 9 } }, { failure: "'role' attribute empty. Either select a role from https://www.w3.org/TR/wai-aria/roles#role" + - "_definitions, or simply remove this attribute", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-role", + '_definitions, or simply remove this attribute', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-role', startPosition: { character: 16, line: 10 } } ]); diff --git a/src/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts b/src/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts index 8974b1992..c38f5d9f1 100644 --- a/src/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts +++ b/src/tests/reactA11yRoleSupportsAriaPropsRuleTests.ts @@ -1,25 +1,25 @@ -import { TestHelper } from "./TestHelper"; +import { TestHelper } from './TestHelper'; import { getFailureStringForNoRole, getFailureStringForImplicitRole, getFailureStringForNotImplicitRole -} from "../reactA11yRoleSupportsAriaPropsRule"; +} from '../reactA11yRoleSupportsAriaPropsRule'; /** * Unit test for a11y-role-supports-aria-props rule. */ -describe("a11yRoleSupportsAriaPropsRule", () => { - const ruleName: string = "react-a11y-role-supports-aria-props"; +describe('a11yRoleSupportsAriaPropsRule', () => { + const ruleName: string = 'react-a11y-role-supports-aria-props'; - describe("should pass", () => { - const fileDirectory: string = "test-data/a11yRoleSupportsAriaProps/PassingTestInputs/"; + describe('should pass', () => { + const fileDirectory: string = 'test-data/a11yRoleSupportsAriaProps/PassingTestInputs/'; - it("when the element is react custom element", () => { - const fileName: string = fileDirectory + "CustomElementSupportsAllAriaProps.tsx"; + it('when the element is react custom element', () => { + const fileName: string = fileDirectory + 'CustomElementSupportsAllAriaProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when empty role supports all aria props in element", () => { + it('when empty role supports all aria props in element', () => { const fileName: string = ` import React = require('react'); @@ -48,90 +48,90 @@ describe("a11yRoleSupportsAriaPropsRule", () => { TestHelper.assertNoViolation(ruleName, fileName); }); - it("when explicit role supports all aria props in element", () => { - const fileName: string = fileDirectory + "ExplicitRoleSupportsAllAriaProps.tsx"; + it('when explicit role supports all aria props in element', () => { + const fileName: string = fileDirectory + 'ExplicitRoleSupportsAllAriaProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when implicit role supports all aria props in element", () => { - const fileName: string = fileDirectory + "ImplicitRoleSupportsAllAriaProps.tsx"; + it('when implicit role supports all aria props in element', () => { + const fileName: string = fileDirectory + 'ImplicitRoleSupportsAllAriaProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when role is defined but not retrievable", () => { - const fileName: string = fileDirectory + "UnretrievableRoleSupportsAllAriaProps.tsx"; + it('when role is defined but not retrievable', () => { + const fileName: string = fileDirectory + 'UnretrievableRoleSupportsAllAriaProps.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); - describe("should fail", () => { - const fileDirectory: string = "test-data/a11yRoleSupportsAriaProps/FailingTestInputs/"; + describe('should fail', () => { + const fileDirectory: string = 'test-data/a11yRoleSupportsAriaProps/FailingTestInputs/'; - it("when element has not supported aria props for empty role", () => { - const fileName: string = fileDirectory + "ElementHasNotSupportedAriaPropsForEmptyRole.tsx"; + it('when element has not supported aria props for empty role', () => { + const fileName: string = fileDirectory + 'ElementHasNotSupportedAriaPropsForEmptyRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringForNoRole("div", ["aria-checked"]) + failure: getFailureStringForNoRole('div', ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringForNoRole("a", ["aria-checked"]) + failure: getFailureStringForNoRole('a', ['aria-checked']) } ]); }); - it("when element has not supported aria props for implicit role", () => { - const fileName: string = fileDirectory + "ElementHasNotSupportedAriaPropsForImplicitRole.tsx"; + it('when element has not supported aria props for implicit role', () => { + const fileName: string = fileDirectory + 'ElementHasNotSupportedAriaPropsForImplicitRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 3 }, - failure: getFailureStringForImplicitRole("a", "link", ["aria-checked"]) + failure: getFailureStringForImplicitRole('a', 'link', ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringForImplicitRole("area", "link", ["aria-checked"]) + failure: getFailureStringForImplicitRole('area', 'link', ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 5 }, - failure: getFailureStringForImplicitRole("link", "link", ["aria-checked"]) + failure: getFailureStringForImplicitRole('link', 'link', ['aria-checked']) } ]); }); - it("when element has not supported aria props for explicit role", () => { - const fileName: string = fileDirectory + "ElementHasNotSupportedAriaPropsForExplicitRole.tsx"; + it('when element has not supported aria props for explicit role', () => { + const fileName: string = fileDirectory + 'ElementHasNotSupportedAriaPropsForExplicitRole.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 4 }, - failure: getFailureStringForNotImplicitRole(["button"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['button'], ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 7 }, - failure: getFailureStringForNotImplicitRole(["button", "img"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['button', 'img'], ['aria-checked']) }, { name: fileName, ruleName: ruleName, startPosition: { character: 11, line: 10 }, - failure: getFailureStringForNotImplicitRole(["button"], ["aria-checked"]) + failure: getFailureStringForNotImplicitRole(['button'], ['aria-checked']) } ]); }); diff --git a/src/tests/reactA11yTabindexNoPositiveRuleTests.ts b/src/tests/reactA11yTabindexNoPositiveRuleTests.ts index cec79a9ec..3e5e03702 100644 --- a/src/tests/reactA11yTabindexNoPositiveRuleTests.ts +++ b/src/tests/reactA11yTabindexNoPositiveRuleTests.ts @@ -1,32 +1,32 @@ -import { Utils } from "../utils/Utils"; -import { TestHelper } from "./TestHelper"; -import { getFailureString } from "../reactA11yTabindexNoPositiveRule"; +import { Utils } from '../utils/Utils'; +import { TestHelper } from './TestHelper'; +import { getFailureString } from '../reactA11yTabindexNoPositiveRule'; /** * Unit test for tabindex-no-positive */ -describe("a11yTabindexNoPositive", () => { - const ruleName: string = "react-a11y-tabindex-no-positive"; +describe('a11yTabindexNoPositive', () => { + const ruleName: string = 'react-a11y-tabindex-no-positive'; - describe("should pass", () => { - it("when the attribute name is not tabindex", () => { - const fileName: string = "test-data/a11yTabindexNoPositive/PassingTestInputs/AttributeNotTabindex.tsx"; + describe('should pass', () => { + it('when the attribute name is not tabindex', () => { + const fileName: string = 'test-data/a11yTabindexNoPositive/PassingTestInputs/AttributeNotTabindex.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the tabindex value is not string or numeric literal", () => { - const fileName: string = "test-data/a11yTabindexNoPositive/PassingTestInputs/TabindexValueNotLiteral.tsx"; + it('when the tabindex value is not string or numeric literal', () => { + const fileName: string = 'test-data/a11yTabindexNoPositive/PassingTestInputs/TabindexValueNotLiteral.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); - it("when the tabindex value is -1 or 0", () => { - const fileName: string = "test-data/a11yTabindexNoPositive/PassingTestInputs/CorrectTabindexValue.tsx"; + it('when the tabindex value is -1 or 0', () => { + const fileName: string = 'test-data/a11yTabindexNoPositive/PassingTestInputs/CorrectTabindexValue.tsx'; TestHelper.assertNoViolation(ruleName, fileName); }); }); - describe("should fail", () => { - it("when the tabindex value is undefined", () => { + describe('should fail', () => { + it('when the tabindex value is undefined', () => { const fileName: string = `import React = require('react'); const e =
@@ -38,46 +38,46 @@ const v =
`; TestHelper.assertViolations(ruleName, fileName, [ { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 3 } }, { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 4 } }, { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 5 } }, { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 6 } }, { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 7 } }, { - failure: "The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.", - name: Utils.absolutePath("file.tsx"), - ruleName: "react-a11y-tabindex-no-positive", + failure: 'The value of tabindex attribute is invalid or undefined. It must be either -1 or 0.', + name: Utils.absolutePath('file.tsx'), + ruleName: 'react-a11y-tabindex-no-positive', startPosition: { character: 16, line: 8 } } ]); }); - it("when tabindex value is not a number", () => { - const fileName: string = "test-data/a11yTabindexNoPositive/FailingTestInputs/TabindexValueNotNumericLiteral.tsx"; + it('when tabindex value is not a number', () => { + const fileName: string = 'test-data/a11yTabindexNoPositive/FailingTestInputs/TabindexValueNotNumericLiteral.tsx'; TestHelper.assertViolations(ruleName, fileName, [ { @@ -101,7 +101,7 @@ const v =
`; ]); }); - it("when the tabindex value is not -1 or 0", () => { + it('when the tabindex value is not -1 or 0', () => { const fileName: string = `import React = require('react'); const a =
@@ -112,31 +112,31 @@ const e =
`; TestHelper.assertViolations(ruleName, fileName, [ { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 16, line: 3 }, failure: getFailureString() }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 16, line: 4 }, failure: getFailureString() }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 16, line: 5 }, failure: getFailureString() }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 16, line: 6 }, failure: getFailureString() }, { - name: Utils.absolutePath("file.tsx"), + name: Utils.absolutePath('file.tsx'), ruleName: ruleName, startPosition: { character: 16, line: 7 }, failure: getFailureString() diff --git a/src/underscoreConsistentInvocationRule.ts b/src/underscoreConsistentInvocationRule.ts index 76c969eff..f11326517 100644 --- a/src/underscoreConsistentInvocationRule.ts +++ b/src/underscoreConsistentInvocationRule.ts @@ -1,90 +1,90 @@ -import * as ts from "typescript"; -import * as Lint from "tslint"; +import * as ts from 'typescript'; +import * as Lint from 'tslint'; -import { AstUtils } from "./utils/AstUtils"; -import { ExtendedMetadata } from "./utils/ExtendedMetadata"; -import { isObject } from "./utils/TypeGuard"; +import { AstUtils } from './utils/AstUtils'; +import { ExtendedMetadata } from './utils/ExtendedMetadata'; +import { isObject } from './utils/TypeGuard'; -const FAILURE_STATIC_FOUND: string = "Static invocation of underscore function found. Prefer instance version instead: "; -const FAILURE_INSTANCE_FOUND: string = "Underscore instance wrapping of variable found. Prefer underscore static functions instead: "; +const FAILURE_STATIC_FOUND: string = 'Static invocation of underscore function found. Prefer instance version instead: '; +const FAILURE_INSTANCE_FOUND: string = 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: '; const FUNCTION_NAMES: string[] = [ - "each", - "forEach", - "map", - "collect", - "reduce", - "inject", - "foldl", - "reduceRight", - "foldr", - "find", - "detect", - "filter", - "select", - "where", - "findWhere", - "reject", - "every", - "all", - "some", - "any", - "contains", - "include", - "invoke", - "pluck", - "max", - "min", - "sortBy", - "groupBy", - "indexBy", - "countBy", - "shuffle", - "sample", - "toArray", - "size", - "partition", - "first", - "head", - "take", - "initial", - "last", - "rest", - "tail", - "drop", - "compact", - "flatten", - "without", - "union", - "intersection", - "difference", - "uniq", - "unique", - "object", - "zip", - "unzip", - "indexOf", - "findIndex", - "lastIndexOf", - "findLastIndex", - "sortedIndex", - "range" + 'each', + 'forEach', + 'map', + 'collect', + 'reduce', + 'inject', + 'foldl', + 'reduceRight', + 'foldr', + 'find', + 'detect', + 'filter', + 'select', + 'where', + 'findWhere', + 'reject', + 'every', + 'all', + 'some', + 'any', + 'contains', + 'include', + 'invoke', + 'pluck', + 'max', + 'min', + 'sortBy', + 'groupBy', + 'indexBy', + 'countBy', + 'shuffle', + 'sample', + 'toArray', + 'size', + 'partition', + 'first', + 'head', + 'take', + 'initial', + 'last', + 'rest', + 'tail', + 'drop', + 'compact', + 'flatten', + 'without', + 'union', + 'intersection', + 'difference', + 'uniq', + 'unique', + 'object', + 'zip', + 'unzip', + 'indexOf', + 'findIndex', + 'lastIndexOf', + 'findLastIndex', + 'sortedIndex', + 'range' ]; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: "underscore-consistent-invocation", - type: "maintainability", - description: "Enforce a consistent usage of the _ functions", + ruleName: 'underscore-consistent-invocation', + type: 'maintainability', + description: 'Enforce a consistent usage of the _ functions', options: null, // tslint:disable-line:no-null-keyword - optionsDescription: "", + optionsDescription: '', typescriptOnly: true, - issueClass: "Non-SDL", - issueType: "Warning", - severity: "Low", - level: "Opportunity for Excellence", - group: "Clarity", - commonWeaknessEnumeration: "398, 710" + issueClass: 'Non-SDL', + issueType: 'Warning', + severity: 'Low', + level: 'Opportunity for Excellence', + group: 'Clarity', + commonWeaknessEnumeration: '398, 710' }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { @@ -93,14 +93,14 @@ export class Rule extends Lint.Rules.AbstractRule { } class UnderscoreConsistentInvocationRuleWalker extends Lint.RuleWalker { - private style: string = "instance"; + private style: string = 'instance'; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { super(sourceFile, options); this.getOptions().forEach((opt: unknown) => { if (isObject(opt)) { - if (opt.style === "static") { - this.style = "static"; + if (opt.style === 'static') { + this.style = 'static'; } } }); @@ -109,10 +109,10 @@ class UnderscoreConsistentInvocationRuleWalker extends Lint.RuleWalker { protected visitCallExpression(node: ts.CallExpression): void { const functionName: string = AstUtils.getFunctionName(node); - if (this.style === "instance" && this.isStaticUnderscoreInvocation(node)) { - this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STATIC_FOUND + "_." + functionName); + if (this.style === 'instance' && this.isStaticUnderscoreInvocation(node)) { + this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STATIC_FOUND + '_.' + functionName); } - if (this.style === "static" && this.isStaticUnderscoreInstanceInvocation(node)) { + if (this.style === 'static' && this.isStaticUnderscoreInstanceInvocation(node)) { this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_INSTANCE_FOUND + node.expression.getText()); } super.visitCallExpression(node); @@ -125,7 +125,7 @@ class UnderscoreConsistentInvocationRuleWalker extends Lint.RuleWalker { const call: ts.CallExpression = propExpression.expression; const target = AstUtils.getFunctionTarget(call); const functionName = AstUtils.getFunctionName(call); - if (target === undefined && functionName === "_" && call.arguments.length === 1) { + if (target === undefined && functionName === '_' && call.arguments.length === 1) { const underscoreFunctionName = AstUtils.getFunctionName(node); return FUNCTION_NAMES.indexOf(underscoreFunctionName) > -1; } @@ -136,7 +136,7 @@ class UnderscoreConsistentInvocationRuleWalker extends Lint.RuleWalker { private isStaticUnderscoreInvocation(node: ts.CallExpression) { const target = AstUtils.getFunctionTarget(node); - if (target !== "_") { + if (target !== '_') { return false; } const functionName: string = AstUtils.getFunctionName(node); diff --git a/src/useNamedParameterRule.ts b/src/useNamedParameterRule.ts index 33ab83e2f..ce4e0c82b 100644 --- a/src/useNamedParameterRule.ts +++ b/src/useNamedParameterRule.ts @@ -1,25 +1,25 @@ -import * as ts from "typescript"; -import * as Lint from "tslint"; +import * as ts from 'typescript'; +import * as Lint from 'tslint'; -import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { ExtendedMetadata } from './utils/ExtendedMetadata'; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: "use-named-parameter", - type: "maintainability", - description: "Do not reference the arguments object by numerical index; instead, use a named parameter.", + ruleName: 'use-named-parameter', + type: 'maintainability', + description: 'Do not reference the arguments object by numerical index; instead, use a named parameter.', options: null, // tslint:disable-line:no-null-keyword - optionsDescription: "", + optionsDescription: '', typescriptOnly: true, - issueClass: "Non-SDL", - issueType: "Warning", - severity: "Important", - level: "Opportunity for Excellence", - group: "Correctness", - commonWeaknessEnumeration: "710" + issueClass: 'Non-SDL', + issueType: 'Warning', + severity: 'Important', + level: 'Opportunity for Excellence', + group: 'Correctness', + commonWeaknessEnumeration: '710' }; - public static FAILURE_STRING: string = "Use a named parameter instead: "; + public static FAILURE_STRING: string = 'Use a named parameter instead: '; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new UseNamedParameterWalker(sourceFile, this.getOptions())); @@ -30,7 +30,7 @@ class UseNamedParameterWalker extends Lint.RuleWalker { protected visitElementAccessExpression(node: ts.ElementAccessExpression): void { if (node.argumentExpression !== undefined) { if (node.argumentExpression.kind === ts.SyntaxKind.NumericLiteral) { - if (node.expression.getText() === "arguments") { + if (node.expression.getText() === 'arguments') { const failureString = Rule.FAILURE_STRING + "'" + node.getText() + "'"; this.addFailureAt(node.getStart(), node.getWidth(), failureString); } diff --git a/src/utils/AstUtils.ts b/src/utils/AstUtils.ts index ab09df553..d84555413 100644 --- a/src/utils/AstUtils.ts +++ b/src/utils/AstUtils.ts @@ -1,5 +1,5 @@ -import * as ts from "typescript"; -import { isNamed } from "./TypeGuard"; +import * as ts from 'typescript'; +import { isNamed } from './TypeGuard'; /** * General utility class. @@ -7,7 +7,7 @@ import { isNamed } from "./TypeGuard"; export namespace AstUtils { export function getLanguageVariant(node: ts.SourceFile): ts.LanguageVariant { const fileName: string = node.fileName.toLowerCase(); - if (fileName.endsWith(".tsx") || fileName.endsWith(".jsx")) { + if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx')) { return ts.LanguageVariant.JSX; } else { return ts.LanguageVariant.Standard; @@ -16,13 +16,13 @@ export namespace AstUtils { export function getFunctionName(node: ts.CallExpression | ts.NewExpression): string { const expression: ts.Expression = node.expression; - if ("text" in expression) { + if ('text' in expression) { return (<{ text: unknown }>expression).text; } if (isNamed(expression)) { return expression.name.getText(); } - return ""; + return ''; } export function getFunctionTarget(expression: ts.CallExpression): string | undefined { @@ -34,7 +34,7 @@ export namespace AstUtils { } export function isJQuery(functionTarget: string): boolean { - return functionTarget === "$" || /^(jquery)$/i.test(functionTarget); + return functionTarget === '$' || /^(jquery)$/i.test(functionTarget); } export function hasModifier(modifiers: ts.ModifiersArray, modifierKind: number): boolean { @@ -55,63 +55,63 @@ export namespace AstUtils { export function dumpTypeInfo(expression: ts.Expression, languageServices: ts.LanguageService, typeChecker: ts.TypeChecker): void { /* tslint:disable:no-console */ console.log(expression.getFullText()); - console.log("\tkind: " + expression.kind); + console.log('\tkind: ' + expression.kind); if (expression.kind === ts.SyntaxKind.Identifier || expression.kind === ts.SyntaxKind.PropertyAccessExpression) { - const definitionInfo = languageServices.getDefinitionAtPosition("file.ts", expression.getStart()); + const definitionInfo = languageServices.getDefinitionAtPosition('file.ts', expression.getStart()); if (definitionInfo !== undefined) { definitionInfo.forEach( (info: ts.DefinitionInfo, index: number): void => { - console.log("\tdefinitionInfo-" + index); - console.log("\t\tkind: " + info.kind); - console.log("\t\tname: " + info.name); + console.log('\tdefinitionInfo-' + index); + console.log('\t\tkind: ' + info.kind); + console.log('\t\tname: ' + info.name); } ); } - const typeInfo = languageServices.getTypeDefinitionAtPosition("file.ts", expression.getStart()); + const typeInfo = languageServices.getTypeDefinitionAtPosition('file.ts', expression.getStart()); if (typeInfo !== undefined) { typeInfo.forEach( (info: ts.DefinitionInfo, index: number): void => { - console.log("\ttypeDefinitionInfo-" + index); - console.log("\t\tkind: " + info.kind); - console.log("\t\tname: " + info.name); + console.log('\ttypeDefinitionInfo-' + index); + console.log('\t\tkind: ' + info.kind); + console.log('\t\tname: ' + info.name); } ); } - const quickInfo = languageServices.getQuickInfoAtPosition("file.ts", expression.getStart()); + const quickInfo = languageServices.getQuickInfoAtPosition('file.ts', expression.getStart()); if (quickInfo !== undefined) { - console.log("\tquickInfo.kind = " + quickInfo.kind); - console.log("\tquickInfo.kindModifiers= " + quickInfo.kindModifiers); - console.log("\tquickInfo.textSpan = " + quickInfo.textSpan.start); + console.log('\tquickInfo.kind = ' + quickInfo.kind); + console.log('\tquickInfo.kindModifiers= ' + quickInfo.kindModifiers); + console.log('\tquickInfo.textSpan = ' + quickInfo.textSpan.start); if (quickInfo.displayParts !== undefined) { - console.log("\tquickInfo.displayParts = " + quickInfo.displayParts[0].text); - console.log("\tquickInfo.displayParts = " + quickInfo.displayParts[0].kind); + console.log('\tquickInfo.displayParts = ' + quickInfo.displayParts[0].text); + console.log('\tquickInfo.displayParts = ' + quickInfo.displayParts[0].kind); } } const expressionType: ts.Type = typeChecker.getTypeAtLocation(expression); - console.log("\ttypeChecker.typeToString: " + typeChecker.typeToString(expressionType)); - console.log("\ttype.flags: " + expressionType.flags); - console.log("\ttype.symbol: " + expressionType.symbol); + console.log('\ttypeChecker.typeToString: ' + typeChecker.typeToString(expressionType)); + console.log('\ttype.flags: ' + expressionType.flags); + console.log('\ttype.symbol: ' + expressionType.symbol); const expressionSymbol = typeChecker.getSymbolAtLocation(expression); if (expressionSymbol === undefined) { - console.log("\tsymbol: " + expressionSymbol); + console.log('\tsymbol: ' + expressionSymbol); } else { - console.log("\tsymbol.flags: " + expressionSymbol.flags); - console.log("\tsymbol.name: " + expressionSymbol.name); - console.log("\tsymbol.declarations: " + expressionSymbol.declarations); + console.log('\tsymbol.flags: ' + expressionSymbol.flags); + console.log('\tsymbol.name: ' + expressionSymbol.name); + console.log('\tsymbol.declarations: ' + expressionSymbol.declarations); } const contextualType = typeChecker.getContextualType(expression); if (contextualType === undefined) { - console.log("\tcontextualType: " + contextualType); + console.log('\tcontextualType: ' + contextualType); } else { - console.log("\tcontextualType.flags: " + contextualType.flags); - console.log("\tcontextualType.symbol: " + contextualType.symbol); + console.log('\tcontextualType.flags: ' + contextualType.flags); + console.log('\tcontextualType.symbol: ' + contextualType.symbol); } } /* tslint:enable:no-console */ @@ -222,7 +222,7 @@ export namespace AstUtils { } parent = parent.parent; } - throw new Error("Could not determine parent block of node: " + child); + throw new Error('Could not determine parent block of node: ' + child); } export function isSameIdentifer(source: ts.Node, target: ts.Node): boolean { @@ -252,7 +252,7 @@ export namespace AstUtils { export function isDeclarationFunctionType(node: ts.PropertyDeclaration | ts.VariableDeclaration | ts.ParameterDeclaration): boolean { if (node.type !== undefined) { - if (node.type.getText() === "Function") { + if (node.type.getText() === 'Function') { return true; } return node.type.kind === ts.SyntaxKind.FunctionType; @@ -265,7 +265,7 @@ export namespace AstUtils { export function isUndefined(node: ts.Expression | undefined): boolean { if (node !== undefined) { if (node.kind === ts.SyntaxKind.Identifier) { - return node.getText() === "undefined"; + return node.getText() === 'undefined'; } } return false; diff --git a/src/utils/BannedTermWalker.ts b/src/utils/BannedTermWalker.ts index f219ae44e..d89ca509a 100644 --- a/src/utils/BannedTermWalker.ts +++ b/src/utils/BannedTermWalker.ts @@ -1,6 +1,6 @@ -import * as ts from "typescript"; -import * as Lint from "tslint"; -import { isObject, isNamed } from "./TypeGuard"; +import * as ts from 'typescript'; +import * as Lint from 'tslint'; +import { isObject, isNamed } from './TypeGuard'; export class BannedTermWalker extends Lint.RuleWalker { private readonly failureString: string; @@ -13,7 +13,7 @@ export class BannedTermWalker extends Lint.RuleWalker { this.bannedTerms = bannedTerms; this.getOptions().forEach((opt: unknown) => { if (isObject(opt)) { - this.allowQuotedProperties = opt["allow-quoted-properties"] === true; + this.allowQuotedProperties = opt['allow-quoted-properties'] === true; } }); } @@ -64,7 +64,7 @@ export class BannedTermWalker extends Lint.RuleWalker { protected visitParameterDeclaration(node: ts.ParameterDeclaration): void { // typescript 2.0 introduces function level 'this' types - if (node.name.getText() !== "this") { + if (node.name.getText() !== 'this') { this.validateNode(node); } super.visitParameterDeclaration(node); diff --git a/src/utils/BaseFormatter.ts b/src/utils/BaseFormatter.ts index 61c2d8e0d..41ba648a4 100644 --- a/src/utils/BaseFormatter.ts +++ b/src/utils/BaseFormatter.ts @@ -1,7 +1,7 @@ -"use strict"; +'use strict'; -import * as fs from "fs"; -import { Formatters, RuleFailure } from "tslint"; +import * as fs from 'fs'; +import { Formatters, RuleFailure } from 'tslint'; /** * A base class for formatters that fix linting issues. @@ -26,17 +26,17 @@ export class BaseFormatter extends Formatters.AbstractFormatter { } } const outputLines = allFailures.map(this.formatFailure); - return outputLines.join("\n") + "\n"; + return outputLines.join('\n') + '\n'; } protected readFile(fileName: string): string { // tslint:disable-next-line non-literal-fs-path - return fs.readFileSync(fileName, { encoding: "UTF-8" }); + return fs.readFileSync(fileName, { encoding: 'UTF-8' }); } protected writeFile(fileName: string, fileContents: string): void { // tslint:disable-next-line non-literal-fs-path - fs.writeFileSync(fileName, fileContents, { encoding: "UTF-8" }); + fs.writeFileSync(fileName, fileContents, { encoding: 'UTF-8' }); } private formatFailure(failure: RuleFailure): string { @@ -44,7 +44,7 @@ export class BaseFormatter extends Formatters.AbstractFormatter { const failureString: string = failure.getFailure(); const ruleName: string = failure.getRuleName(); const lineAndCharacter = failure.getStartPosition().getLineAndCharacter(); - const positionTuple = "[" + (lineAndCharacter.line + 1) + ", " + (lineAndCharacter.character + 1) + "]"; - return "(" + ruleName + ") " + fileName + positionTuple + ": " + failureString; + const positionTuple = '[' + (lineAndCharacter.line + 1) + ', ' + (lineAndCharacter.character + 1) + ']'; + return '(' + ruleName + ') ' + fileName + positionTuple + ': ' + failureString; } } diff --git a/src/utils/ChaiUtils.ts b/src/utils/ChaiUtils.ts index c2a4e132f..48d92090b 100644 --- a/src/utils/ChaiUtils.ts +++ b/src/utils/ChaiUtils.ts @@ -1,4 +1,4 @@ -import * as ts from "typescript"; +import * as ts from 'typescript'; /** * Utility methods for the chai.related rules. diff --git a/src/utils/ExtendedMetadata.ts b/src/utils/ExtendedMetadata.ts index f662c069b..b1a955b34 100644 --- a/src/utils/ExtendedMetadata.ts +++ b/src/utils/ExtendedMetadata.ts @@ -1,4 +1,4 @@ -import * as Lint from "tslint"; +import * as Lint from 'tslint'; /** * Additional information that each rule must specify. @@ -19,17 +19,17 @@ export interface ExtendedMetadata extends Lint.IRuleMetadata { * Non-SDL - Use this value when you want a rule to show up in Microsoft's Warnings Central * Ignored - Use this value to exclude the rule from Warnings Central */ -export type IssueClass = "SDL" | "Non-SDL" | "Ignored"; -export type IssueType = "Error" | "Warning"; -export type Severity = "Critical" | "Important" | "Moderate" | "Low"; +export type IssueClass = 'SDL' | 'Non-SDL' | 'Ignored'; +export type IssueType = 'Error' | 'Warning'; +export type Severity = 'Critical' | 'Important' | 'Moderate' | 'Low'; /** * Mandatory - This means that all teams should be using this rule with no exceptions. * Opportunity for Excellence - This means that we recommend using the rule. */ -export type Level = "Mandatory" | "Opportunity for Excellence"; +export type Level = 'Mandatory' | 'Opportunity for Excellence'; /** * Ignored - Use this value to exclude the rule from recommended_ruleset.js and the deployed tslint.json file. */ -export type Group = "Ignored" | "Security" | "Correctness" | "Accessibility" | "Clarity" | "Whitespace" | "Configurable" | "Deprecated"; +export type Group = 'Ignored' | 'Security' | 'Correctness' | 'Accessibility' | 'Clarity' | 'Whitespace' | 'Configurable' | 'Deprecated'; diff --git a/src/utils/JsxAttribute.ts b/src/utils/JsxAttribute.ts index ae5f8a434..ace1cbe31 100644 --- a/src/utils/JsxAttribute.ts +++ b/src/utils/JsxAttribute.ts @@ -2,7 +2,7 @@ * @JsxAttribute utilities for react rules. */ -import * as ts from "typescript"; +import * as ts from 'typescript'; import { isJsxAttribute, isJsxExpression, @@ -13,11 +13,11 @@ import { isJsxOpeningElement, isFalseKeyword, isTrueKeyword -} from "./TypeGuard"; +} from './TypeGuard'; export function getPropName(node: ts.JsxAttribute): string | undefined { if (!isJsxAttribute(node)) { - throw new Error("The node must be a JsxAttribute collected by the AST parser."); + throw new Error('The node must be a JsxAttribute collected by the AST parser.'); } return node.name ? node.name.text : undefined; @@ -32,14 +32,14 @@ export function getPropName(node: ts.JsxAttribute): string | undefined { */ export function getStringLiteral(node: ts.JsxAttribute | ts.JsxSpreadAttribute): string | undefined { if (!isJsxAttribute(node)) { - throw new Error("The node must be a JsxAttribute collected by the AST parser."); + throw new Error('The node must be a JsxAttribute collected by the AST parser.'); } const initializer = node === undefined ? undefined : node.initializer; if (!initializer) { // - return ""; + return ''; } else if (isStringLiteral(initializer)) { // return initializer.text.trim(); @@ -48,7 +48,7 @@ export function getStringLiteral(node: ts.JsxAttribute | ts.JsxSpreadAttribute): return (initializer.expression).text; } else if (isJsxExpression(initializer) && !initializer.expression) { // - return ""; + return ''; } else { return undefined; } @@ -65,7 +65,7 @@ export function getStringLiteral(node: ts.JsxAttribute | ts.JsxSpreadAttribute): */ export function getBooleanLiteral(node: ts.JsxAttribute): boolean | undefined { if (!isJsxAttribute(node)) { - throw new Error("The node must be a JsxAttribute collected by the AST parser."); + throw new Error('The node must be a JsxAttribute collected by the AST parser.'); } const initializer = node === undefined ? undefined : node.initializer; @@ -74,9 +74,9 @@ export function getBooleanLiteral(node: ts.JsxAttribute): boolean | undefined { } const getBooleanFromString: (value: string) => boolean | undefined = (value: string) => { - if (value.toLowerCase() === "true") { + if (value.toLowerCase() === 'true') { return true; - } else if (value.toLowerCase() === "false") { + } else if (value.toLowerCase() === 'false') { return false; } else { return undefined; @@ -112,11 +112,11 @@ export function isEmpty(node: ts.JsxAttribute): boolean { if (initializer === undefined) { return true; } else if (isStringLiteral(initializer)) { - return initializer.text.trim() === ""; + return initializer.text.trim() === ''; } else if (initializer.expression !== undefined) { const expression: ts.Expression = initializer.expression; if (expression.kind === ts.SyntaxKind.Identifier) { - return expression.getText() === "undefined"; + return expression.getText() === 'undefined'; } else if (expression.kind === ts.SyntaxKind.NullKeyword) { return true; } @@ -131,7 +131,7 @@ export function isEmpty(node: ts.JsxAttribute): boolean { */ export function getNumericLiteral(node: ts.JsxAttribute): string | undefined { if (!isJsxAttribute(node)) { - throw new Error("The node must be a JsxAttribute collected by the AST parser."); + throw new Error('The node must be a JsxAttribute collected by the AST parser.'); } const initializer = node === undefined ? undefined : node.initializer; @@ -161,7 +161,7 @@ export function getAllAttributesFromJsxElement(node: ts.Node): ts.NodeArray { - const prefix: string = AstUtils.isStatic(element) && node.name !== undefined ? node.name.getText() + "." : "this."; + const prefix: string = AstUtils.isStatic(element) && node.name !== undefined ? node.name.getText() + '.' : 'this.'; if (element.kind === ts.SyntaxKind.MethodDeclaration) { // add all declared methods as valid functions diff --git a/src/utils/TypeGuard.ts b/src/utils/TypeGuard.ts index 69293e387..4e7f2fa98 100644 --- a/src/utils/TypeGuard.ts +++ b/src/utils/TypeGuard.ts @@ -1,4 +1,4 @@ -import * as ts from "typescript"; +import * as ts from 'typescript'; /** * TypeScript 2.0 will have more features to support type guard. @@ -54,9 +54,9 @@ export function isNullKeyword(node: ts.Node): node is ts.LiteralExpression { } export function isObject(value: unknown): value is { [key: string]: unknown } { - return value !== undefined && typeof value === "object" && !Array.isArray(value); + return value !== undefined && typeof value === 'object' && !Array.isArray(value); } export function isNamed(node: ts.Node): node is ts.Node & { name: ts.Node } { - return "name" in node && (<{ name: ts.Node }>node).name !== undefined; + return 'name' in node && (<{ name: ts.Node }>node).name !== undefined; } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 463692e88..ccd0bdd58 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,4 +1,4 @@ -import * as path from "path"; +import * as path from 'path'; /** * Control flow functions. @@ -59,17 +59,17 @@ export namespace Utils { export function trimTo(source: string | undefined, maxLength: number): string { if (source === undefined) { - return ""; + return ''; } if (source.length <= maxLength) { return source; } - return source.substr(0, maxLength - 2) + "..."; + return source.substr(0, maxLength - 2) + '...'; } export function absolutePath(relativePath: string): string { // Replaces \ with / to match format of ts.SourceFile.fileName on Windows - return path.resolve(relativePath).replace(/\\/g, "/"); + return path.resolve(relativePath).replace(/\\/g, '/'); } } /* tslint:enable:no-increment-decrement */ diff --git a/src/utils/getImplicitRole.ts b/src/utils/getImplicitRole.ts index 8dfbcfb18..d00d2fbe8 100644 --- a/src/utils/getImplicitRole.ts +++ b/src/utils/getImplicitRole.ts @@ -1,6 +1,6 @@ -import * as ts from "typescript"; -import { implicitRoles } from "./implicitRoles"; -import { isJsxElement, isJsxSelfClosingElement, isJsxOpeningElement } from "./TypeGuard"; +import * as ts from 'typescript'; +import { implicitRoles } from './implicitRoles'; +import { isJsxElement, isJsxSelfClosingElement, isJsxOpeningElement } from './TypeGuard'; /** * @returns string of the implicit role or undefined if no corresponding role for a diff --git a/src/utils/implicitRoles/a.ts b/src/utils/implicitRoles/a.ts index ccbd95b73..470b0a69b 100644 --- a/src/utils/implicitRoles/a.ts +++ b/src/utils/implicitRoles/a.ts @@ -1,13 +1,13 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement } from '../JsxAttribute'; -const hrefString: string = "href"; +const hrefString: string = 'href'; /** * @Returns the implicit role for an anchor tag. */ function getImplicitRoleForAnchor(node: ts.Node): string | undefined { - return getJsxAttributesFromJsxElement(node)[hrefString] ? "link" : undefined; + return getJsxAttributesFromJsxElement(node)[hrefString] ? 'link' : undefined; } export { getImplicitRoleForAnchor as a }; diff --git a/src/utils/implicitRoles/area.ts b/src/utils/implicitRoles/area.ts index 3e7671735..8ffa6fb0d 100644 --- a/src/utils/implicitRoles/area.ts +++ b/src/utils/implicitRoles/area.ts @@ -1,13 +1,13 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement } from '../JsxAttribute'; -const hrefString: string = "href"; +const hrefString: string = 'href'; /** * @Returns the implicit role for an area tag. */ function getImplicitRoleForArea(node: ts.Node): string | undefined { - return getJsxAttributesFromJsxElement(node)[hrefString] ? "link" : undefined; + return getJsxAttributesFromJsxElement(node)[hrefString] ? 'link' : undefined; } export { getImplicitRoleForArea as area }; diff --git a/src/utils/implicitRoles/article.ts b/src/utils/implicitRoles/article.ts index 77c37ebe8..69caee375 100644 --- a/src/utils/implicitRoles/article.ts +++ b/src/utils/implicitRoles/article.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an article tag. */ function getImplicitRoleForArticle(): string { - return "article"; + return 'article'; } export { getImplicitRoleForArticle as article }; diff --git a/src/utils/implicitRoles/aside.ts b/src/utils/implicitRoles/aside.ts index 1a9994e31..29301ed18 100644 --- a/src/utils/implicitRoles/aside.ts +++ b/src/utils/implicitRoles/aside.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an aside tag. */ function getImplicitRoleForAside(): string { - return "complementary"; + return 'complementary'; } export { getImplicitRoleForAside as aside }; diff --git a/src/utils/implicitRoles/body.ts b/src/utils/implicitRoles/body.ts index 520d6ec0b..ed996075b 100644 --- a/src/utils/implicitRoles/body.ts +++ b/src/utils/implicitRoles/body.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a body tag. */ function getImplicitRoleForBody(): string { - return "document"; + return 'document'; } export { getImplicitRoleForBody as body }; diff --git a/src/utils/implicitRoles/button.ts b/src/utils/implicitRoles/button.ts index e67cab42b..270a0ecb8 100644 --- a/src/utils/implicitRoles/button.ts +++ b/src/utils/implicitRoles/button.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a button tag. */ function getImplicitRoleForButton(): string { - return "button"; + return 'button'; } export { getImplicitRoleForButton as button }; diff --git a/src/utils/implicitRoles/datalist.ts b/src/utils/implicitRoles/datalist.ts index dc5ea2cc2..d85f03fbb 100644 --- a/src/utils/implicitRoles/datalist.ts +++ b/src/utils/implicitRoles/datalist.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a datalist tag. */ function getImplicitRoleForDatalist(): string { - return "listbox"; + return 'listbox'; } export { getImplicitRoleForDatalist as datalist }; diff --git a/src/utils/implicitRoles/dd.ts b/src/utils/implicitRoles/dd.ts index 8242e9cb6..484873503 100644 --- a/src/utils/implicitRoles/dd.ts +++ b/src/utils/implicitRoles/dd.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a dd tag. */ function getImplicitRoleForDd(): string { - return "definition"; + return 'definition'; } export { getImplicitRoleForDd as dd }; diff --git a/src/utils/implicitRoles/details.ts b/src/utils/implicitRoles/details.ts index 9dd495cd1..8212380a0 100644 --- a/src/utils/implicitRoles/details.ts +++ b/src/utils/implicitRoles/details.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a details tag. */ function getImplicitRoleForDetails(): string { - return "group"; + return 'group'; } export { getImplicitRoleForDetails as details }; diff --git a/src/utils/implicitRoles/dialog.ts b/src/utils/implicitRoles/dialog.ts index e7d536f56..6f53bb151 100644 --- a/src/utils/implicitRoles/dialog.ts +++ b/src/utils/implicitRoles/dialog.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a dialog tag. */ function getImplicitRoleForDialog(): string { - return "dialog"; + return 'dialog'; } export { getImplicitRoleForDialog as dialog }; diff --git a/src/utils/implicitRoles/dl.ts b/src/utils/implicitRoles/dl.ts index 2abfd6b1f..1a319ee6f 100644 --- a/src/utils/implicitRoles/dl.ts +++ b/src/utils/implicitRoles/dl.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a dl tag. */ function getImplicitRoleForDl(): string { - return "list"; + return 'list'; } export { getImplicitRoleForDl as dl }; diff --git a/src/utils/implicitRoles/dt.ts b/src/utils/implicitRoles/dt.ts index 9752bf931..43dd9c89c 100644 --- a/src/utils/implicitRoles/dt.ts +++ b/src/utils/implicitRoles/dt.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a dt tag. */ function getImplicitRoleForDt(): string { - return "listitem"; + return 'listitem'; } export { getImplicitRoleForDt as dt }; diff --git a/src/utils/implicitRoles/footer.ts b/src/utils/implicitRoles/footer.ts index 99f62ff69..45485a547 100644 --- a/src/utils/implicitRoles/footer.ts +++ b/src/utils/implicitRoles/footer.ts @@ -1,11 +1,11 @@ -import * as ts from "typescript"; -import { getAncestorNode } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getAncestorNode } from '../JsxAttribute'; /** * @Returns the implicit role for a footer tag. */ function getImplicitRoleForFooter(node: ts.Node): string | undefined { - return getAncestorNode(node, "article") || getAncestorNode(node, "section") ? undefined : "contentinfo"; + return getAncestorNode(node, 'article') || getAncestorNode(node, 'section') ? undefined : 'contentinfo'; } export { getImplicitRoleForFooter as footer }; diff --git a/src/utils/implicitRoles/form.ts b/src/utils/implicitRoles/form.ts index 427fbffba..009275ddd 100644 --- a/src/utils/implicitRoles/form.ts +++ b/src/utils/implicitRoles/form.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a form tag. */ function getImplicitRoleForForm(): string { - return "form"; + return 'form'; } export { getImplicitRoleForForm as form }; diff --git a/src/utils/implicitRoles/h1.ts b/src/utils/implicitRoles/h1.ts index c5e6f6e84..988d5d116 100644 --- a/src/utils/implicitRoles/h1.ts +++ b/src/utils/implicitRoles/h1.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h1 tag. */ function getImplicitRoleForH1(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH1 as h1 }; diff --git a/src/utils/implicitRoles/h2.ts b/src/utils/implicitRoles/h2.ts index a2e0fe973..58a46f567 100644 --- a/src/utils/implicitRoles/h2.ts +++ b/src/utils/implicitRoles/h2.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h2 tag. */ function getImplicitRoleForH2(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH2 as h2 }; diff --git a/src/utils/implicitRoles/h3.ts b/src/utils/implicitRoles/h3.ts index 6cd35e57b..6bc2de041 100644 --- a/src/utils/implicitRoles/h3.ts +++ b/src/utils/implicitRoles/h3.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h3 tag. */ function getImplicitRoleForH3(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH3 as h3 }; diff --git a/src/utils/implicitRoles/h4.ts b/src/utils/implicitRoles/h4.ts index e52436b51..0cd69b0e2 100644 --- a/src/utils/implicitRoles/h4.ts +++ b/src/utils/implicitRoles/h4.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h4 tag. */ function getImplicitRoleForH4(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH4 as h4 }; diff --git a/src/utils/implicitRoles/h5.ts b/src/utils/implicitRoles/h5.ts index bbd50fc07..e32522ad0 100644 --- a/src/utils/implicitRoles/h5.ts +++ b/src/utils/implicitRoles/h5.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h5 tag. */ function getImplicitRoleForH5(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH5 as h5 }; diff --git a/src/utils/implicitRoles/h6.ts b/src/utils/implicitRoles/h6.ts index bcfb24bac..fd427a623 100644 --- a/src/utils/implicitRoles/h6.ts +++ b/src/utils/implicitRoles/h6.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an h6 tag. */ function getImplicitRoleForH6(): string { - return "heading"; + return 'heading'; } export { getImplicitRoleForH6 as h6 }; diff --git a/src/utils/implicitRoles/header.ts b/src/utils/implicitRoles/header.ts index f0cbdafcb..255a59cf2 100644 --- a/src/utils/implicitRoles/header.ts +++ b/src/utils/implicitRoles/header.ts @@ -1,11 +1,11 @@ -import * as ts from "typescript"; -import { getAncestorNode } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getAncestorNode } from '../JsxAttribute'; /** * @Returns the implicit role for a header tag. */ function getImplicitRoleForHeader(node: ts.Node): string | undefined { - return getAncestorNode(node, "article") || getAncestorNode(node, "section") ? undefined : "banner"; + return getAncestorNode(node, 'article') || getAncestorNode(node, 'section') ? undefined : 'banner'; } export { getImplicitRoleForHeader as header }; diff --git a/src/utils/implicitRoles/hr.ts b/src/utils/implicitRoles/hr.ts index f32b56412..6fa189497 100644 --- a/src/utils/implicitRoles/hr.ts +++ b/src/utils/implicitRoles/hr.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an hr tag. */ function getImplicitRoleForHr(): string { - return "separator"; + return 'separator'; } export { getImplicitRoleForHr as hr }; diff --git a/src/utils/implicitRoles/img.ts b/src/utils/implicitRoles/img.ts index 03f695cd5..cf9706c36 100644 --- a/src/utils/implicitRoles/img.ts +++ b/src/utils/implicitRoles/img.ts @@ -1,7 +1,7 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement, getStringLiteral } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement, getStringLiteral } from '../JsxAttribute'; -const altString: string = "alt"; +const altString: string = 'alt'; /** * @Returns the implicit role for an img tag. @@ -10,10 +10,10 @@ function getImplicitRoleForImg(node: ts.Node): string { const alt: ts.JsxAttribute = getJsxAttributesFromJsxElement(node)[altString]; if (alt && getStringLiteral(alt)) { - return "img"; + return 'img'; } - return "presentation"; + return 'presentation'; } export { getImplicitRoleForImg as img }; diff --git a/src/utils/implicitRoles/index.ts b/src/utils/implicitRoles/index.ts index b63aba15a..722da1e9b 100644 --- a/src/utils/implicitRoles/index.ts +++ b/src/utils/implicitRoles/index.ts @@ -1,54 +1,54 @@ -import * as ts from "typescript"; +import * as ts from 'typescript'; -import { a } from "./a"; -import { area } from "./area"; -import { article } from "./article"; -import { aside } from "./aside"; -import { body } from "./body"; -import { button } from "./button"; -import { datalist } from "./datalist"; -import { dd } from "./dd"; -import { details } from "./details"; -import { dialog } from "./dialog"; -import { dl } from "./dl"; -import { dt } from "./dt"; -import { footer } from "./footer"; -import { form } from "./form"; -import { h1 } from "./h1"; -import { h2 } from "./h2"; -import { h3 } from "./h3"; -import { h4 } from "./h4"; -import { h5 } from "./h5"; -import { h6 } from "./h6"; -import { header } from "./header"; -import { hr } from "./hr"; -import { img } from "./img"; -import { input } from "./input"; -import { li } from "./li"; -import { link } from "./link"; -import { main } from "./main"; -import { math } from "./math"; -import { menu } from "./menu"; -import { menuitem } from "./menuitem"; -import { meter } from "./meter"; -import { nav } from "./nav"; -import { ol } from "./ol"; -import { optgroup } from "./optgroup"; -import { option } from "./option"; -import { output } from "./output"; -import { progress } from "./progress"; -import { section } from "./section"; -import { select } from "./select"; -import { summary } from "./summary"; -import { table } from "./table"; -import { tbody } from "./tbody"; -import { td } from "./td"; -import { textarea } from "./textarea"; -import { tfoot } from "./tfoot"; -import { th } from "./th"; -import { thead } from "./thead"; -import { tr } from "./tr"; -import { ul } from "./ul"; +import { a } from './a'; +import { area } from './area'; +import { article } from './article'; +import { aside } from './aside'; +import { body } from './body'; +import { button } from './button'; +import { datalist } from './datalist'; +import { dd } from './dd'; +import { details } from './details'; +import { dialog } from './dialog'; +import { dl } from './dl'; +import { dt } from './dt'; +import { footer } from './footer'; +import { form } from './form'; +import { h1 } from './h1'; +import { h2 } from './h2'; +import { h3 } from './h3'; +import { h4 } from './h4'; +import { h5 } from './h5'; +import { h6 } from './h6'; +import { header } from './header'; +import { hr } from './hr'; +import { img } from './img'; +import { input } from './input'; +import { li } from './li'; +import { link } from './link'; +import { main } from './main'; +import { math } from './math'; +import { menu } from './menu'; +import { menuitem } from './menuitem'; +import { meter } from './meter'; +import { nav } from './nav'; +import { ol } from './ol'; +import { optgroup } from './optgroup'; +import { option } from './option'; +import { output } from './output'; +import { progress } from './progress'; +import { section } from './section'; +import { select } from './select'; +import { summary } from './summary'; +import { table } from './table'; +import { tbody } from './tbody'; +import { td } from './td'; +import { textarea } from './textarea'; +import { tfoot } from './tfoot'; +import { th } from './th'; +import { thead } from './thead'; +import { tr } from './tr'; +import { ul } from './ul'; export interface IImplicitRoles { [i: string]: (node: ts.Node) => string | undefined; diff --git a/src/utils/implicitRoles/input.ts b/src/utils/implicitRoles/input.ts index cfdcf09f6..a58d0c567 100644 --- a/src/utils/implicitRoles/input.ts +++ b/src/utils/implicitRoles/input.ts @@ -1,8 +1,8 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement, getStringLiteral } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement, getStringLiteral } from '../JsxAttribute'; -const typeString: string = "type"; -const listString: string = "list"; +const typeString: string = 'type'; +const listString: string = 'list'; /** * @returns the implicit role for an input tag. @@ -12,48 +12,48 @@ function getImplicitRoleForInput(node: ts.Node): string | undefined { const typeAttribute: ts.JsxAttribute = attributes[typeString]; if (typeAttribute) { - const value: string = getStringLiteral(typeAttribute) || ""; + const value: string = getStringLiteral(typeAttribute) || ''; // tslint:disable:no-switch-case-fall-through switch (value.toUpperCase()) { - case "BUTTON": - case "IMAGE": - case "RESET": - case "SUBMIT": - return "button"; - case "CHECKBOX": - return "checkbox"; - case "NUMBER": - return "spinbutton"; - case "PASSWORD": - return "textbox"; - case "RADIO": - return "radio"; - case "RANGE": - return "slider"; - case "SEARCH": - return attributes[listString] ? "combobox" : "searchbox"; - case "EMAIL": - case "TEL": - case "URL": - case "TEXT": - return attributes[listString] ? "combobox" : "textbox"; - case "COLOR": - case "DATE": - case "DATETIME": - case "FILE": - case "HIDDEN": - case "MONTH": - case "TIME": - case "WEEK": + case 'BUTTON': + case 'IMAGE': + case 'RESET': + case 'SUBMIT': + return 'button'; + case 'CHECKBOX': + return 'checkbox'; + case 'NUMBER': + return 'spinbutton'; + case 'PASSWORD': + return 'textbox'; + case 'RADIO': + return 'radio'; + case 'RANGE': + return 'slider'; + case 'SEARCH': + return attributes[listString] ? 'combobox' : 'searchbox'; + case 'EMAIL': + case 'TEL': + case 'URL': + case 'TEXT': + return attributes[listString] ? 'combobox' : 'textbox'; + case 'COLOR': + case 'DATE': + case 'DATETIME': + case 'FILE': + case 'HIDDEN': + case 'MONTH': + case 'TIME': + case 'WEEK': return undefined; default: - return "textbox"; + return 'textbox'; } } // tslint:enable:no-switch-case-fall-through - return "textbox"; + return 'textbox'; } export { getImplicitRoleForInput as input }; diff --git a/src/utils/implicitRoles/li.ts b/src/utils/implicitRoles/li.ts index 22e95ea1f..ac483bdfc 100644 --- a/src/utils/implicitRoles/li.ts +++ b/src/utils/implicitRoles/li.ts @@ -1,5 +1,5 @@ -import * as ts from "typescript"; -import { isJsxElement } from "../TypeGuard"; +import * as ts from 'typescript'; +import { isJsxElement } from '../TypeGuard'; /** * @Returns the implicit role for an li tag. @@ -12,7 +12,7 @@ function getImplicitRoleForLi(node: ts.Node): string | undefined { parentTagName = parentNode.openingElement.tagName.getText(); } - return parentTagName === "ol" || parentTagName === "ul" ? "listitem" : undefined; + return parentTagName === 'ol' || parentTagName === 'ul' ? 'listitem' : undefined; } export { getImplicitRoleForLi as li }; diff --git a/src/utils/implicitRoles/link.ts b/src/utils/implicitRoles/link.ts index cf18e16f3..7041dd5dd 100644 --- a/src/utils/implicitRoles/link.ts +++ b/src/utils/implicitRoles/link.ts @@ -1,13 +1,13 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement } from '../JsxAttribute'; -const hrefString: string = "href"; +const hrefString: string = 'href'; /** * @Returns the implicit role for a link tag. */ function getImplicitRoleForLink(node: ts.Node): string | undefined { - return getJsxAttributesFromJsxElement(node)[hrefString] ? "link" : undefined; + return getJsxAttributesFromJsxElement(node)[hrefString] ? 'link' : undefined; } export { getImplicitRoleForLink as link }; diff --git a/src/utils/implicitRoles/main.ts b/src/utils/implicitRoles/main.ts index 571fee8aa..6db9a6691 100644 --- a/src/utils/implicitRoles/main.ts +++ b/src/utils/implicitRoles/main.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a main tag. */ function getImplicitRoleForMain(): string { - return "main"; + return 'main'; } export { getImplicitRoleForMain as main }; diff --git a/src/utils/implicitRoles/math.ts b/src/utils/implicitRoles/math.ts index c712079b6..a644c33b8 100644 --- a/src/utils/implicitRoles/math.ts +++ b/src/utils/implicitRoles/math.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a math tag. */ function getImplicitRoleForMath(): string { - return "math"; + return 'math'; } export { getImplicitRoleForMath as math }; diff --git a/src/utils/implicitRoles/menu.ts b/src/utils/implicitRoles/menu.ts index d01baef66..9c7b0dc2b 100644 --- a/src/utils/implicitRoles/menu.ts +++ b/src/utils/implicitRoles/menu.ts @@ -1,7 +1,7 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement, getStringLiteral } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement, getStringLiteral } from '../JsxAttribute'; -const typeString: string = "type"; +const typeString: string = 'type'; /** * @Returns the implicit role for a menu tag. @@ -12,7 +12,7 @@ function getImplicitRoleForMenu(node: ts.Node): string | undefined { if (typeAttribute) { const value = getStringLiteral(typeAttribute) || undefined; - return value && value.toUpperCase() === "TOOLBAR" ? "toolbar" : undefined; + return value && value.toUpperCase() === 'TOOLBAR' ? 'toolbar' : undefined; } return undefined; diff --git a/src/utils/implicitRoles/menuitem.ts b/src/utils/implicitRoles/menuitem.ts index ee237b720..61e4f8b13 100644 --- a/src/utils/implicitRoles/menuitem.ts +++ b/src/utils/implicitRoles/menuitem.ts @@ -1,7 +1,7 @@ -import * as ts from "typescript"; -import { getJsxAttributesFromJsxElement, getStringLiteral } from "../JsxAttribute"; +import * as ts from 'typescript'; +import { getJsxAttributesFromJsxElement, getStringLiteral } from '../JsxAttribute'; -const typeString: string = "type"; +const typeString: string = 'type'; /** * @Returns the implicit role for a menuitem tag. @@ -10,15 +10,15 @@ function getImplicitRoleForMenuitem(node: ts.Node): string | undefined { const typeAttribute: ts.JsxAttribute = getJsxAttributesFromJsxElement(node)[typeString]; if (typeAttribute) { - const value = getStringLiteral(typeAttribute) || ""; + const value = getStringLiteral(typeAttribute) || ''; switch (value.toUpperCase()) { - case "COMMAND": - return "menuitem"; - case "CHECKBOX": - return "menuitemcheckbox"; - case "RADIO": - return "menuitemradio"; + case 'COMMAND': + return 'menuitem'; + case 'CHECKBOX': + return 'menuitemcheckbox'; + case 'RADIO': + return 'menuitemradio'; default: return undefined; } diff --git a/src/utils/implicitRoles/meter.ts b/src/utils/implicitRoles/meter.ts index 5badc67b6..14eeca841 100644 --- a/src/utils/implicitRoles/meter.ts +++ b/src/utils/implicitRoles/meter.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a meter tag. */ function getImplicitRoleForMeter(): string { - return "progressbar"; + return 'progressbar'; } export { getImplicitRoleForMeter as meter }; diff --git a/src/utils/implicitRoles/nav.ts b/src/utils/implicitRoles/nav.ts index 8f9762610..42ad0de24 100644 --- a/src/utils/implicitRoles/nav.ts +++ b/src/utils/implicitRoles/nav.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a nav tag. */ function getImplicitRoleForNav(): string { - return "navigation"; + return 'navigation'; } export { getImplicitRoleForNav as nav }; diff --git a/src/utils/implicitRoles/ol.ts b/src/utils/implicitRoles/ol.ts index 615350ccc..98f631071 100644 --- a/src/utils/implicitRoles/ol.ts +++ b/src/utils/implicitRoles/ol.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an ol tag. */ function getImplicitRoleForOl(): string { - return "list"; + return 'list'; } export { getImplicitRoleForOl as ol }; diff --git a/src/utils/implicitRoles/optgroup.ts b/src/utils/implicitRoles/optgroup.ts index 7ed02c305..76943c5e4 100644 --- a/src/utils/implicitRoles/optgroup.ts +++ b/src/utils/implicitRoles/optgroup.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a optgroup tag. */ function getImplicitRoleForOptgroup(): string { - return "group"; + return 'group'; } export { getImplicitRoleForOptgroup as optgroup }; diff --git a/src/utils/implicitRoles/option.ts b/src/utils/implicitRoles/option.ts index 73da91c9a..9111b5bc6 100644 --- a/src/utils/implicitRoles/option.ts +++ b/src/utils/implicitRoles/option.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an option tag. */ function getImplicitRoleForOption(): string { - return "option"; + return 'option'; } export { getImplicitRoleForOption as option }; diff --git a/src/utils/implicitRoles/output.ts b/src/utils/implicitRoles/output.ts index 0de18c2bf..2ccd144bb 100644 --- a/src/utils/implicitRoles/output.ts +++ b/src/utils/implicitRoles/output.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for an output tag. */ function getImplicitRoleForOutput(): string { - return "status"; + return 'status'; } export { getImplicitRoleForOutput as output }; diff --git a/src/utils/implicitRoles/progress.ts b/src/utils/implicitRoles/progress.ts index f5cbba27b..31d1cd7e7 100644 --- a/src/utils/implicitRoles/progress.ts +++ b/src/utils/implicitRoles/progress.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a progress tag. */ function getImplicitRoleForProgress(): string { - return "progressbar"; + return 'progressbar'; } export { getImplicitRoleForProgress as progress }; diff --git a/src/utils/implicitRoles/section.ts b/src/utils/implicitRoles/section.ts index 1f555f3b7..dd46cea75 100644 --- a/src/utils/implicitRoles/section.ts +++ b/src/utils/implicitRoles/section.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a section tag. */ function getImplicitRoleForSection(): string { - return "region"; + return 'region'; } export { getImplicitRoleForSection as section }; diff --git a/src/utils/implicitRoles/select.ts b/src/utils/implicitRoles/select.ts index fdabd1db2..ce003e38e 100644 --- a/src/utils/implicitRoles/select.ts +++ b/src/utils/implicitRoles/select.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a select tag. */ function getImplicitRoleForSelect(): string { - return "listbox"; + return 'listbox'; } export { getImplicitRoleForSelect as select }; diff --git a/src/utils/implicitRoles/summary.ts b/src/utils/implicitRoles/summary.ts index 61ae850a8..da4549682 100644 --- a/src/utils/implicitRoles/summary.ts +++ b/src/utils/implicitRoles/summary.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a summary tag. */ function getImplicitRoleForSummary(): string { - return "button"; + return 'button'; } export { getImplicitRoleForSummary as summary }; diff --git a/src/utils/implicitRoles/table.ts b/src/utils/implicitRoles/table.ts index 38d75b0d8..10a69ac49 100644 --- a/src/utils/implicitRoles/table.ts +++ b/src/utils/implicitRoles/table.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a table tag. */ function getImplicitRoleForTable(): string { - return "table"; + return 'table'; } export { getImplicitRoleForTable as table }; diff --git a/src/utils/implicitRoles/tbody.ts b/src/utils/implicitRoles/tbody.ts index d1d9874c0..7ae791405 100644 --- a/src/utils/implicitRoles/tbody.ts +++ b/src/utils/implicitRoles/tbody.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a tbody tag. */ function getImplicitRoleForTbody(): string { - return "rowgroup"; + return 'rowgroup'; } export { getImplicitRoleForTbody as tbody }; diff --git a/src/utils/implicitRoles/td.ts b/src/utils/implicitRoles/td.ts index 1cb9aa97b..113398c06 100644 --- a/src/utils/implicitRoles/td.ts +++ b/src/utils/implicitRoles/td.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a td tag. */ function getImplicitRoleForTd(): string { - return "cell"; + return 'cell'; } export { getImplicitRoleForTd as td }; diff --git a/src/utils/implicitRoles/textarea.ts b/src/utils/implicitRoles/textarea.ts index 698e83aad..4c84a93ea 100644 --- a/src/utils/implicitRoles/textarea.ts +++ b/src/utils/implicitRoles/textarea.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a textarea tag. */ function getImplicitRoleForTextarea(): string { - return "textbox"; + return 'textbox'; } export { getImplicitRoleForTextarea as textarea }; diff --git a/src/utils/implicitRoles/tfoot.ts b/src/utils/implicitRoles/tfoot.ts index a5d0cb398..9919d650f 100644 --- a/src/utils/implicitRoles/tfoot.ts +++ b/src/utils/implicitRoles/tfoot.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a tfoot tag. */ function getImplicitRoleForTfoot(): string { - return "rowgroup"; + return 'rowgroup'; } export { getImplicitRoleForTfoot as tfoot }; diff --git a/src/utils/implicitRoles/th.ts b/src/utils/implicitRoles/th.ts index c73b150ea..0ca07248e 100644 --- a/src/utils/implicitRoles/th.ts +++ b/src/utils/implicitRoles/th.ts @@ -3,7 +3,7 @@ * The implicit role is columnheader or rowheader, the func only return columnheader. */ function getImplicitRoleForTh(): string { - return "columnheader"; + return 'columnheader'; } export { getImplicitRoleForTh as th }; diff --git a/src/utils/implicitRoles/thead.ts b/src/utils/implicitRoles/thead.ts index 87b1f60a8..84a917eab 100644 --- a/src/utils/implicitRoles/thead.ts +++ b/src/utils/implicitRoles/thead.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a thead tag. */ function getImplicitRoleForThead(): string { - return "rowgroup"; + return 'rowgroup'; } export { getImplicitRoleForThead as thead }; diff --git a/src/utils/implicitRoles/tr.ts b/src/utils/implicitRoles/tr.ts index 4d2352e01..1d01cf743 100644 --- a/src/utils/implicitRoles/tr.ts +++ b/src/utils/implicitRoles/tr.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a tr tag. */ function getImplicitRoleForTr(): string { - return "row"; + return 'row'; } export { getImplicitRoleForTr as tr }; diff --git a/src/utils/implicitRoles/ul.ts b/src/utils/implicitRoles/ul.ts index cd808077a..eeebfd408 100644 --- a/src/utils/implicitRoles/ul.ts +++ b/src/utils/implicitRoles/ul.ts @@ -2,7 +2,7 @@ * @Returns the implicit role for a ul tag. */ function getImplicitRoleForUl(): string { - return "list"; + return 'list'; } export { getImplicitRoleForUl as ul }; diff --git a/src/validTypeofRule.ts b/src/validTypeofRule.ts index 845c4b95a..f245109f1 100644 --- a/src/validTypeofRule.ts +++ b/src/validTypeofRule.ts @@ -1,33 +1,33 @@ -import * as ts from "typescript"; -import * as Lint from "tslint"; +import * as ts from 'typescript'; +import * as Lint from 'tslint'; -import { ExtendedMetadata } from "./utils/ExtendedMetadata"; +import { ExtendedMetadata } from './utils/ExtendedMetadata'; export class Rule extends Lint.Rules.AbstractRule { public static metadata: ExtendedMetadata = { - ruleName: "valid-typeof", - type: "maintainability", - description: "Ensures that the results of typeof are compared against a valid string.", + ruleName: 'valid-typeof', + type: 'maintainability', + description: 'Ensures that the results of typeof are compared against a valid string.', options: null, // tslint:disable-line:no-null-keyword - optionsDescription: "", + optionsDescription: '', typescriptOnly: true, - issueClass: "Non-SDL", - issueType: "Error", - severity: "Critical", - level: "Opportunity for Excellence", - recommendation: "false,", - group: "Deprecated" + issueClass: 'Non-SDL', + issueType: 'Error', + severity: 'Critical', + level: 'Opportunity for Excellence', + recommendation: 'false,', + group: 'Deprecated' }; - public static FAILURE_STRING: string = "Invalid comparison in typeof. Did you mean "; + public static FAILURE_STRING: string = 'Invalid comparison in typeof. Did you mean '; - public static VALID_TERMS: string[] = ["undefined", "object", "boolean", "number", "string", "function", "symbol"]; + public static VALID_TERMS: string[] = ['undefined', 'object', 'boolean', 'number', 'string', 'function', 'symbol']; private static isWarningShown: boolean = false; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { if (Rule.isWarningShown === false) { - console.warn("Warning: valid-typeof rule is deprecated. Replace your usage with the TSLint typeof-compare rule."); + console.warn('Warning: valid-typeof rule is deprecated. Replace your usage with the TSLint typeof-compare rule.'); Rule.isWarningShown = true; } return this.applyWithWalker(new ValidTypeofRuleWalker(sourceFile, this.getOptions())); @@ -48,7 +48,7 @@ class ValidTypeofRuleWalker extends Lint.RuleWalker { if (Rule.VALID_TERMS.indexOf(node.text) === -1) { const start: number = node.getStart(); const width: number = node.getWidth(); - this.addFailureAt(start, width, Rule.FAILURE_STRING + this.getClosestTerm(node.text) + "?"); + this.addFailureAt(start, width, Rule.FAILURE_STRING + this.getClosestTerm(node.text) + '?'); } } @@ -61,7 +61,7 @@ class ValidTypeofRuleWalker extends Lint.RuleWalker { closestTerm = thisTerm; } return closestTerm; - }, ""); + }, ''); } /** diff --git a/test-data/NoCookies/NoCookiesFailingTestInput.ts b/test-data/NoCookies/NoCookiesFailingTestInput.ts index ce77c55fd..6316014c6 100644 --- a/test-data/NoCookies/NoCookiesFailingTestInput.ts +++ b/test-data/NoCookies/NoCookiesFailingTestInput.ts @@ -2,11 +2,11 @@ function documentFunction(): Document { return window.document; } -document.cookie = "..."; -this.document.cookie = "..."; -window.document.cookie = "..."; +document.cookie = '...'; +this.document.cookie = '...'; +window.document.cookie = '...'; -documentFunction().cookie = "..."; +documentFunction().cookie = '...'; var doc = document; -doc.cookie = "..."; +doc.cookie = '...'; diff --git a/test-data/NoCookies/NoCookiesPassingTestInput.ts b/test-data/NoCookies/NoCookiesPassingTestInput.ts index a97d7c765..d91410b80 100644 --- a/test-data/NoCookies/NoCookiesPassingTestInput.ts +++ b/test-data/NoCookies/NoCookiesPassingTestInput.ts @@ -8,6 +8,6 @@ function documentLikeAPIFunction(): DocumentLikeAPI { // These usages are OK because they are not on the DOM document var document2: DocumentLikeAPI = documentLikeAPIFunction(); -document2.cookie = "..."; -document2.cookie = "..."; -documentLikeAPIFunction().cookie = "..."; +document2.cookie = '...'; +document2.cookie = '...'; +documentLikeAPIFunction().cookie = '...'; diff --git a/test-data/NoFunctionConstructorWithStringArgsTestInput.ts b/test-data/NoFunctionConstructorWithStringArgsTestInput.ts index c76cc27c1..4eae349de 100644 --- a/test-data/NoFunctionConstructorWithStringArgsTestInput.ts +++ b/test-data/NoFunctionConstructorWithStringArgsTestInput.ts @@ -1,4 +1,4 @@ -var f = new Function("doSomething()"); +var f = new Function('doSomething()'); () => { alert(1); diff --git a/test-data/NoOctalLiteral/NoOctalLiteralTestInput-passing.ts b/test-data/NoOctalLiteral/NoOctalLiteralTestInput-passing.ts index c97d7fe36..56a31ffe9 100644 --- a/test-data/NoOctalLiteral/NoOctalLiteralTestInput-passing.ts +++ b/test-data/NoOctalLiteral/NoOctalLiteralTestInput-passing.ts @@ -1,13 +1,13 @@ function demoScriptPass1() { - var w1 = "Sample text \xB2"; - var x1 = "Sample text \0111"; // longer than octal - var y1 = "Sample text \\1"; - var z1 = "Sample text \\\\1"; + var w1 = 'Sample text \xB2'; + var x1 = 'Sample text \0111'; // longer than octal + var y1 = 'Sample text \\1'; + var z1 = 'Sample text \\\\1'; - var w2 = "Sample text \xB2"; - var x2 = "Sample text \0111"; // longer than octal - var y2 = "Sample text \\1"; - var z2 = "Sample text \\\\1"; + var w2 = 'Sample text \xB2'; + var x2 = 'Sample text \0111'; // longer than octal + var y2 = 'Sample text \\1'; + var z2 = 'Sample text \\\\1'; var w3 = `Sample text \xB2`; var x3 = `Sample text \0111`; // longer than octal diff --git a/test-data/NoStringBasedSetImmediateTestInput.ts b/test-data/NoStringBasedSetImmediateTestInput.ts index a2c094d75..e4949ce52 100644 --- a/test-data/NoStringBasedSetImmediateTestInput.ts +++ b/test-data/NoStringBasedSetImmediateTestInput.ts @@ -8,7 +8,7 @@ interface Window { // tslint:enable -var typedStringVariable = "string variable"; +var typedStringVariable = 'string variable'; var functionVariable = () => {}; var anyVariable: any = () => {}; var createFunction: () => (() => void) = () => { @@ -16,7 +16,7 @@ var createFunction: () => (() => void) = () => { }; // function that produces a function var untypedCreateFunction: () => any = () => {}; // function that produces a function var stringFunction: () => string = () => { - return ""; + return ''; }; // function that produces a string // lambdas are OK diff --git a/test-data/NoStringBasedSetIntervalTestInput.ts b/test-data/NoStringBasedSetIntervalTestInput.ts index 4942b599f..005e995e7 100644 --- a/test-data/NoStringBasedSetIntervalTestInput.ts +++ b/test-data/NoStringBasedSetIntervalTestInput.ts @@ -1,4 +1,4 @@ -var typedStringVariable = "string variable"; +var typedStringVariable = 'string variable'; var functionVariable = () => {}; var anyVariable: any = () => {}; var createFunction: () => (() => void) = () => { @@ -6,7 +6,7 @@ var createFunction: () => (() => void) = () => { }; // function that produces a function var untypedCreateFunction: () => any = () => {}; // function that produces a function var stringFunction: () => string = () => { - return ""; + return ''; }; // function that produces a string // lambdas are OK diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-functions.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-functions.ts index 6c9349e4c..bbaf8e332 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-functions.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-functions.ts @@ -1,5 +1,5 @@ var stringFunction: () => string = () => { - return ""; + return ''; }; // function that produces a string // these should all create violations diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-variables.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-variables.ts index fadf943ef..8bebde0f8 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-variables.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-string-variables.ts @@ -1,4 +1,4 @@ -var typedStringVariable = "string variable"; +var typedStringVariable = 'string variable'; // these should all create violations setTimeout(typedStringVariable); // example 2 diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-template-strings.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-template-strings.ts index 17c02e2b7..19951937f 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-template-strings.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutFailingTestInput-template-strings.ts @@ -1,2 +1,2 @@ -var data = "alert(1)"; +var data = 'alert(1)'; window.setTimeout(`${data}`, 200); diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-case4.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-case4.ts index 2b7853170..69b753831 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-case4.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-case4.ts @@ -1,6 +1,6 @@ var function1 = () => { var functionVariable = () => {}; - var typedStringVariable = "string variable"; + var typedStringVariable = 'string variable'; // expressions of type function are OK setTimeout(functionVariable); diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error3.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error3.ts index 162ce759c..3b62d11e2 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error3.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error3.ts @@ -9,7 +9,7 @@ namespace MyModule { private myMethod(param1: any): void {} private perform(): void { - setTimeout(_.bind(this.myMethod, "some value"), 500); + setTimeout(_.bind(this.myMethod, 'some value'), 500); } } } diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error4.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error4.ts index 91bc4ffda..70cd83429 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error4.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-error4.ts @@ -1,5 +1,5 @@ namespace SetTimeoutSample { - "use strict"; + 'use strict'; class MyClass { private onAnimationEnd(): Function { diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-issue46.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-issue46.ts index b105b9d9b..c30ace91e 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-issue46.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-issue46.ts @@ -10,8 +10,8 @@ class TestClassIssue46 { //Strings const alertNum = 1; - setTimeout("alert(" + alertNum + ")", 100); - window.setTimeout("alert(" + alertNum + ")", 100); + setTimeout('alert(' + alertNum + ')', 100); + window.setTimeout('alert(' + alertNum + ')', 100); //TS Template Strings setTimeout(`alert(${alertNum})`, 100); diff --git a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-shadowedVariables.ts b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-shadowedVariables.ts index 6123732da..a744409dc 100644 --- a/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-shadowedVariables.ts +++ b/test-data/NoStringBasedSetTimeout/NoStringBasedSetTimeoutTestInput-shadowedVariables.ts @@ -10,7 +10,7 @@ namespace SetTimeoutModule { var moduleProp3 = function() {}; var globalProp1: any; // ! shadow ! - var globalFunctionShadow1 = "not a function"; // ! shadow ! + var globalFunctionShadow1 = 'not a function'; // ! shadow ! function moduleFunction1(globalProp2: any, moduleProp1: any) { // ! shadow ! diff --git a/test-data/NoUnnecessarySemicolonsTestInput.ts b/test-data/NoUnnecessarySemicolonsTestInput.ts index 013558b77..d3ea24216 100644 --- a/test-data/NoUnnecessarySemicolonsTestInput.ts +++ b/test-data/NoUnnecessarySemicolonsTestInput.ts @@ -1,3 +1,6 @@ // these are 3 empty statements +; +;; + // this is an empty statement but should not trigger a warning while (false) {} diff --git a/test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx b/test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx index 9cce31e79..420ec8c19 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssue-anon-instance.tsx @@ -1,5 +1,5 @@ -import React = require("react"); -import _ = require("underscore"); +import React = require('react'); +import _ = require('underscore'); export class MyComponent extends React.Component<{}, {}> { private listener(): void {} @@ -9,7 +9,7 @@ export class MyComponent extends React.Component<{}, {}> { // all of these examples create instances of anonymous functions on every render() call - + // create some self-closing elements as welll {}} /> diff --git a/test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx b/test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx index 3a4d27cbd..fca85217e 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssue-doublebinding.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); export class MyComponent extends React.Component<{}, {}> { constructor(props, context) { diff --git a/test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx b/test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx index fee7f63c8..41505565e 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssue-local-instance.tsx @@ -1,5 +1,5 @@ -import React = require("react"); -import _ = require("underscore"); +import React = require('react'); +import _ = require('underscore'); export class MyComponent extends React.Component<{}, {}> { private listenerMethod() {} diff --git a/test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx b/test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx index 72265503d..38e9f5c06 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssue-passing.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); export class BaseClass extends React.Component<{}, {}> { public notALocalMethod(): void {} @@ -24,7 +24,7 @@ export class MyComponent extends BaseClass { public render() { return (
- {" "} + {' '} // this is not a real method, so it is OK
); diff --git a/test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx b/test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx index 9ce7cbde0..db280b2e5 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssue-unbound.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); export class MyComponent extends React.Component<{}, {}> { private listener(): void {} diff --git a/test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx b/test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx index e80738567..f4d951f73 100644 --- a/test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx +++ b/test-data/ReactThisBinding/ReactThisBindingIssueWithDecorator-passing.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); export class BaseClass extends React.Component<{}, {}> { public notALocalMethod(): void {} @@ -18,7 +18,7 @@ export class MyComponent extends BaseClass { public render() { return (
- {" "} + {' '} // this is not a real method, so it is OK
); diff --git a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx index eecbee534..f1c506192 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasEmptyAltValueAndNotPresentationRole.tsx @@ -1,10 +1,10 @@ -import React = require("react"); +import React = require('react'); let Picture = props => ; const a = ; const b = ; -const c = ; +const c = ; const d = ; const e = ; -const f = {""}; +const f = {''}; diff --git a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNoAltProp.tsx b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNoAltProp.tsx index fbc2e4726..07630126e 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNoAltProp.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNoAltProp.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); let Picture = props => ; diff --git a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx index 47cc5516b..a1b44c620 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/FailingTestInputs/CustomElementHasNonEmptyAltValueAndPresentationRole.tsx @@ -1,10 +1,10 @@ -import React = require("react"); +import React = require('react'); let Picture = props => ; let altValue; const a = ; -const b = ; +const b = ; const c = ; const d = altValue; const e = altValue; diff --git a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx index 6fd5f4659..6d7e655cf 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/CustomElementHasNonEmptyAltValueAndNotPresentationRole.tsx @@ -1,11 +1,11 @@ -import React = require("react"); +import React = require('react'); let Picture = props => ; let validAltValue; const a = ; const b = ; -const c = ; +const c = ; const d = validAltValue; const e = {validAltValue}; -const f = {"validAltValue"}; +const f = {'validAltValue'}; diff --git a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/ElementNeitherImgNorCustomElement.tsx b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/ElementNeitherImgNorCustomElement.tsx index 911c6b36e..5e7a34408 100644 --- a/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/ElementNeitherImgNorCustomElement.tsx +++ b/test-data/a11yImgHasAlt/CustomElementTests/PassingTestInputs/ElementNeitherImgNorCustomElement.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); const a =
; const b = ; diff --git a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNoAlt.tsx b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNoAlt.tsx index 6b12b0b55..d962ab1a8 100644 --- a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNoAlt.tsx +++ b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNoAlt.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); const a = ; const b = ; diff --git a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx index 1cd939556..a7e320552 100644 --- a/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx +++ b/test-data/a11yImgHasAlt/DefaltTests/FailingTestInputs/ImgElementHasNonEmptyAltValueAndPresentationRole.tsx @@ -1,12 +1,12 @@ -import React = require("react"); +import React = require('react'); let altValue; const a = altValue; const b = altValue; -const c = {altValue}; -const d = {"altValue"}; +const c = {altValue}; +const d = {'altValue'}; const e = W3Schools.com; const f = W3Schools.com; -const g = W3Schools.com; +const g = W3Schools.com; diff --git a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ElementNotImg.tsx b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ElementNotImg.tsx index 1cec55e17..2cdfdbdaf 100644 --- a/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ElementNotImg.tsx +++ b/test-data/a11yImgHasAlt/DefaltTests/PassingTestInputs/ElementNotImg.tsx @@ -1,4 +1,4 @@ -import React = require("react"); +import React = require('react'); const a =
; const b =