Import completions for require calls

This commit is contained in:
Richard Knoll
2016-06-27 13:06:40 -07:00
parent ccf27d1339
commit dbdd9893f5
10 changed files with 225 additions and 152 deletions

View File

@@ -2775,13 +2775,17 @@ namespace ts {
function isNameOfExternalModuleImportOrDeclaration(node: Node): boolean {
if (node.kind === SyntaxKind.StringLiteral) {
return isNameOfModuleDeclaration(node) ||
(isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node);
return isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node);
}
return false;
}
function isExpressionOfExternalModuleImportEqualsDeclaration(node: Node) {
return isExternalModuleImportEqualsDeclaration(node.parent.parent) &&
getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node;
}
/** Returns true if the position is within a comment */
function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean {
// The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment
@@ -4256,15 +4260,25 @@ namespace ts {
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
if (argumentInfo) {
// Get string literal completions from specialized signatures of the target
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo);
// Try to get string literal completions from specialized signatures of the target
const callExpressionCompletionEntries = getStringLiteralCompletionEntriesFromCallExpression(argumentInfo);
if (callExpressionCompletionEntries) {
return callExpressionCompletionEntries;
}
else if (isRequireCall(node.parent, false)) {
// If that failed but this call mataches the signature of a require call, treat the literal as an external module name
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node);
}
else {
return undefined;
}
}
else if (isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) {
// Get all names of properties on the expression
return getStringLiteralCompletionEntriesFromElementAccess(node.parent);
}
else if (node.parent.kind === SyntaxKind.ImportDeclaration) {
// Get all known module names
else if (node.parent.kind === SyntaxKind.ImportDeclaration || isExpressionOfExternalModuleImportEqualsDeclaration(node)) {
// Get all known external module names or complete a path to a module
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node);
}
else {

View File

@@ -1,13 +1,17 @@
/// <reference path='fourslash.ts' />
// @Filename: tests/test0.ts
//// import * as foo from "f/*0*/
//// import * as foo1 from "f/*import_as0*/
//// import * as foo2 from "fake-module//*import_as1*/
//// import * as foo3 from "fake-module/*import_as2*/
// @Filename: tests/test1.ts
//// import * as foo from "fake-module//*1*/
//// import foo4 = require("f/*import_equals0*/
//// import foo5 = require("fake-module//*import_equals1*/
//// import foo6 = require("fake-module/*import_equals2*/
// @Filename: tests/test2.ts
//// import * as foo from "fake-module/*2*/
//// var foo7 = require("f/*require0*/
//// var foo8 = require("fake-module//*require1*/
//// var foo9 = require("fake-module/*require2*/
// @Filename: package.json
//// { "dependencies": { "fake-module": "latest" }, "devDependencies": { "fake-module-dev": "latest" } }
@@ -35,19 +39,23 @@
// @Filename: node_modules/unlisted-module/index.ts
//// /*unlisted-module*/
goTo.marker("0");
verify.completionListContains("fake-module");
verify.completionListContains("fake-module-dev");
verify.not.completionListItemsCountIsGreaterThan(2);
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("1");
verify.completionListContains("index");
verify.completionListContains("ts");
verify.completionListContains("dts");
verify.completionListContains("tsx");
verify.not.completionListItemsCountIsGreaterThan(4);
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("fake-module");
verify.completionListContains("fake-module-dev");
verify.not.completionListItemsCountIsGreaterThan(2);
goTo.marker("2");
verify.completionListContains("fake-module");
verify.completionListContains("fake-module-dev");
verify.not.completionListItemsCountIsGreaterThan(2);
goTo.marker(kind + "1");
verify.completionListContains("index");
verify.completionListContains("ts");
verify.completionListContains("dts");
verify.completionListContains("tsx");
verify.not.completionListItemsCountIsGreaterThan(4);
goTo.marker(kind + "2");
verify.completionListContains("fake-module");
verify.completionListContains("fake-module-dev");
verify.not.completionListItemsCountIsGreaterThan(2);
}

View File

