Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Use tsutils package for utilities #2217

Merged
merged 1 commit into from
Feb 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"glob": "^7.1.1",
"optimist": "~0.6.0",
"resolve": "^1.1.7",
"tsutils": "^1.0.0",
"update-notifier": "^2.0.0"
},
"peerDependencies": {
Expand All @@ -68,7 +69,7 @@
"rimraf": "^2.5.4",
"tslint": "latest",
"tslint-test-config-non-relative": "file:test/external/tslint-test-config-non-relative",
"typescript": "2.1.4"
"typescript": "^2.1.6"
},
"license": "Apache-2.0",
"engines": {
Expand Down
28 changes: 14 additions & 14 deletions src/enableDisableRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import {AbstractRule} from "./language/rule/abstractRule";
import {forEachComment, TokenPosition} from "./language/utils";
import {IEnableDisablePosition} from "./ruleLoader";

export class EnableDisableRulesWalker {
Expand All @@ -42,11 +42,11 @@ export class EnableDisableRulesWalker {
}

public getEnableDisableRuleMap() {
forEachComment(this.sourceFile, (fullText, kind, pos) => {
const commentText = kind === ts.SyntaxKind.SingleLineCommentTrivia
? fullText.substring(pos.tokenStart + 2, pos.end)
: fullText.substring(pos.tokenStart + 2, pos.end - 2);
return this.handleComment(commentText, pos);
utils.forEachComment(this.sourceFile, (fullText, comment) => {
const commentText = comment.kind === ts.SyntaxKind.SingleLineCommentTrivia
? fullText.substring(comment.pos + 2, comment.end)
: fullText.substring(comment.pos + 2, comment.end - 2);
return this.handleComment(commentText, comment);
});

return this.enableDisableRuleMap;
Expand Down Expand Up @@ -85,7 +85,7 @@ export class EnableDisableRulesWalker {
}
}

private handleComment(commentText: string, pos: TokenPosition) {
private handleComment(commentText: string, range: ts.TextRange) {
// regex is: start of string followed by any amount of whitespace
// followed by tslint and colon
// followed by either "enable" or "disable"
Expand All @@ -110,32 +110,32 @@ export class EnableDisableRulesWalker {
rulesList = this.enabledRules;
}

this.handleTslintLineSwitch(rulesList, match[1] === "enable", match[2], pos);
this.handleTslintLineSwitch(rulesList, match[1] === "enable", match[2], range);
}
}

private handleTslintLineSwitch(rules: string[], isEnabled: boolean, modifier: string, pos: TokenPosition) {
private handleTslintLineSwitch(rules: string[], isEnabled: boolean, modifier: string, range: ts.TextRange) {
let start: number | undefined;
let end: number | undefined;

if (modifier === "line") {
// start at the beginning of the line where comment starts
start = this.getStartOfLinePosition(pos.tokenStart)!;
start = this.getStartOfLinePosition(range.pos)!;
// end at the beginning of the line following the comment
end = this.getStartOfLinePosition(pos.end, 1);
end = this.getStartOfLinePosition(range.end, 1);
} else if (modifier === "next-line") {
// start at the beginning of the line following the comment
start = this.getStartOfLinePosition(pos.end, 1);
start = this.getStartOfLinePosition(range.end, 1);
if (start === undefined) {
// no need to switch anything, there is no next line
return;
}
// end at the beginning of the line following the next line
end = this.getStartOfLinePosition(pos.end, 2);
end = this.getStartOfLinePosition(range.end, 2);
} else {
// switch rule for the rest of the file
// start at the current position, but skip end position
start = pos.tokenStart;
start = range.pos;
end = undefined;
}

Expand Down
26 changes: 4 additions & 22 deletions src/rules/adjacentOverloadSignaturesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -114,32 +115,13 @@ interface Overload {
name: string;
}

function isLiteralExpression(node: ts.Node): node is ts.LiteralExpression {
return node.kind === ts.SyntaxKind.StringLiteral || node.kind === ts.SyntaxKind.NumericLiteral;
}

export function getOverloadKey(node: ts.SignatureDeclaration): string | undefined {
const o = getOverload(node);
return o && o.key;
}

function getOverloadIfSignature(node: ts.TypeElement | ts.ClassElement): Overload | undefined {
return isSignatureDeclaration(node) ? getOverload(node) : undefined;
}

export function isSignatureDeclaration(node: ts.Node): node is ts.SignatureDeclaration {
switch (node.kind) {
case ts.SyntaxKind.ConstructSignature:
case ts.SyntaxKind.Constructor:
case ts.SyntaxKind.CallSignature:
case ts.SyntaxKind.CallSignature:
case ts.SyntaxKind.MethodSignature:
case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.FunctionDeclaration:
return true;
default:
return false;
}
return utils.isSignatureDeclaration(node) ? getOverload(node) : undefined;
}

function getOverload(node: ts.SignatureDeclaration): Overload | undefined {
Expand Down Expand Up @@ -173,8 +155,8 @@ function getPropertyInfo(name: ts.PropertyName): { name: string, computed?: bool
return { name: (name as ts.Identifier).text };
case ts.SyntaxKind.ComputedPropertyName:
const { expression } = (name as ts.ComputedPropertyName);
return isLiteralExpression(expression) ? { name: expression.text } : { name: expression.getText(), computed: true };
return utils.isLiteralExpression(expression) ? { name: expression.text } : { name: expression.getText(), computed: true };
default:
return isLiteralExpression(name) ? { name: (name as ts.StringLiteral).text } : undefined;
return utils.isLiteralExpression(name) ? { name: (name as ts.StringLiteral).text } : undefined;
}
}
9 changes: 5 additions & 4 deletions src/rules/commentFormatRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -117,10 +118,10 @@ class CommentWalker extends Lint.RuleWalker {
}

public visitSourceFile(node: ts.SourceFile) {
Lint.forEachComment(node, (fullText, kind, pos) => {
if (kind === ts.SyntaxKind.SingleLineCommentTrivia) {
const commentText = fullText.substring(pos.tokenStart, pos.end);
const startPosition = pos.tokenStart + 2;
utils.forEachComment(node, (fullText, comment) => {
if (comment.kind === ts.SyntaxKind.SingleLineCommentTrivia) {
const commentText = fullText.substring(comment.pos, comment.end);
const startPosition = comment.pos + 2;
const width = commentText.length - 2;
if (this.hasOption(OPTION_SPACE)) {
if (!startsWithSpace(commentText)) {
Expand Down
14 changes: 3 additions & 11 deletions src/rules/importBlacklistRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";
import * as Lint from "../index";

Expand Down Expand Up @@ -66,7 +67,7 @@ class ImportBlacklistWalker extends Lint.RuleWalker {
}

public visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration) {
if (isExternalModuleReference(node.moduleReference) &&
if (utils.isExternalModuleReference(node.moduleReference) &&
node.moduleReference.expression !== undefined) {
// If it's an import require and not an import alias
this.checkForBannedImport(node.moduleReference.expression);
Expand All @@ -80,7 +81,7 @@ class ImportBlacklistWalker extends Lint.RuleWalker {
}

private checkForBannedImport(expression: ts.Expression) {
if (isStringLiteral(expression) && this.hasOption(expression.text)) {
if (utils.isTextualLiteral(expression) && this.hasOption(expression.text)) {
this.addFailureFromStartToEnd(
expression.getStart(this.getSourceFile()) + 1,
expression.getEnd() - 1,
Expand All @@ -89,12 +90,3 @@ class ImportBlacklistWalker extends Lint.RuleWalker {
}
}
}

function isStringLiteral(node: ts.Node): node is ts.LiteralExpression {
return node.kind === ts.SyntaxKind.StringLiteral ||
node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral;
}

function isExternalModuleReference(node: ts.ModuleReference): node is ts.ExternalModuleReference {
return node.kind === ts.SyntaxKind.ExternalModuleReference;
}
7 changes: 4 additions & 3 deletions src/rules/jsdocFormatRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -50,9 +51,9 @@ export class Rule extends Lint.Rules.AbstractRule {

class JsdocWalker extends Lint.RuleWalker {
public visitSourceFile(node: ts.SourceFile) {
Lint.forEachComment(node, (fullText, kind, pos) => {
if (kind === ts.SyntaxKind.MultiLineCommentTrivia) {
this.findFailuresForJsdocComment(fullText.substring(pos.tokenStart, pos.end), pos.tokenStart);
utils.forEachComment(node, (fullText, comment) => {
if (comment.kind === ts.SyntaxKind.MultiLineCommentTrivia) {
this.findFailuresForJsdocComment(fullText.substring(comment.pos, comment.end), comment.pos);
}
});
}
Expand Down
7 changes: 2 additions & 5 deletions src/rules/newlineBeforeReturnRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";
import * as Lint from "../index";

Expand Down Expand Up @@ -47,7 +48,7 @@ class NewlineBeforeReturnWalker extends Lint.RuleWalker {
super.visitReturnStatement(node);

const parent = node.parent!;
if (!isBlockLike(parent)) {
if (!utils.isBlockLike(parent)) {
// `node` is the only statement within this "block scope". No need to do any further validation.
return;
}
Expand Down Expand Up @@ -75,7 +76,3 @@ class NewlineBeforeReturnWalker extends Lint.RuleWalker {
}
}
}

function isBlockLike(node: ts.Node): node is ts.BlockLike {
return "statements" in node;
}
19 changes: 10 additions & 9 deletions src/rules/noTrailingWhitespaceRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -73,29 +74,29 @@ export class Rule extends Lint.Rules.AbstractRule {
function walk(ctx: Lint.WalkContext<IgnoreOption>) {
let lastSeenWasWhitespace = false;
let lastSeenWhitespacePosition = 0;
Lint.forEachToken(ctx.sourceFile, false, (fullText, kind, pos) => {
utils.forEachTokenWithTrivia(ctx.sourceFile, (fullText, kind, range) => {
if (kind === ts.SyntaxKind.NewLineTrivia || kind === ts.SyntaxKind.EndOfFileToken) {
if (lastSeenWasWhitespace) {
reportFailure(ctx, lastSeenWhitespacePosition, pos.tokenStart);
reportFailure(ctx, lastSeenWhitespacePosition, range.pos);
}
lastSeenWasWhitespace = false;
} else if (kind === ts.SyntaxKind.WhitespaceTrivia) {
lastSeenWasWhitespace = true;
lastSeenWhitespacePosition = pos.tokenStart;
lastSeenWhitespacePosition = range.pos;
} else {
if (ctx.options !== IgnoreOption.Comments) {
if (kind === ts.SyntaxKind.SingleLineCommentTrivia) {
const commentText = fullText.substring(pos.tokenStart + 2, pos.end);
const commentText = fullText.substring(range.pos + 2, range.end);
const match = /\s+$/.exec(commentText);
if (match !== null) {
reportFailure(ctx, pos.end - match[0].length, pos.end);
reportFailure(ctx, range.end - match[0].length, range.end);
}
} else if (kind === ts.SyntaxKind.MultiLineCommentTrivia &&
(ctx.options !== IgnoreOption.JsDoc ||
fullText[pos.tokenStart + 2] !== "*" ||
fullText[pos.tokenStart + 3] === "*")) {
let startPos = pos.tokenStart + 2;
const commentText = fullText.substring(startPos, pos.end - 2);
fullText[range.pos + 2] !== "*" ||
fullText[range.pos + 3] === "*")) {
let startPos = range.pos + 2;
const commentText = fullText.substring(startPos, range.end - 2);
const lines = commentText.split("\n");
// we don't want to check the content of the last comment line, as it is always followed by */
const len = lines.length - 1;
Expand Down
7 changes: 2 additions & 5 deletions src/rules/noUnnecessaryInitializerRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -45,7 +46,7 @@ export class Rule extends Lint.Rules.AbstractRule {

class Walker extends Lint.RuleWalker {
public visitVariableDeclaration(node: ts.VariableDeclaration) {
if (isBindingPattern(node.name)) {
if (utils.isBindingPattern(node.name)) {
for (const elem of node.name.elements) {
if (elem.kind === ts.SyntaxKind.BindingElement) {
this.checkInitializer(elem);
Expand Down Expand Up @@ -115,7 +116,3 @@ function isUndefined(node: ts.Node | undefined): boolean {
node.kind === ts.SyntaxKind.Identifier &&
(node as ts.Identifier).originalKeywordKind === ts.SyntaxKind.UndefinedKeyword;
}

function isBindingPattern(node: ts.Node): node is ts.ArrayBindingPattern | ts.ObjectBindingPattern {
return node.kind === ts.SyntaxKind.ArrayBindingPattern || node.kind === ts.SyntaxKind.ObjectBindingPattern;
}
8 changes: 2 additions & 6 deletions src/rules/noUnnecessaryQualifierRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -67,7 +68,7 @@ class Walker extends Lint.ProgramAwareRuleWalker {
break;
case ts.SyntaxKind.PropertyAccessExpression:
const { expression, name } = node as ts.PropertyAccessExpression;
if (isEntityNameExpression(expression)) {
if (utils.isEntityNameExpression(expression)) {
this.visitNamespaceAccess(node, expression, name);
break;
}
Expand Down Expand Up @@ -126,11 +127,6 @@ class Walker extends Lint.ProgramAwareRuleWalker {
}
}

function isEntityNameExpression(expr: ts.Expression): expr is ts.EntityNameExpression {
return expr.kind === ts.SyntaxKind.Identifier ||
expr.kind === ts.SyntaxKind.PropertyAccessExpression && isEntityNameExpression((expr as ts.PropertyAccessExpression).expression);
}

// TODO: Should just be `===`. See https://github.com/palantir/tslint/issues/1969
function nodesAreEqual(a: ts.Node, b: ts.Node) {
return a.pos === b.pos;
Expand Down
10 changes: 4 additions & 6 deletions src/rules/noUnsafeAnyRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ export class Rule extends Lint.Rules.TypedRule {
}
}

// This is marked @internal, but we need it!
const isExpression: (node: ts.Node) => node is ts.Expression = (ts as any).isExpression;

class Walker extends Lint.ProgramAwareRuleWalker {
public visitNode(node: ts.Node) {
if (ts.isExpression(node) && isAny(this.getType(node)) && !this.isAllowedLocation(node)) {
if (isExpression(node) && isAny(this.getType(node)) && !this.isAllowedLocation(node)) {
this.addFailureAtNode(node, Rule.FAILURE_STRING);
} else {
super.visitNode(node);
Expand Down Expand Up @@ -111,8 +114,3 @@ class Walker extends Lint.ProgramAwareRuleWalker {
function isAny(type: ts.Type | undefined): boolean {
return type !== undefined && Lint.isTypeFlagSet(type, ts.TypeFlags.Any);
}

// This is marked @internal, but we need it!
declare module "typescript" {
export function isExpression(node: ts.Node): node is ts.Expression;
}
Loading