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

Commit

Permalink
Merge pull request #420 from adidahiya/destructuring-no-use-before-de…
Browse files Browse the repository at this point in the history
…clare

Add destructuring & namespace import syntax support to no-use-before-declare rule
  • Loading branch information
gscshoyru committed Jun 2, 2015
2 parents 0aa7114 + 44b9808 commit e4bfe6f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 24 deletions.
33 changes: 26 additions & 7 deletions src/rules/noUseBeforeDeclareRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
*/

export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING_PREFIX = "variable '";
Expand All @@ -27,22 +27,29 @@ export class Rule extends Lint.Rules.AbstractRule {
}
}

class NoUseBeforeDeclareWalker extends Lint.ScopeAwareRuleWalker<{}> {
type VisitedVariables = {[varName: string]: boolean};

class NoUseBeforeDeclareWalker extends Lint.ScopeAwareRuleWalker<VisitedVariables> {
private languageService: ts.LanguageService;

constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, languageService: ts.LanguageService) {
super(sourceFile, options);
this.languageService = languageService;
}

public createScope(): {} {
public createScope(): VisitedVariables {
return {};
}

public visitImportDeclaration(node: ts.ImportDeclaration): void {
if (node.importClause != null) {
var name = <ts.Identifier> node.importClause.name;
this.validateUsageForVariable(name.text, name.getStart());
var importClause = node.importClause;

// named imports & namespace imports handled by other walker methods
if (importClause.name != null) {
var variableIdentifier = importClause.name;
this.validateUsageForVariable(variableIdentifier.text, variableIdentifier.getStart());
}
}

super.visitImportDeclaration(node);
Expand All @@ -55,7 +62,20 @@ class NoUseBeforeDeclareWalker extends Lint.ScopeAwareRuleWalker<{}> {
super.visitImportEqualsDeclaration(node);
}

public visitNamedImports(node: ts.NamedImports): void {
node.elements.forEach((namedImport: ts.ImportSpecifier) => {
this.validateUsageForVariable(namedImport.name.text, namedImport.name.getStart());
});
super.visitNamedImports(node);
}

public visitNamespaceImport(node: ts.NamespaceImport): void {
this.validateUsageForVariable(node.name.text, node.name.getStart());
super.visitNamespaceImport(node);
}

public visitVariableDeclaration(node: ts.VariableDeclaration): void {
var isSingleVariable = node.name.kind === ts.SyntaxKind.Identifier;
var nameNode = <ts.Identifier> node.name;
var variableName = nameNode.text;
var currentScope = this.getCurrentScope();
Expand All @@ -77,8 +97,7 @@ class NoUseBeforeDeclareWalker extends Lint.ScopeAwareRuleWalker<{}> {
var referencePosition = highlightSpan.textSpan.start;
if (referencePosition < position) {
var failureString = Rule.FAILURE_STRING_PREFIX + name + Rule.FAILURE_STRING_POSTFIX;
var failure = this.createFailure(referencePosition, name.length, failureString);
this.addFailure(failure);
this.addFailure(this.createFailure(referencePosition, name.length, failureString));
}
});
});
Expand Down
18 changes: 15 additions & 3 deletions test/files/rules/nousebeforedeclare.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
$.x = 3;
$.x = 3; // failure on '$'
import $ = require("$");
var vara = varb, varb;
var vara = varb, varb; // failure on 'varb'

class Test {
constructor() {
Expand All @@ -10,7 +10,7 @@ class Test {
private a: number;
}

var i = j;
var i = j; // failure on 'j'

class ClassA {
prop: number;
Expand All @@ -30,3 +30,15 @@ if (something) {
} else {
var defined;
}

function testUndeclaredImports() {
console.log(foo1); // failure on 'foo1'
console.log(foo2); // failure on 'foo2'
console.log(foo3); // failure on 'foo3'
map([], (x) => x); // failure on 'map'
}

import { default as foo1 } from "lib";
import foo2 from "lib";
import _, { map, foldl } from "underscore";
import * as foo3 from "lib";
41 changes: 27 additions & 14 deletions test/rules/noUseBeforeDeclareRuleTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,48 @@
*/

describe("<no-use-before-declare>", () => {
var Rule: any;

before(() => {
Rule = Lint.Test.getRule("no-use-before-declare");
});

it("restricts usage before declaration", () => {
var fileName = "rules/nousebeforedeclare.test.ts";
var Rule = Lint.Test.getRule("no-use-before-declare");

var actualFailures = Lint.Test.applyRuleOnFile(fileName, Rule);
assert.equal(actualFailures.length, 3);

assert.equal(actualFailures.length, 7);
});

it("restricts usage of imports before declaration", () => {
var fileName = "rules/nousebeforedeclare.test.ts";
var Rule = Lint.Test.getRule("no-use-before-declare");
var failureString = Rule.FAILURE_STRING_PREFIX + "$" + Rule.FAILURE_STRING_POSTFIX;
var failure = Lint.Test.createFailuresOnFile(fileName, failureString)([1, 1], [1, 2]);

var actualFailures = Lint.Test.applyRuleOnFile(fileName, Rule);

Lint.Test.assertContainsFailure(actualFailures, failure);
var failure1 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("$"))([1, 1], [1, 2]);
var failure2 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("foo1"))([35, 17], [35, 21]);
var failure3 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("foo2"))([36, 17], [36, 21]);
var failure4 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("foo3"))([37, 17], [37, 21]);
var failure5 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("map"))([38, 5], [38, 8]);

Lint.Test.assertContainsFailure(actualFailures, failure1);
Lint.Test.assertContainsFailure(actualFailures, failure2);
Lint.Test.assertContainsFailure(actualFailures, failure3);
Lint.Test.assertContainsFailure(actualFailures, failure4);
Lint.Test.assertContainsFailure(actualFailures, failure5);
});

it("restricts usage of variables before declaration", () => {
var fileName = "rules/nousebeforedeclare.test.ts";
var Rule = Lint.Test.getRule("no-use-before-declare");
var failureString1 = Rule.FAILURE_STRING_PREFIX + "varb" + Rule.FAILURE_STRING_POSTFIX;
var failureString2 = Rule.FAILURE_STRING_PREFIX + "j" + Rule.FAILURE_STRING_POSTFIX;
var failure1 = Lint.Test.createFailuresOnFile(fileName, failureString1)([3, 12], [3, 16]);
var failure2 = Lint.Test.createFailuresOnFile(fileName, failureString2)([13, 9], [13, 10]);

var actualFailures = Lint.Test.applyRuleOnFile(fileName, Rule);

var failure1 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("varb"))([3, 12], [3, 16]);
var failure2 = Lint.Test.createFailuresOnFile(fileName, makeFailureString("j"))([13, 9], [13, 10]);

Lint.Test.assertContainsFailure(actualFailures, failure1);
Lint.Test.assertContainsFailure(actualFailures, failure2);
});

function makeFailureString(varName: string) {
return `${Rule.FAILURE_STRING_PREFIX}${varName}${Rule.FAILURE_STRING_POSTFIX}`;
}
});

0 comments on commit e4bfe6f

Please sign in to comment.