From a4f6edab857d386a1f1469b296755b2e389253d4 Mon Sep 17 00:00:00 2001 From: Henry Zhu Date: Mon, 1 Jun 2015 21:16:02 -0400 Subject: [PATCH] Merge pull request babel/babel-eslint#109 from hzoo/i-108 visit flow types - fixes babel/babel-eslint#108 --- .../babel-eslint-parser/acorn-to-esprima.js | 37 +- eslint/babel-eslint-parser/index.js | 196 ++++- eslint/babel-eslint-parser/package.json | 3 +- .../test/non-regression.js | 763 +++++++++++++++++- 4 files changed, 963 insertions(+), 36 deletions(-) diff --git a/eslint/babel-eslint-parser/acorn-to-esprima.js b/eslint/babel-eslint-parser/acorn-to-esprima.js index d8ac33df92..324758fd1e 100644 --- a/eslint/babel-eslint-parser/acorn-to-esprima.js +++ b/eslint/babel-eslint-parser/acorn-to-esprima.js @@ -117,7 +117,7 @@ function convertTemplateType(tokens) { // create Template token function replaceWithTemplateType(start, end) { var templateToken = { - type: 'Template', + type: "Template", value: createTemplateValue(start, end), range: [tokens[start].start, tokens[end].end], loc: { @@ -183,18 +183,37 @@ var astTransformVisitor = { delete node.argument; } - if (this.isTypeCastExpression()) { - return node.expression; - } - - if (this.isFlow()) { - return this.remove(); - } - if (this.isRestElement()) { return node.argument; } + // prevent "no-undef" + // for "Component" in: "let x: React.Component" + if (this.isQualifiedTypeIdentifier()) { + delete node.id; + } + // for "b" in: "var a: { b: Foo }" + if (this.isObjectTypeProperty()) { + delete node.key; + } + // for "indexer" in: "var a: {[indexer: string]: number}" + if (this.isObjectTypeIndexer()) { + delete node.id; + } + // for "param" in: "var a: { func(param: Foo): Bar };" + if (this.isFunctionTypeParam()) { + delete node.name; + } + + // flow + + if (this.isDeclareModule() || + this.isDeclareClass() || + this.isDeclareFunction() || + this.isDeclareVariable()) { + return this.remove(); + } + // modules if (this.isImportDeclaration()) { diff --git a/eslint/babel-eslint-parser/index.js b/eslint/babel-eslint-parser/index.js index 613d1fc72d..0977fd421a 100644 --- a/eslint/babel-eslint-parser/index.js +++ b/eslint/babel-eslint-parser/index.js @@ -1,6 +1,7 @@ var acornToEsprima = require("./acorn-to-esprima"); var traverse = require("babel-core").traverse; var assign = require("lodash.assign"); +var pick = require("lodash.pick"); var Module = require("module"); var parse = require("babel-core").parse; var path = require("path"); @@ -46,12 +47,7 @@ function monkeypatch() { escope.analyze = function (ast, opts) { opts.ecmaVersion = 6; opts.sourceType = "module"; - // Don't visit TypeAlias when analyzing scope, but retain them for other - // eslint rules. - var TypeAliasKeys = estraverse.VisitorKeys.TypeAlias; - estraverse.VisitorKeys.TypeAlias = []; var results = analyze.call(this, ast, opts); - estraverse.VisitorKeys.TypeAlias = TypeAliasKeys; return results; }; @@ -62,8 +58,18 @@ function monkeypatch() { } catch (err) { throw new ReferenceError("couldn't resolve escope/referencer"); } + var referencerMod = createModule(referencerLoc); var referencer = require(referencerLoc); + // reference Definition + var definitionLoc; + try { + var definitionLoc = Module._resolveFilename("./definition", referencerMod); + } catch (err) { + throw new ReferenceError("couldn't resolve escope/definition"); + } + var Definition = require(definitionLoc).Definition; + // if there are decotators, then visit each function visitDecorators(node) { if (!node.decorators) { @@ -76,18 +82,182 @@ function monkeypatch() { } } - // monkeypatch referencer methods to visit decorators - var visitClass = referencer.prototype.visitClass; - referencer.prototype.visitClass = function (node) { - // visit decorators that are in: Class Declaration - visitDecorators.call(this, node); - visitClass.call(this, node); + // iterate through part of t.VISITOR_KEYS + var visitorKeysMap = pick(t.VISITOR_KEYS, function(k) { + return t.FLIPPED_ALIAS_KEYS.Flow.concat([ + "ArrayPattern", + "ClassDeclaration", + "ClassExpression", + "FunctionDeclaration", + "FunctionExpression", + "Identifier", + "ObjectPattern", + "RestElement" + ]).indexOf(k) === -1; + }); + + var propertyTypes = { + // loops + callProperties: { type: "loop", values: ["value"] }, + indexers: { type: "loop", values: ["key", "value"] }, + properties: { type: "loop", values: ["value"] }, + types: { type: "loop" }, + params: { type: "loop" }, + // single property + argument: { type: "single" }, + elementType: { type: "single" }, + qualification: { type: "single" }, + rest: { type: "single" }, + returnType: { type: "single" }, + // others + typeAnnotation: { type: "typeAnnotation" }, + typeParameters: { type: "typeParameters" }, + id: { type: "id" } + }; + + function visitTypeAnnotation(node) { + // get property to check (params, id, etc...) + var visitorValues = visitorKeysMap[node.type]; + if (!visitorValues) { + return; + } + + // can have multiple properties + for (var i = 0; i < visitorValues.length; i++) { + var visitorValue = visitorValues[i]; + var propertyType = propertyTypes[visitorValue]; + var nodeProperty = node[visitorValue]; + // check if property or type is defined + if (propertyType == null || nodeProperty == null) { + continue; + } + if (propertyType.type === "loop") { + for (var j = 0; j < nodeProperty.length; j++) { + if (Array.isArray(propertyType.values)) { + for (var k = 0; k < propertyType.values.length; k++) { + checkIdentifierOrVisit.call(this, nodeProperty[j][propertyType.values[k]]); + } + } else { + checkIdentifierOrVisit.call(this, nodeProperty[j]); + } + } + } else if (propertyType.type === "single") { + checkIdentifierOrVisit.call(this, nodeProperty); + } else if (propertyType.type === "typeAnnotation") { + visitTypeAnnotation.call(this, node.typeAnnotation); + } else if (propertyType.type === "typeParameters") { + for (var j = 0; j < node.typeParameters.params.length; j++) { + checkIdentifierOrVisit.call(this, node.typeParameters.params[j]); + } + } else if (propertyType.type === "id") { + if (node.id.type === "Identifier") { + checkIdentifierOrVisit.call(this, node.id); + } else { + visitTypeAnnotation.call(this, node.id); + } + } + } } + + function checkIdentifierOrVisit(node) { + if (node.typeAnnotation) { + visitTypeAnnotation.call(this, node.typeAnnotation); + } else if (node.type === "Identifier") { + this.visit(node); + } else { + visitTypeAnnotation.call(this, node); + } + } + + // visit decorators that are in: ClassDeclaration / ClassExpression + var visitClass = referencer.prototype.visitClass; + referencer.prototype.visitClass = function(node) { + visitDecorators.call(this, node); + // visit class + if (node.id) { + this.visit(node.id); + } + // visit flow type: ClassImplements + if (node.implements) { + for (var i = 0; i < node.implements.length; i++) { + checkIdentifierOrVisit.call(this, node.implements[i]); + } + } + if (node.typeParameters) { + for (var i = 0; i < node.typeParameters.params.length; i++) { + checkIdentifierOrVisit.call(this, node.typeParameters.params[i]); + } + } + if (node.superTypeParameters) { + for (var i = 0; i < node.superTypeParameters.params.length; i++) { + checkIdentifierOrVisit.call(this, node.superTypeParameters.params[i]); + } + } + visitClass.call(this, node); + }; + // visit decorators that are in: Property / MethodDefinition var visitProperty = referencer.prototype.visitProperty; - referencer.prototype.visitProperty = function (node) { - // visit decorators that are in: Visit Property / MethodDefinition + referencer.prototype.visitProperty = function(node) { + if (node.value.type === 'TypeCastExpression') { + visitTypeAnnotation.call(this, node.value); + } visitDecorators.call(this, node); visitProperty.call(this, node); + }; + + // visit flow type in FunctionDeclaration, FunctionExpression, ArrowFunctionExpression + var visitFunction = referencer.prototype.visitFunction; + referencer.prototype.visitFunction = function(node) { + if (node.returnType) { + checkIdentifierOrVisit.call(this, node.returnType); + } + // only visit if function parameters have types + if (node.params) { + for (var i = 0; i < node.params.length; i++) { + if (node.params[i].typeAnnotation) { + checkIdentifierOrVisit.call(this, node.params[i]); + } + } + } + if (node.typeParameters) { + for (var i = 0; i < node.typeParameters.params.length; i++) { + checkIdentifierOrVisit.call(this, node.typeParameters.params[i]); + } + } + visitFunction.call(this, node); + }; + + // visit flow type in VariableDeclaration + var variableDeclaration = referencer.prototype.VariableDeclaration; + referencer.prototype.VariableDeclaration = function(node) { + if (node.declarations) { + for (var i = 0; i < node.declarations.length; i++) { + checkIdentifierOrVisit.call(this, node.declarations[i].id); + } + } + variableDeclaration.call(this, node); + }; + + referencer.prototype.TypeAlias = function(node) { + this.currentScope().__define( + node.id, + new Definition( + "Variable", + node.id, + node, + null, + null, + null + ) + ); + if (node.right) { + visitTypeAnnotation.call(this, node.right); + } + if (node.typeParameters) { + for (var i = 0; i < node.typeParameters.params.length; i++) { + checkIdentifierOrVisit.call(this, node.typeParameters.params[i]); + } + } } } diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index 8aa2a8e07c..f1b3880106 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -9,7 +9,8 @@ }, "dependencies": { "babel-core": "^5.1.8", - "lodash.assign": "^3.0.0" + "lodash.assign": "^3.0.0", + "lodash.pick": "^3.1.0" }, "scripts": { "test": "mocha" diff --git a/eslint/babel-eslint-parser/test/non-regression.js b/eslint/babel-eslint-parser/test/non-regression.js index 57c80ad953..9b0b783d33 100644 --- a/eslint/babel-eslint-parser/test/non-regression.js +++ b/eslint/babel-eslint-parser/test/non-regression.js @@ -124,20 +124,757 @@ describe("verify", function () { ); }); - it("flow type", function () { - verifyAndAssertMessages( - "type SomeNewType = any;", - {}, - [] - ); - }); + describe("flow", function () { + it("check regular function", function () { + verifyAndAssertMessages([ + "function a(b, c) { b += 1; c += 1; } a;", + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); - it("type cast expression #102", function () { - verifyAndAssertMessages( - "for (let a of (a: Array)) {}", - {}, - [] - ); + it("type alias", function () { + verifyAndAssertMessages( + "type SomeNewType = any;", + { "no-undef": 1 }, + [] + ); + }); + + it("type cast expression #102", function () { + verifyAndAssertMessages( + "for (let a of (a: Array)) {}", + {}, + [] + ); + }); + + it("multiple nullable type annotations and return #108", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "function log(foo: ?Foo, foo2: ?Foo2): ?Foo3 {", + "console.log(foo, foo2);", + "}", + "log(1, 2);" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("type parameters", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "function log() {}", + "log();" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("nested type annotations", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "function foo(callback: () => Foo) {", + "return callback();", + "}", + "foo();" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("type in var declaration", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "var x: Foo = 1;", + "x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("object type annotation", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "var a: {numVal: Foo};", + "a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("object property types", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var a = {", + "circle: (null : ?{ setNativeProps(props: Foo): Foo2 })", + "};", + "a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("namespaced types", function () { + verifyAndAssertMessages([ + "var React = require('react-native');", + "var b = {", + "openExternalExample: (null: ?React.Component)", + "};", + "var c = {", + "render(): React.Component {}", + "};", + "b;", + "c;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("ArrayTypeAnnotation", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "var x: Foo[]; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("ClassImplements", function () { + verifyAndAssertMessages([ + "import type Foo from 'foo';", + "import type Bar from 'foo';", + "class Foo implements Bar {}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("type alias creates declaration + usage", function () { + verifyAndAssertMessages([ + "type Foo = any;", + "var x : Foo = 1; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("type alias with type parameters", function () { + verifyAndAssertMessages([ + "import type Bar from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "type Foo = Bar", + "var x : Foo = 1; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("export type alias", function () { + verifyAndAssertMessages([ + "import type Foo2 from 'foo';", + "export type Foo = Foo2;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("1", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "export default function(a: Foo, b: ?Foo2, c){ a; b; c; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("2", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "export default function(a: () => Foo){ a; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("3", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "export default function(a: (_:Foo) => Foo2){ a; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("4", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "export default function(a: (_1:Foo, _2:Foo2) => Foo3){ a; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("5", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "export default function(a: (_1:Foo, ...foo:Array) => number){ a; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("6", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "export default function(): Foo {}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("7", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "export default function():() => Foo {}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("8", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "export default function():(_?:Foo) => Foo2{}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("9", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "export default function () {}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }) + + it("10", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var a=function() {}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("11", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a={*id(x: Foo2): Foo3 { x; }}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("12", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a={async id(x: Foo2): Foo3 { x; }}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("13", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a={123(x: Foo2): Foo3 { x; }}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("14", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "class Bar {set fooProp(value:Foo):Foo2{ value; }}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("15", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "class Foo {get fooProp():Foo{}}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("16", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var numVal:Foo; numVal;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("17", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: {numVal: Foo;}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("18", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a: ?{numVal: Foo; [indexer: Foo2]: Foo3}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("19", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var a: {numVal: Foo; subObj?: ?{strVal: Foo2}}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("20", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "import type Foo4 from 'foo';", + "var a: { [a: Foo]: Foo2; [b: Foo3]: Foo4; }; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("21", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a: {add(x:Foo, ...y:Array): Foo3}; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("22", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a: { id(x: Foo2): Foo3; }; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("23", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a:Array = [1, 2, 3]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("24", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import Baz from 'foo';", + "class Bar extends Baz { };" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("25", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "class Bar { bar():Foo3 { return 42; }}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("26", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "class Bar { static prop1:Foo; prop2:Foo2; }" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("27", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var x : Foo | Foo2 = 4; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("28", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var x : () => Foo | () => Foo2; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("29", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var x: typeof Foo | number = Foo2; x;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("30", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + 'var {x}: {x: Foo; } = { x: "hello" }; x;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("31", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + 'var [x]: Array = [ "hello" ]; x;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("32", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "export default function({x}: { x: Foo; }) {}" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("33", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "function foo([x]: Array) { x; } foo();" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("34", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var a: Map >; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("35", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: ?Promise[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("36", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "var a:(...rest:Array) => Foo2; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("37", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "import type Foo4 from 'foo';", + "var a: (x: Foo2, ...y:Foo3[]) => Foo4; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("38", function () { + verifyAndAssertMessages( + [ + 'import type {foo, bar} from "baz";', + 'foo; bar;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("39", function () { + verifyAndAssertMessages( + [ + 'import type {foo as bar} from "baz";', + 'bar;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("40", function () { + verifyAndAssertMessages( + [ + 'import type from "foo";', + 'type;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("41", function () { + verifyAndAssertMessages( + [ + 'import type, {foo} from "bar";', + 'type; foo;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("42", function () { + verifyAndAssertMessages( + [ + 'import type * as namespace from "bar";', + 'namespace;' + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("43", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: Foo[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("44", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: ?Foo[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("45", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: (?Foo)[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("46", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: () => Foo[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("47", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: (() => Foo)[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("48", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "var a: typeof Foo[]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); + + it("49", function () { + verifyAndAssertMessages( + [ + "import type Foo from 'foo';", + "import type Foo2 from 'foo';", + "import type Foo3 from 'foo';", + "var a : [Foo, Foo2,] = [123, 'duck',]; a;" + ].join("\n"), + { "no-unused-vars": 1, "no-undef": 1 }, + [] + ); + }); }); it("class usage", function () {