@@ -1,7 +1,9 @@
/// <reference path='fourslash.ts' />
// @Filename: tests/test0.ts
//// import * as foo from "fake-module//*0*/
//// import * as foo1 from "fake-module//*import_as0*/
//// import foo2 = require("fake-module//*import_equals0*/
//// var foo3 = require("fake-module//*require0*/
// @Filename: package.json
//// { "dependencies": { "fake-module": "latest" }, "devDependencies": { "fake-module-dev": "latest" } }
@@ -26,7 +28,11 @@
// @Filename: node_modules/@types/unlisted-module/index.d.ts
//// /*unlisted-types*/
goTo.marker("0");
verify.completionListContains("repeated");
verify.completionListContains("other");
verify.not.completionListItemsCountIsGreaterThan(2);
const kinds = ["import_as", "import_equals", "require"];
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("repeated");
verify.completionListContains("other");
verify.not.completionListItemsCountIsGreaterThan(2);
}

View File

@@ -2,7 +2,9 @@
// @allowJs: true
// @Filename: tests/test0.ts
//// import * as foo from "fake-module//*0*/
//// import * as foo1 from "fake-module//*import_as0*/
//// import foo2 = require("fake-module//*import_equals0*/
//// var foo3 = require("fake-module//*require0*/
// @Filename: package.json
//// { "dependencies": { "fake-module": "latest" } }
@@ -22,9 +24,12 @@
// @Filename: node_modules/fake-module/repeated.jsx
//// /*repeatedjsx*/
goTo.marker("0");
const kinds = ["import_as", "import_equals", "require"];
verify.completionListContains("ts");
verify.completionListContains("tsx");
verify.completionListContains("dts");
verify.not.completionListItemsCountIsGreaterThan(3);
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("ts");
verify.completionListContains("tsx");
verify.completionListContains("dts");
verify.not.completionListItemsCountIsGreaterThan(3);
}

View File

@@ -1,13 +1,17 @@
/// <reference path='fourslash.ts' />
// @Filename: dir1/dir2/dir3/dir4/test0.ts
//// import * as foo from "f/*0*/
//// import * as foo1 from "f/*import_as0*/
//// import * as foo2 from "a/*import_as1*/
//// import * as foo3 from "fake-module/*import_as2*/
// @Filename: dir1/dir2/dir3/dir4/test1.ts
//// import * as foo from "a/*1*/
//// import foo4 = require("f/*import_equals0*/
//// import foo5 = require("a/*import_equals1*/
//// import foo6 = require("fake-module/*import_equals2*/
// @Filename: dir1/dir2/dir3/dir4/test2.ts
//// import * as foo from "fake-module/*2*/
//// var foo7 = require("f/*require0*/
//// var foo8 = require("a/*require1*/
//// var foo9 = require("fake-module/*require2*/
// @Filename: package.json
//// { "dependencies": { "fake-module": "latest" } }
@@ -24,22 +28,25 @@
// @Filename: dir1/dir2/dir3/node_modules/fake-module3/ts.ts
//// /*module3*/
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("0");
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("fake-module/");
verify.completionListContains("fake-module2/");
verify.completionListContains("fake-module3/");
verify.not.completionListItemsCountIsGreaterThan(3);
verify.completionListContains("fake-module/");
verify.completionListContains("fake-module2/");
verify.completionListContains("fake-module3/");
verify.not.completionListItemsCountIsGreaterThan(3);
goTo.marker("1");
goTo.marker(kind + "1");
verify.completionListContains("ambient-module-test");
verify.not.completionListItemsCountIsGreaterThan(1);
verify.completionListContains("ambient-module-test");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker("2");
goTo.marker(kind + "2");
verify.completionListContains("fake-module/");
verify.completionListContains("fake-module2/");
verify.completionListContains("fake-module3/");
verify.not.completionListItemsCountIsGreaterThan(3);
verify.completionListContains("fake-module/");
verify.completionListContains("fake-module2/");
verify.completionListContains("fake-module3/");
verify.not.completionListItemsCountIsGreaterThan(3);
}

View File

@@ -1,10 +1,14 @@
/// <reference path='fourslash.ts' />
// @Filename: test0.ts
//// import * as foo from "/*0*/
//// import * as foo1 from "/*import_as0*/
//// import * as foo2 from "a/*import_as1*/
// @Filename: test1.ts
//// import * as foo from "a/*1*/
//// import foo3 = require("/*import_equals0*/
//// import foo4 = require("a/*import_equals1*/
//// var foo5 = require("/*require0*/
//// var foo6 = require("a/*require1*/
// @Filename: ambientModules.d.ts
//// declare module "ambientModule" {}
@@ -13,16 +17,19 @@
// @Filename: ambientModules2.d.ts
//// declare module "otherOtherAmbientModule" {}
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("0");
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("ambientModule");
verify.completionListContains("otherAmbientModule");
verify.completionListContains("otherOtherAmbientModule");
verify.not.completionListItemsCountIsGreaterThan(3);
verify.completionListContains("ambientModule");
verify.completionListContains("otherAmbientModule");
verify.completionListContains("otherOtherAmbientModule");
verify.not.completionListItemsCountIsGreaterThan(3);
goTo.marker("1");
goTo.marker(kind + "1");
verify.completionListContains("ambientModule");
verify.not.completionListItemsCountIsGreaterThan(1);
verify.completionListContains("ambientModule");
verify.not.completionListItemsCountIsGreaterThan(1);
}

