Skip to content

Commit

Permalink
Enabled no-non-null-assertion internally (microsoft#669)
Browse files Browse the repository at this point in the history
Includes @IllusionMH's changes to `exportNameRule.ts` from microsoft#666. This shouldn't be merged in until that PR is.

Continues microsoft#491.
  • Loading branch information
Josh Goldberg authored and apawast committed Feb 26, 2019
1 parent 378bc24 commit 6c22263
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 28 deletions.
11 changes: 8 additions & 3 deletions src/exportNameRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,18 @@ export class ExportNameWalker extends Lint.RuleWalker {
}

private getExportStatementsWithinModules(moduleDeclaration: ts.ModuleDeclaration): ts.Statement[] | undefined {
if (moduleDeclaration.body!.kind === ts.SyntaxKind.ModuleDeclaration) {
if (moduleDeclaration.body === undefined) {
return undefined;
}

if (moduleDeclaration.body.kind === ts.SyntaxKind.ModuleDeclaration) {
// modules may be nested so recur into the structure
return this.getExportStatementsWithinModules(<ts.ModuleDeclaration>moduleDeclaration.body);
} else if (moduleDeclaration.body!.kind === ts.SyntaxKind.ModuleBlock) {
} else if (moduleDeclaration.body.kind === ts.SyntaxKind.ModuleBlock) {
const moduleBlock: ts.ModuleBlock = <ts.ModuleBlock>moduleDeclaration.body;
return moduleBlock.statements.filter(isExportedDeclaration);
}

return undefined;
}

Expand All @@ -146,7 +151,7 @@ export class ExportNameWalker extends Lint.RuleWalker {
const element = exportedElements[0];
if (ts.isModuleDeclaration(element) || ts.isClassDeclaration(element) || ts.isFunctionDeclaration(element)) {
if (element.name !== undefined) {
this.validateExport(element.name!.text, exportedElements[0]);
this.validateExport(element.name.text, exportedElements[0]);
}
} else if (exportedElements[0].kind === ts.SyntaxKind.VariableStatement) {
const variableStatement: ts.VariableStatement = <ts.VariableStatement>exportedElements[0];
Expand Down
38 changes: 27 additions & 11 deletions src/importNameRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Lint from 'tslint';
import { Utils } from './utils/Utils';
import { ExtendedMetadata } from './utils/ExtendedMetadata';
import { isObject } from './utils/TypeGuard';
import { isImportEqualsDeclaration } from 'tsutils';

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: ExtendedMetadata = {
Expand Down Expand Up @@ -142,8 +143,8 @@ class ImportNameRuleWalker extends Lint.RuleWalker {
}

protected visitImportDeclaration(node: ts.ImportDeclaration): void {
if (node.importClause!.name !== undefined) {
const name: string = node.importClause!.name!.text;
if (node.importClause !== undefined && node.importClause.name !== undefined) {
const name: string = node.importClause.name.text;
if (node.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) {
const moduleName: string = (<ts.StringLiteral>node.moduleSpecifier).text;
this.validateImport(node, name, moduleName);
Expand All @@ -157,17 +158,32 @@ class ImportNameRuleWalker extends Lint.RuleWalker {
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
? (<ts.ImportEqualsDeclaration>node).name
: (<ts.ImportDeclaration>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);
if (this.isImportNameValid(importedName, expectedImportedName, moduleName, node)) {
return;
}

const message: string = `Misnamed import. Import should be named '${expectedImportedName}' but found '${importedName}'`;

const nameNode = this.getNameNodeFromImportNode(node);
if (nameNode === undefined) {
return;
}

const nameNodeStartPos = nameNode.getStart();
const fix = new Lint.Replacement(nameNodeStartPos, nameNode.end - nameNodeStartPos, expectedImportedName);
this.addFailureAt(node.getStart(), node.getWidth(), message, fix);
}

private getNameNodeFromImportNode(node: ts.ImportEqualsDeclaration | ts.ImportDeclaration): ts.Node | undefined {
if (isImportEqualsDeclaration(node)) {
return node.name;
}

const importClause = node.importClause;

return importClause === undefined ? undefined : importClause.name;
}

private makeCamelCase(input: string): string {
Expand Down
15 changes: 12 additions & 3 deletions src/noUnsupportedBrowserCodeRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,25 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker {
// tslint:disable-next-line:no-conditional-assignment
while ((match = regex.exec(tokenText))) {
const browser = this.parseBrowserString(match[1]);
if (browser === undefined) {
break;
}

this.findUnsupportedBrowserFailures(browser, range.pos, range.end - range.pos);
}
});
}

private parseBrowserString(browser: string): BrowserVersion {
private parseBrowserString(browser: string): BrowserVersion | undefined {
// This case-insensitive regex contains 3 capture groups:
// #1 looks for a browser name (combination of spaces and alpha)
// #2 looks for an optional comparison operator (>=, <=, etc)
// #3 looks for a version number
const regex = /([a-zA-Z ]*)(>=|<=|<|>)?\s*(\d*)/i;
const match = browser.match(regex)!;
const match = browser.match(regex);
if (match === null) {
return undefined;
}

return {
name: match[1].trim(),
Expand All @@ -89,7 +96,9 @@ class NoUnsupportedBrowserCodeRuleWalker extends Lint.RuleWalker {
if (option instanceof Array) {
option.forEach((browserString: string) => {
const browser = this.parseBrowserString(browserString);
result[browser.name.toLowerCase()] = browser;
if (browser !== undefined) {
result[browser.name.toLowerCase()] = browser;
}
});
}
});
Expand Down
1 change: 1 addition & 0 deletions src/reactA11yAnchorsRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class ReactA11yAnchorsRuleWalker extends Lint.RuleWalker {
const differentHrefSameText: IAnchorInfo[] = [];

while (this.anchorInfoList.length > 0) {
// tslint:disable-next-line:no-non-null-assertion
const current: IAnchorInfo = this.anchorInfoList.shift()!;
this.anchorInfoList.forEach(
(anchorInfo: IAnchorInfo): void => {
Expand Down
13 changes: 6 additions & 7 deletions src/reactA11yImageButtonHasAltRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,12 @@ class ReactA11yImageButtonHasAltWalker extends Lint.RuleWalker {
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)) {
return;
}

const stringLiteral = getStringLiteral(typeAttribute);
if (stringLiteral === undefined || stringLiteral.toLowerCase() !== 'image') {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/reactA11yLangRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ class ReactA11yLangRuleWalker extends Lint.RuleWalker {
if (attribute.kind === ts.SyntaxKind.JsxAttribute) {
if (attribute.name.getText() === 'lang') {
langFound = true;
if (attribute.initializer!.kind === ts.SyntaxKind.StringLiteral) {
if (attribute.initializer !== undefined && attribute.initializer.kind === ts.SyntaxKind.StringLiteral) {
const langText: string = (<ts.StringLiteral>(<ts.JsxAttribute>attribute).initializer).text;
if (LANGUAGE_CODES.indexOf(langText) === -1) {
this.addFailureAt(parent.getStart(), parent.getWidth(), FAILURE_WRONG_LANG_CODE + langText);
Expand Down
1 change: 0 additions & 1 deletion src/reactNoDangerousHtmlRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class NoDangerousHtmlWalker extends Lint.RuleWalker {
}

protected visitPropertyAssignment(node: ts.PropertyAssignment): void {
super.visitPropertyAssignment(node);
const keyNode: ts.DeclarationName = node.name;

if (keyNode.kind === ts.SyntaxKind.Identifier) {
Expand Down
10 changes: 9 additions & 1 deletion src/utils/ScopedSymbolTrackingWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ export class ScopedSymbolTrackingWalker extends Lint.RuleWalker {

protected visitModuleDeclaration(node: ts.ModuleDeclaration): void {
this.scope = new Scope(this.scope);
this.scope.addGlobalScope(node.body!, this.getSourceFile(), this.getOptions());

if (node.body !== undefined) {
this.scope.addGlobalScope(node.body, this.getSourceFile(), this.getOptions());
}

super.visitModuleDeclaration(node);
this.scope = this.scope.parent;
}
Expand Down Expand Up @@ -181,11 +185,15 @@ export class ScopedSymbolTrackingWalker extends Lint.RuleWalker {
}

protected visitVariableDeclaration(node: ts.VariableDeclaration): void {
// this.scope is always set upon entering a source file, so we know it exists here
// tslint:disable:no-non-null-assertion
if (AstUtils.isDeclarationFunctionType(node)) {
this.scope!.addFunctionSymbol(node.name.getText());
} else {
this.scope!.addNonFunctionSymbol(node.name.getText());
}
// tslint:enable:no-non-null-assertion

super.visitVariableDeclaration(node);
}
}
1 change: 0 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"no-inferrable-types": false,
"no-internal-module": false,
"no-namespace": false,
"no-non-null-assertion": false,
"no-unbound-method": false,
"no-unsafe-any": false,
"prefer-for-of": false,
Expand Down

0 comments on commit 6c22263

Please sign in to comment.