tslint-microsoft-contrib
Advanced tools
Comparing version
@@ -53,2 +53,20 @@ "use strict"; | ||
exports.Rule = Rule; | ||
function isExportedDeclaration(element) { | ||
return AstUtils_1.AstUtils.hasModifier(element.modifiers, ts.SyntaxKind.ExportKeyword); | ||
} | ||
function isExportStatement(node) { | ||
return ts.isExportAssignment(node) || ts.isExportDeclaration(node); | ||
} | ||
function getExportsFromStatement(node) { | ||
if (ts.isExportAssignment(node)) { | ||
return [[node.expression.getText(), node.expression]]; | ||
} | ||
else { | ||
var symbolAndNodes_1 = []; | ||
node.exportClause.elements.forEach(function (e) { | ||
symbolAndNodes_1.push([e.name.getText(), node]); | ||
}); | ||
return symbolAndNodes_1; | ||
} | ||
} | ||
var ExportNameWalker = (function (_super) { | ||
@@ -61,15 +79,11 @@ __extends(ExportNameWalker, _super); | ||
var _this = this; | ||
var singleExport = node.statements.filter(function (element) { | ||
return element.kind === ts.SyntaxKind.ExportAssignment; | ||
}); | ||
var singleExport = node.statements.filter(isExportStatement); | ||
if (singleExport.length === 1) { | ||
var exportAssignment = singleExport[0]; | ||
this.validateExport(exportAssignment.expression.getText(), exportAssignment.expression); | ||
var symbolsAndNodes = getExportsFromStatement(singleExport[0]); | ||
if (symbolsAndNodes.length === 1) { | ||
this.validateExport(symbolsAndNodes[0][0], symbolsAndNodes[0][1]); | ||
} | ||
return; | ||
} | ||
var exportedTopLevelElements = []; | ||
node.statements.forEach(function (element) { | ||
var exportStatements = _this.getExportStatements(element); | ||
exportedTopLevelElements = exportedTopLevelElements.concat(exportStatements); | ||
}); | ||
var exportedTopLevelElements = node.statements.filter(isExportedDeclaration); | ||
if (exportedTopLevelElements.length === 0) { | ||
@@ -86,3 +100,2 @@ node.statements.forEach(function (element) { | ||
ExportNameWalker.prototype.getExportStatementsWithinModules = function (moduleDeclaration) { | ||
var _this = this; | ||
if (moduleDeclaration.body.kind === ts.SyntaxKind.ModuleDeclaration) { | ||
@@ -92,22 +105,7 @@ return this.getExportStatementsWithinModules(moduleDeclaration.body); | ||
else if (moduleDeclaration.body.kind === ts.SyntaxKind.ModuleBlock) { | ||
var exportStatements_1 = []; | ||
var moduleBlock = moduleDeclaration.body; | ||
moduleBlock.statements.forEach(function (element) { | ||
exportStatements_1 = exportStatements_1.concat(_this.getExportStatements(element)); | ||
}); | ||
return exportStatements_1; | ||
return moduleBlock.statements.filter(isExportedDeclaration); | ||
} | ||
return null; | ||
}; | ||
ExportNameWalker.prototype.getExportStatements = function (element) { | ||
var exportStatements = []; | ||
if (element.kind === ts.SyntaxKind.ExportAssignment) { | ||
var exportAssignment = element; | ||
this.validateExport(exportAssignment.expression.getText(), exportAssignment.expression); | ||
} | ||
else if (AstUtils_1.AstUtils.hasModifier(element.modifiers, ts.SyntaxKind.ExportKeyword)) { | ||
exportStatements.push(element); | ||
} | ||
return exportStatements; | ||
}; | ||
ExportNameWalker.prototype.validateExportedElements = function (exportedElements) { | ||
@@ -114,0 +112,0 @@ if (exportedElements.length === 1) { |
@@ -148,2 +148,5 @@ "use strict"; | ||
} | ||
if (/^this\.(retries|slow|timeout)\(.+\)$/.test(initializer.getText())) { | ||
return; | ||
} | ||
if (initializer.getText() === 'moment()') { | ||
@@ -150,0 +153,0 @@ return; |
@@ -51,3 +51,3 @@ "use strict"; | ||
}); | ||
if (!walker.isAccessingThis) { | ||
if (!walker.isAccessingThis && !node.asteriskToken) { | ||
this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING); | ||
@@ -54,0 +54,0 @@ } |
@@ -37,3 +37,3 @@ "use strict"; | ||
group: 'Security', | ||
recommendation: '[true, "http://www.example.com/?.*", "http://www.examples.com/?.*"],', | ||
recommendation: '[true, "http://www.example.com/?.*", "http://localhost:?.*"],', | ||
commonWeaknessEnumeration: '319' | ||
@@ -40,0 +40,0 @@ }; |
@@ -19,3 +19,3 @@ "use strict"; | ||
var FAILURE_OUTER = 'Writing a string to the outerHTML property is insecure: '; | ||
var FAILURE_JQUERY = 'Using the html() function to write a string to innerHTML is insecure: '; | ||
var FAILURE_HTML_LIB = 'Using the html() function to write a string to innerHTML is insecure: '; | ||
var Rule = (function (_super) { | ||
@@ -48,4 +48,10 @@ __extends(Rule, _super); | ||
__extends(NoInnerHtmlRuleWalker, _super); | ||
function NoInnerHtmlRuleWalker() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
function NoInnerHtmlRuleWalker(sourceFile, options) { | ||
var _this = _super.call(this, sourceFile, options) || this; | ||
_this.htmlLibExpressionRegex = /^(jquery|[$])/i; | ||
var opt = _this.getOptions(); | ||
if (typeof opt[1] === 'object' && opt[1]['html-lib-matcher']) { | ||
_this.htmlLibExpressionRegex = new RegExp(opt[1]['html-lib-matcher']); | ||
} | ||
return _this; | ||
} | ||
@@ -71,3 +77,6 @@ NoInnerHtmlRuleWalker.prototype.visitBinaryExpression = function (node) { | ||
if (node.arguments.length > 0) { | ||
this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_JQUERY + node.getText()); | ||
var functionTarget = AstUtils_1.AstUtils.getFunctionTarget(node); | ||
if (this.htmlLibExpressionRegex.test(functionTarget)) { | ||
this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_HTML_LIB + node.getText()); | ||
} | ||
} | ||
@@ -74,0 +83,0 @@ } |
@@ -48,3 +48,3 @@ "use strict"; | ||
NoOctalLiteral.prototype.visitNode = function (node) { | ||
if (node.kind === ts.SyntaxKind.StringLiteral) { | ||
if (node.kind === ts.SyntaxKind.StringLiteral || node.kind === ts.SyntaxKind.FirstTemplateToken) { | ||
this.failOnOctalString(node); | ||
@@ -55,8 +55,12 @@ } | ||
NoOctalLiteral.prototype.failOnOctalString = function (node) { | ||
var match = /("|')(.*(\\-?[0-7]{1,3}(?![0-9])).*("|'))/g.exec(node.getText()); | ||
var match = /("|'|`)[^\\]*(\\+-?[0-7]{1,3}(?![0-9]))(?:.|\n|\t|\u2028|\u2029)*(?:\1)/g.exec(node.getText()); | ||
if (match) { | ||
var octalValue = match[3]; | ||
var startOfMatch = node.getStart() + node.getText().indexOf(octalValue); | ||
var width = octalValue.length; | ||
this.addFailureAt(startOfMatch, width, Rule.FAILURE_STRING + octalValue); | ||
var octalValue = match[2]; | ||
var backslashCount = octalValue.lastIndexOf('\\') + 1; | ||
if (backslashCount % 2 === 1) { | ||
octalValue = octalValue.substr(backslashCount - 1); | ||
var startOfMatch = node.getStart() + node.getText().indexOf(octalValue); | ||
var width = octalValue.length; | ||
this.addFailureAt(startOfMatch, width, Rule.FAILURE_STRING + octalValue); | ||
} | ||
} | ||
@@ -63,0 +67,0 @@ }; |
@@ -53,3 +53,4 @@ "use strict"; | ||
&& _this.isSingleLineComment(tokenText) | ||
&& !_this.isTsLintSuppression(tokenText)) { | ||
&& !_this.isTsLintSuppression(tokenText) | ||
&& !_this.isFollowedByMoreCodeOnSameLine(fullText, range)) { | ||
_this.addFailureAt(range.pos, range.end - range.pos, FAILURE_STRING); | ||
@@ -66,4 +67,8 @@ } | ||
}; | ||
NoSingleLineBlockCommentRuleWalker.prototype.isFollowedByMoreCodeOnSameLine = function (fullText, range) { | ||
var restOfText = fullText.substring(range.end); | ||
return /^\s*\r?\n/.test(restOfText) === false; | ||
}; | ||
return NoSingleLineBlockCommentRuleWalker; | ||
}(Lint.RuleWalker)); | ||
//# sourceMappingURL=noSingleLineBlockCommentRule.js.map |
@@ -29,3 +29,3 @@ "use strict"; | ||
type: 'maintainability', | ||
description: 'Do not use suspicious comments, such as BUG, HACK, FIXME, LATER, LATER2, TODO', | ||
description: "Do not use suspicious comments, such as " + SUSPICIOUS_WORDS.join(', '), | ||
options: null, | ||
@@ -32,0 +32,0 @@ optionsDescription: '', |
@@ -13,4 +13,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var ts = require("typescript"); | ||
var Lint = require("tslint"); | ||
var tsutils = require("tsutils"); | ||
var ErrorTolerantWalker_1 = require("./utils/ErrorTolerantWalker"); | ||
@@ -46,3 +46,5 @@ var FAILURE_STRING = 'Unnecessary local variable: '; | ||
function UnnecessaryLocalVariableRuleWalker() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this.variableUsages = tsutils.collectVariableUsage(_this.getSourceFile()); | ||
return _this; | ||
} | ||
@@ -66,3 +68,3 @@ UnnecessaryLocalVariableRuleWalker.prototype.visitBlock = function (node) { | ||
UnnecessaryLocalVariableRuleWalker.prototype.visitModuleDeclaration = function (node) { | ||
if (node.body != null && node.body.kind === ts.SyntaxKind.ModuleBlock) { | ||
if (node.body != null && tsutils.isModuleBlock(node.body)) { | ||
this.validateStatementArray(node.body.statements); | ||
@@ -79,16 +81,20 @@ } | ||
var returnedVariableName = this.tryToGetReturnedVariableName(lastStatement); | ||
var declaredVariableName = this.tryToGetDeclaredVariableName(nextToLastStatement); | ||
if (returnedVariableName != null && declaredVariableName != null) { | ||
if (returnedVariableName === declaredVariableName) { | ||
this.addFailureAt(nextToLastStatement.getStart(), nextToLastStatement.getWidth(), FAILURE_STRING + returnedVariableName); | ||
} | ||
var declaredVariableIdentifier = this.tryToGetDeclaredVariable(nextToLastStatement); | ||
if (declaredVariableIdentifier == null) { | ||
return; | ||
} | ||
var declaredVariableName = declaredVariableIdentifier.text; | ||
if (returnedVariableName != null | ||
&& declaredVariableName != null | ||
&& returnedVariableName === declaredVariableName | ||
&& this.variableIsOnlyUsedOnce(declaredVariableIdentifier)) { | ||
this.addFailureAt(nextToLastStatement.getStart(), nextToLastStatement.getWidth(), FAILURE_STRING + returnedVariableName); | ||
} | ||
}; | ||
UnnecessaryLocalVariableRuleWalker.prototype.tryToGetDeclaredVariableName = function (statement) { | ||
if (statement != null && statement.kind === ts.SyntaxKind.VariableStatement) { | ||
var variableStatement = statement; | ||
if (variableStatement.declarationList.declarations.length === 1) { | ||
var declaration = variableStatement.declarationList.declarations[0]; | ||
if (declaration.name != null && declaration.name.kind === ts.SyntaxKind.Identifier) { | ||
return declaration.name.text; | ||
UnnecessaryLocalVariableRuleWalker.prototype.tryToGetDeclaredVariable = function (statement) { | ||
if (statement != null && tsutils.isVariableStatement(statement)) { | ||
if (statement.declarationList.declarations.length === 1) { | ||
var declaration = statement.declarationList.declarations[0]; | ||
if (declaration.name != null && tsutils.isIdentifier(declaration.name)) { | ||
return declaration.name; | ||
} | ||
@@ -100,6 +106,5 @@ } | ||
UnnecessaryLocalVariableRuleWalker.prototype.tryToGetReturnedVariableName = function (statement) { | ||
if (statement != null && statement.kind === ts.SyntaxKind.ReturnStatement) { | ||
var returnStatement = statement; | ||
if (returnStatement.expression != null && returnStatement.expression.kind === ts.SyntaxKind.Identifier) { | ||
return returnStatement.expression.text; | ||
if (statement != null && tsutils.isReturnStatement(statement)) { | ||
if (statement.expression != null && tsutils.isIdentifier(statement.expression)) { | ||
return statement.expression.text; | ||
} | ||
@@ -109,4 +114,8 @@ } | ||
}; | ||
UnnecessaryLocalVariableRuleWalker.prototype.variableIsOnlyUsedOnce = function (declaredVariableIdentifier) { | ||
var usage = this.variableUsages.get(declaredVariableIdentifier); | ||
return usage !== undefined && usage.uses.length === 1; | ||
}; | ||
return UnnecessaryLocalVariableRuleWalker; | ||
}(ErrorTolerantWalker_1.ErrorTolerantWalker)); | ||
//# sourceMappingURL=noUnnecessaryLocalVariableRule.js.map |
{ | ||
"name": "tslint-microsoft-contrib", | ||
"version": "5.0.3", | ||
"version": "5.1.0", | ||
"description": "TSLint Rules for Microsoft", | ||
@@ -22,2 +22,6 @@ "repository": { | ||
"email": "hamlet.darcy@microsoft.com" | ||
}, | ||
{ | ||
"name": "Josh Goldberg", | ||
"email": "joshua.goldberg@microsoft.com" | ||
} | ||
@@ -24,0 +28,0 @@ ], |
@@ -11,3 +11,3 @@ [](https://badge.fury.io/js/tslint-microsoft-contrib) | ||
Version 5.0.3 (Stable) | ||
Version 5.1.0 (Stable) | ||
------------- | ||
@@ -18,3 +18,3 @@ The project has been in use for several years on multiple projects. Please report any bugs or false positives you might find! | ||
Version 5.0.4 (In-Development) | ||
Version 5.1.1 (In-Development) | ||
------------- | ||
@@ -31,3 +31,3 @@ The [Latest Development Version](https://github.com/Microsoft/tslint-microsoft-contrib/tree/releases) is available online. | ||
* [5.0.3](https://github.com/Microsoft/tslint-microsoft-contrib/tree/npm-5.0.3) | ||
* [5.1.0](https://github.com/Microsoft/tslint-microsoft-contrib/tree/npm-5.1.0) | ||
@@ -149,3 +149,3 @@ #### TSLint and corresponding tslint-microsoft-contrib version | ||
`react-a11y-meta` | For accessibility of your website, HTML meta elements must not have http-equiv="refresh". | 2.0.11 | ||
`react-a11y-props` | For accessibility of your website, enforce all `aria-*` attributes are valid. Elements cannot use an invalid `aria-*` attribute. This rule will fail if it finds an `aria-*` attribute that is not listed in [WAI-ARIA states and properties](https://www.w3.org/TR/wai-aria/states_and_properties#state_prop_def). | 2.0.11 | ||
`react-a11y-props` | For accessibility of your website, enforce all `aria-*` attributes are valid. Elements cannot use an invalid `aria-*` attribute. This rule will fail if it finds an `aria-*` attribute that is not listed in [WAI-ARIA states and properties](https://www.w3.org/WAI/PF/aria/states_and_properties#state_prop_values). | 2.0.11 | ||
`react-a11y-proptypes` | For accessibility of your website, enforce the type of aria state and property values are correct. | 2.0.11 | ||
@@ -152,0 +152,0 @@ `react-a11y-role-has-required-aria-props` | For accessibility of your website, elements with aria roles must have all required attributes according to the role. <br/>References:<br/>[ARIA Definition of Roles](https://www.w3.org/TR/wai-aria/roles#role_definitions)<br/>[WCAG Rule 90: Required properties and states should be defined](http://oaa-accessibility.org/wcag20/rule/90/)<br/>[WCAG Rule 91: Required properties and states must not be empty](http://oaa-accessibility.org/wcag20/rule/91/)<br/>| 2.0.11 |
@@ -22,3 +22,3 @@ /** | ||
"no-function-constructor-with-string-args": true, | ||
"no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"], | ||
"no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*", "http://localhost:?.*"], | ||
"no-inner-html": true, | ||
@@ -25,0 +25,0 @@ "no-octal-literal": true, |
@@ -16,3 +16,3 @@ { | ||
"http://www.example.com/?.*", | ||
"http://www.examples.com/?.*" | ||
"http://localhost:?.*" | ||
], | ||
@@ -46,2 +46,3 @@ "no-inner-html": true, | ||
"info", | ||
"error", | ||
"log", | ||
@@ -48,0 +49,0 @@ "time", |
@@ -35,5 +35,7 @@ "use strict"; | ||
var functionName = AstUtils_1.AstUtils.getFunctionName(call); | ||
var callText = call.expression.getText(); | ||
return functionName === 'it' || functionName === 'specify' | ||
|| functionName === 'before' || functionName === 'beforeEach' || functionName === 'beforeAll' | ||
|| functionName === 'after' || functionName === 'afterEach' || functionName === 'afterAll'; | ||
|| functionName === 'after' || functionName === 'afterEach' || functionName === 'afterAll' | ||
|| callText === 'it.skip' || callText === 'it.only'; | ||
} | ||
@@ -40,0 +42,0 @@ MochaUtils.isLifecycleMethod = isLifecycleMethod; |
@@ -29,4 +29,18 @@ "use strict"; | ||
var functionName = AstUtils_1.AstUtils.getFunctionName(node); | ||
var functionTarget = AstUtils_1.AstUtils.getFunctionTarget(node); | ||
var functionTargetType = this.getFunctionTargetType(node); | ||
var firstArg = node.arguments[0]; | ||
if (functionName === this.targetFunctionName && firstArg != null) { | ||
if (functionTarget) { | ||
if (functionTargetType) { | ||
if (!functionTargetType.match(/^(any|Window|Worker)$/)) { | ||
return; | ||
} | ||
} | ||
else { | ||
if (!functionTarget.match(/^(this|window)$/)) { | ||
return; | ||
} | ||
} | ||
} | ||
if (!this.isExpressionEvaluatingToFunction(firstArg)) { | ||
@@ -33,0 +47,0 @@ var msg = this.failureString + firstArg.getFullText().trim().substring(0, 40); |
@@ -26,2 +26,10 @@ "use strict"; | ||
} | ||
ScopedSymbolTrackingWalker.prototype.getFunctionTargetType = function (expression) { | ||
if (expression.expression.kind === ts.SyntaxKind.PropertyAccessExpression && this.typeChecker) { | ||
var propExp = expression.expression; | ||
var targetType = this.typeChecker.getTypeAtLocation(propExp.expression); | ||
return this.typeChecker.typeToString(targetType); | ||
} | ||
return null; | ||
}; | ||
ScopedSymbolTrackingWalker.prototype.isExpressionEvaluatingToFunction = function (expression) { | ||
@@ -28,0 +36,0 @@ if (expression.kind === ts.SyntaxKind.ArrowFunction |
543337
0.47%12074
0.44%