View File

@@ -1,7 +1,9 @@
/// <reference path='fourslash.ts' />
// @Filename: tests/test0.ts
//// import * as foo from "module-/*0*/
//// import * as foo1 from "module-/*import_as0*/
//// import foo2 = require("module-/*import_equals0*/
//// var foo3 = require("module-/*require0*/
// @Filename: package.json
//// { "dependencies": {
@@ -45,13 +47,16 @@
// @Filename: node_modules/module-typings/types.d.ts
//// /*module-typings*/
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("0");
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("module-no-main/");
verify.completionListContains("module-no-main-index-d-ts/");
verify.completionListContains("module-index-ts");
verify.completionListContains("module-index-d-ts-explicit-main");
verify.completionListContains("module-index-d-ts-default-main");
verify.completionListContains("module-typings");
verify.not.completionListItemsCountIsGreaterThan(6);
verify.completionListContains("module-no-main/");
verify.completionListContains("module-no-main-index-d-ts/");
verify.completionListContains("module-index-ts");
verify.completionListContains("module-index-d-ts-explicit-main");
verify.completionListContains("module-index-d-ts-default-main");
verify.completionListContains("module-typings");
verify.not.completionListItemsCountIsGreaterThan(6);
}

View File

@@ -1,22 +1,30 @@
/// <reference path='fourslash.ts' />
// @Filename: test0.ts
//// import * as foo from "./*0*/
//// import * as foo1 from "./*import_as0*/
//// import * as foo2 from ".//*import_as1*/
//// import * as foo3 from "./f/*import_as2*/
//// import * as foo4 from "./folder//*import_as3*/
//// import * as foo5 from "./folder/h/*import_as4*/
// @Filename: test1.ts
//// import * as foo from ".//*1*/
//// import foo6 = require("./*import_equals0*/
//// import foo7 = require(".//*import_equals1*/
//// import foo8 = require("./f/*import_equals2*/
//// import foo9 = require("./folder//*import_equals3*/
//// import foo10 = require("./folder/h/*import_equals4*/
// @Filename: test2.ts
//// import * as foo from "./f/*2*/
// @Filename: test3.ts
//// import * as foo from "./folder//*3*/
// @Filename: test4.ts
//// import * as foo from "./folder/h/*4*/
//// var foo11 = require("./*require0*/
//// var foo12 = require(".//*require1*/
//// var foo13 = require("./f/*require2*/
//// var foo14 = require("./folder//*require3*/
//// var foo15 = require("./folder/h/*require4*/
// @Filename: parentTest/sub/test5.ts
//// import * as foo from "../g/*5*/
//// import * as foo16 from "../g/*import_as5*/
//// import foo17 = require("../g/*import_equals5*/
//// var foo18 = require("../g/*require5*/
// @Filename: f1.ts
//// /*f1*/
@@ -40,38 +48,37 @@
//// /*parentf1*/
// @Filename: parentTest/g1.ts
//// /*parentg1*/
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("0");
verify.completionListIsEmpty();
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListIsEmpty();
goTo.marker("1");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("e1");
verify.completionListContains("test0");
verify.completionListContains("test1");
verify.completionListContains("test2");
verify.completionListContains("test3");
verify.completionListContains("test4");
verify.completionListContains("folder/");
verify.completionListContains("parentTest/");
verify.not.completionListItemsCountIsGreaterThan(10);
goTo.marker(kind + "1");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("e1");
verify.completionListContains("test0");
verify.completionListContains("folder/");
verify.completionListContains("parentTest/");
verify.not.completionListItemsCountIsGreaterThan(6);
goTo.marker("2");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("folder/");
verify.not.completionListItemsCountIsGreaterThan(3);
goTo.marker(kind + "2");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("folder/");
verify.not.completionListItemsCountIsGreaterThan(3);
goTo.marker("3");
verify.completionListContains("f1");
verify.completionListContains("h1");
verify.not.completionListItemsCountIsGreaterThan(2);
goTo.marker(kind + "3");
verify.completionListContains("f1");
verify.completionListContains("h1");
verify.not.completionListItemsCountIsGreaterThan(2);
goTo.marker("4");
verify.completionListContains("h1");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker(kind + "4");
verify.completionListContains("h1");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker("5");
verify.completionListContains("g1");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker(kind + "5");
verify.completionListContains("g1");
verify.not.completionListItemsCountIsGreaterThan(1);
}

