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

Commit

Permalink
Update to latest tsutils (#2984)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajafff authored and adidahiya committed Jul 5, 2017
1 parent 8da61ff commit 4e8474f
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 73 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.7.1",
"tsutils": "^2.3.0"
"tsutils": "^2.5.1"
},
"peerDependencies": {
"typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev"
Expand Down
10 changes: 6 additions & 4 deletions src/rules/deprecationRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
* limitations under the License.
*/

import { getDeclarationOfBindingElement, isBindingElement, isIdentifier, isVariableDeclaration, isVariableDeclarationList } from "tsutils";
import {
getDeclarationOfBindingElement, isBindingElement, isIdentifier, isJsDoc, isVariableDeclaration, isVariableDeclarationList,
} from "tsutils";
import * as ts from "typescript";
import * as Lint from "../index";

Expand Down Expand Up @@ -139,13 +141,13 @@ function getDeprecationFromDeclarations(declarations?: ts.Declaration[]): string
declaration = declaration.parent!;
}
for (const child of declaration.getChildren()) {
if (child.kind !== ts.SyntaxKind.JSDocComment) {
if (!isJsDoc(child)) {
break;
}
if ((child as ts.JSDoc).tags === undefined) {
if (child.tags === undefined) {
continue;
}
for (const tag of (child as ts.JSDoc).tags!) {
for (const tag of child.tags) {
if (tag.tagName.text === "deprecated") {
return tag.comment === undefined ? "" : tag.comment;
}
Expand Down
60 changes: 16 additions & 44 deletions src/rules/preferForOfRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,64 +41,36 @@ export class Rule extends Lint.Rules.AbstractRule {
}
}

interface IncrementorState {
indexVariableName: string;
arrayExpr: ts.Expression;
onlyArrayReadAccess: boolean;
}

function walk(ctx: Lint.WalkContext<void>): void {
const { sourceFile } = ctx;
const scopes: IncrementorState[] = [];

return ts.forEachChild(sourceFile, cb);

function cb(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.ForStatement:
return visitForStatement(node as ts.ForStatement);
case ts.SyntaxKind.Identifier:
return visitIdentifier(node as ts.Identifier);
default:
return ts.forEachChild(node, cb);
let variables: Map<ts.Identifier, utils.VariableInfo> | undefined;

return ts.forEachChild(sourceFile, function cb(node): void {
if (utils.isForStatement(node)) {
visitForStatement(node);
}
}
return ts.forEachChild(node, cb);
});

function visitForStatement(node: ts.ForStatement): void {
const arrayNodeInfo = getForLoopHeaderInfo(node);
if (arrayNodeInfo === undefined) {
return ts.forEachChild(node, cb);
return;
}

const { indexVariable, arrayExpr } = arrayNodeInfo;
const indexVariableName = indexVariable.text;

// store `for` loop state
const state: IncrementorState = { indexVariableName, arrayExpr, onlyArrayReadAccess: true };
scopes.push(state);
ts.forEachChild(node.statement, cb);
scopes.pop();

if (state.onlyArrayReadAccess) {
ctx.addFailure(node.getStart(), node.statement.getFullStart(), Rule.FAILURE_STRING);
if (variables === undefined) {
variables = utils.collectVariableUsage(sourceFile);
}
}

function visitIdentifier(node: ts.Identifier): void {
const state = getStateForVariable(node.text);
if (state !== undefined && state.onlyArrayReadAccess && isNonSimpleIncrementorUse(node, state.arrayExpr, sourceFile)) {
state.onlyArrayReadAccess = false;
}
}

function getStateForVariable(name: string): IncrementorState | undefined {
for (let i = scopes.length - 1; i >= 0; i--) {
const scope = scopes[i];
if (scope.indexVariableName === name) {
return scope;
for (const {location} of variables.get(indexVariable)!.uses) {
if (location.pos < node.initializer!.end || location.pos >= node.end || // bail out on use outside of for loop
location.pos >= node.statement.pos && // only check uses in loop body
isNonSimpleIncrementorUse(location, arrayExpr, sourceFile)) {
return;
}
}
return undefined;
ctx.addFailure(node.getStart(sourceFile), node.statement.pos, Rule.FAILURE_STRING);
}
}

Expand Down
27 changes: 3 additions & 24 deletions src/rules/preferObjectSpreadRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
*/

import {
hasSideEffects, isCallExpression, isIdentifier, isObjectLiteralExpression, isPropertyAccessExpression,
isSpreadElement, SideEffectOptions,
hasSideEffects, isCallExpression, isExpressionValueUsed, isIdentifier, isObjectLiteralExpression,
isPropertyAccessExpression, isSpreadElement, SideEffectOptions,
} from "tsutils";
import * as ts from "typescript";

Expand Down Expand Up @@ -54,35 +54,14 @@ function walk(ctx: Lint.WalkContext<void>) {
!node.arguments.some(isSpreadElement)) {
if (node.arguments[0].kind === ts.SyntaxKind.ObjectLiteralExpression) {
ctx.addFailureAtNode(node, Rule.FAILURE_STRING, createFix(node, ctx.sourceFile));
} else if (isReturnValueUsed(node) && !hasSideEffects(node.arguments[0], SideEffectOptions.Constructor)) {
} else if (isExpressionValueUsed(node) && !hasSideEffects(node.arguments[0], SideEffectOptions.Constructor)) {
ctx.addFailureAtNode(node, Rule.ASSIGNMENT_FAILURE_STRING, createFix(node, ctx.sourceFile));
}
}
return ts.forEachChild(node, cb);
});
}

function isReturnValueUsed(node: ts.Expression): boolean {
const parent = node.parent!;
switch (parent.kind) {
case ts.SyntaxKind.VariableDeclaration:
case ts.SyntaxKind.PropertyAssignment:
case ts.SyntaxKind.PropertyDeclaration:
case ts.SyntaxKind.ReturnStatement:
case ts.SyntaxKind.BindingElement:
case ts.SyntaxKind.ArrayLiteralExpression:
return true;
case ts.SyntaxKind.BinaryExpression:
return (parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken;
case ts.SyntaxKind.NewExpression:
case ts.SyntaxKind.CallExpression:
return (parent as ts.NewExpression | ts.CallExpression).arguments !== undefined &&
(parent as ts.NewExpression | ts.CallExpression).arguments!.indexOf(node) !== -1;
default:
return false;
}
}

function createFix(node: ts.CallExpression, sourceFile: ts.SourceFile): Lint.Fix {
const args = node.arguments;
const fix = [
Expand Down
23 changes: 23 additions & 0 deletions test/rules/prefer-for-of/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,27 @@ for (let i = 0; i < arr.length; i++) {
delete arr[i];
}

for (let i = 0; i < arr.length; ++i) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [0]
{
let i = 1;
let x = i;
let obj = {i, x};
}
i: while(true) {
let obj = {i: 1};
break i;
}

let node = arr[i];
}

function test() {
function print() {
console.log(arr[i])
}
for (var i = 0, i < arr.length, ++i)
print();
}

[0]: Expected a 'for-of' loop instead of a 'for' loop with this simple iteration
6 changes: 6 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1492,6 +1492,12 @@ tsutils@^2.3.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.4.0.tgz#ad4ce6dba0e5a3edbddf8626b7ca040782189fea"

tsutils@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.5.1.tgz#c2001390c79eec1a5ccfa7ac12d599639683e0cf"
dependencies:
tslib "^1.7.1"

type-detect@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
Expand Down

0 comments on commit 4e8474f

Please sign in to comment.