View File

@@ -2,10 +2,14 @@
// @allowJs: true
// @Filename: test0.ts
//// import * as foo from ".//*0*/
//// import * as foo1 from ".//*import_as0*/
//// import * as foo2 from "./f/*import_as1*/
// @Filename: test1.ts
//// import * as foo from "./f/*1*/
//// import foo3 = require(".//*import_equals0*/
//// import foo4 = require("./f/*import_equals1*/
//// var foo5 = require(".//*require0*/
//// var foo6 = require("./f/*require1*/
// @Filename: f1.ts
//// /f1*/
@@ -23,21 +27,23 @@
//// /*e1*/
// @Filename: e2.js
//// /*e2*/
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("0");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("f3");
verify.completionListContains("f4");
verify.completionListContains("e1");
verify.completionListContains("e2");
verify.completionListContains("test0");
verify.completionListContains("test1");
verify.not.completionListItemsCountIsGreaterThan(8);
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("f3");
verify.completionListContains("f4");
verify.completionListContains("e1");
verify.completionListContains("e2");
verify.completionListContains("test0");
verify.not.completionListItemsCountIsGreaterThan(7);
goTo.marker("1");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("f3");
verify.completionListContains("f4");
verify.not.completionListItemsCountIsGreaterThan(4);
goTo.marker(kind + "1");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("f3");
verify.completionListContains("f4");
verify.not.completionListItemsCountIsGreaterThan(4);
}

View File

@@ -1,13 +1,17 @@
/// <reference path='fourslash.ts' />
// @Filename: tests/test0.ts
//// import * as foo from "c:/tests/cases/f/*0*/
//// import * as foo1 from "c:/tests/cases/f/*import_as0*/
//// import * as foo2 from "c:/tests/cases/fourslash/*import_as1*/
//// import * as foo3 from "c:/tests/cases/fourslash//*import_as2*/
// @Filename: tests/test1.ts
//// import * as foo from "c:/tests/cases/fourslash/*1*/
//// import foo4 = require("c:/tests/cases/f/*import_equals0*/
//// import foo5 = require("c:/tests/cases/fourslash/*import_equals1*/
//// import foo6 = require("c:/tests/cases/fourslash//*import_equals2*/
// @Filename: tests/test2.ts
//// import * as foo from "c:/tests/cases/fourslash//*2*/
//// var foo7 = require("c:/tests/cases/f/*require0*/
//// var foo8 = require("c:/tests/cases/fourslash/*require1*/
//// var foo9 = require("c:/tests/cases/fourslash//*require2*/
// @Filename: f1.ts
//// /*f1*/
@@ -24,18 +28,22 @@
// @Filename: e2.js
//// /*e2*/
goTo.marker("0");
verify.completionListContains("fourslash/");
verify.not.completionListItemsCountIsGreaterThan(1);
const kinds = ["import_as", "import_equals", "require"];
goTo.marker("1");
verify.completionListContains("fourslash/");
verify.not.completionListItemsCountIsGreaterThan(1);
for (const kind of kinds) {
goTo.marker(kind + "0");
verify.completionListContains("fourslash/");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker("2");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("e1");
verify.completionListContains("folder/");
verify.completionListContains("tests/");
verify.not.completionListItemsCountIsGreaterThan(5);
goTo.marker(kind + "1");
verify.completionListContains("fourslash/");
verify.not.completionListItemsCountIsGreaterThan(1);
goTo.marker(kind + "2");
verify.completionListContains("f1");
verify.completionListContains("f2");
verify.completionListContains("e1");
verify.completionListContains("folder/");
verify.completionListContains("tests/");
verify.not.completionListItemsCountIsGreaterThan(5);
}