No more filtering results

This commit is contained in:
Richard Knoll
2016-08-02 15:55:30 -07:00
parent 35cd480a9c
commit a5d73bfc24
7 changed files with 127 additions and 197 deletions

View File

@@ -2069,7 +2069,7 @@ namespace ts {
* for completions.
* For example, this matches /// <reference path="fragment
*/
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^'"]+)$/;
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^'"]*)$/;
let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[];
@@ -4514,31 +4514,27 @@ namespace ts {
return undefined;
function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral) {
const literalValue = node.text;
let result: ImportCompletionEntry[];
const literalValue = normalizeSlashes(node.text);
// Replace the entire text of the string literal (excluding the quotes)
const span: TextSpan = getDirectoryFragmentTextSpan(literalValue, node.getStart() + 1);
const isRelativePath = startsWith(literalValue, ".");
const scriptDir = getDirectoryPath(node.getSourceFile().path);
if (isRelativePath || isRootedDiskPath(literalValue)) {
const scriptPath = node.getSourceFile().path;
const scriptDirectory = getDirectoryPath(scriptPath);
if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) {
const compilerOptions = program.getCompilerOptions();
if (compilerOptions.rootDirs) {
result = getCompletionEntriesForDirectoryFragmentWithRootDirs(
compilerOptions.rootDirs, literalValue, scriptDir, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/false, span);
return getCompletionEntriesForDirectoryFragmentWithRootDirs(
compilerOptions.rootDirs, literalValue, scriptDirectory, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/false, span, scriptPath);
}
else {
result = getCompletionEntriesForDirectoryFragment(
literalValue, scriptDir, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/false, span);
return getCompletionEntriesForDirectoryFragment(
literalValue, scriptDirectory, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/false, span, scriptPath);
}
}
else {
// Check for node modules
result = getCompletionEntriesForNonRelativeModules(literalValue, scriptDir, span);
return getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span);
}
return result;
}
/**
@@ -4562,34 +4558,45 @@ namespace ts {
return deduplicate(map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory)));
}
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan): ImportCompletionEntry[] {
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, exclude?: string): ImportCompletionEntry[] {
const basePath = program.getCompilerOptions().project || host.getCurrentDirectory();
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase);
const baseDirectories = getBaseDirectoriesFromRootDirs(
rootDirs, basePath, scriptPath, host.useCaseSensitiveFileNames && !host.useCaseSensitiveFileNames());
const result: ImportCompletionEntry[] = [];
for (const baseDirectory of baseDirectories) {
getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, result);
getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, exclude, result);
}
return result;
}
function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, result: ImportCompletionEntry[] = []): ImportCompletionEntry[] {
const toComplete = getBaseFileName(fragment);
const absolutePath = normalizeSlashes(host.resolvePath(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)));
const baseDirectory = toComplete ? getDirectoryPath(absolutePath) : absolutePath;
function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, exclude?: string, result: ImportCompletionEntry[] = []): ImportCompletionEntry[] {
fragment = getDirectoryPath(fragment);
if (!fragment) {
fragment = "./"
}
else {
fragment = ensureTrailingDirectorySeparator(fragment);
}
const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment));
const baseDirectory = host.resolvePath(getDirectoryPath(absolutePath));
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
if (directoryProbablyExists(baseDirectory, host)) {
// Enumerate the available files
const files = host.readDirectory(baseDirectory, extensions, /*exclude*/undefined, /*include*/["./*"]);
forEach(files, f => {
const fileName = includeExtensions ? getBaseFileName(f) : removeFileExtension(getBaseFileName(f));
forEach(files, filePath => {
if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) {
return false;
}
const duplicate = includeExtensions ? false : forEach(result, entry => entry.name === fileName);
const fileName = includeExtensions ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath));
const duplicate = !includeExtensions && forEach(result, entry => entry.name === fileName);
if (startsWith(fileName, toComplete) && !duplicate) {
if (!duplicate) {
result.push({
name: fileName,
kind: ScriptElementKind.directory,
@@ -4605,14 +4612,12 @@ namespace ts {
forEach(directories, d => {
const directoryName = getBaseFileName(removeTrailingDirectorySeparator(d));
if (startsWith(directoryName, toComplete)) {
result.push({
name: ensureTrailingDirectorySeparator(directoryName),
kind: ScriptElementKind.directory,
sortText: directoryName,
span
});
}
result.push({
name: ensureTrailingDirectorySeparator(directoryName),
kind: ScriptElementKind.directory,
sortText: directoryName,
span
});
});
}
}
@@ -4679,18 +4684,17 @@ namespace ts {
if (parsed) {
// The prefix has two effective parts: the directory path and the base component after the filepath that is not a
// full directory component. For example: directory/path/of/prefix/base*
const normalizedPrefix = hasTrailingDirectorySeparator(parsed.prefix) ?
ensureTrailingDirectorySeparator(normalizePath(parsed.prefix)) : normalizePath(parsed.prefix);
const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix);
const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix);
const normalizedPrefixBase = getBaseFileName(normalizedPrefix);
const fragmentHasPath = fragment.indexOf(directorySeparator) !== -1;
// Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
const expandedPrefixDir = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory;
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory;
const normalizedSuffix = normalizePath(parsed.suffix);
const baseDirectory = combinePaths(baseUrl, expandedPrefixDir);
const baseDirectory = combinePaths(baseUrl, expandedPrefixDirectory);
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
// If we have a suffix, then we need to read the directory all the way down. We could create a glob
@@ -4720,17 +4724,8 @@ namespace ts {
}
function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions): string[] {
const trailingSeperator = hasTrailingDirectorySeparator(fragment);
fragment = normalizePath(fragment);
if (trailingSeperator) {
fragment = ensureTrailingDirectorySeparator(fragment);
}
// If this is a nested module, get the module name
const firstSeparator = fragment.indexOf(directorySeparator);
const moduleNameFragment = firstSeparator !== -1 ? fragment.substr(0, firstSeparator) : fragment;
const isNestedModule = fragment !== moduleNameFragment;
// Check If this is a nested module
const isNestedModule = fragment.indexOf(directorySeparator) !== -1 ;
// Get modules that the type checker picked up
const ambientModules = ts.map(program.getTypeChecker().getAmbientModules(), sym => stripQuotes(sym.name));
@@ -4749,7 +4744,7 @@ namespace ts {
});
if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) {
forEach(enumerateNodeModulesVisibleToScript(host, scriptPath, moduleNameFragment), visibleModule => {
forEach(enumerateNodeModulesVisibleToScript(host, scriptPath), visibleModule => {
if (!isNestedModule) {
nonRelativeModules.push(visibleModule.canBeImported ? visibleModule.moduleName : ensureTrailingDirectorySeparator(visibleModule.moduleName));
}
@@ -4796,7 +4791,7 @@ namespace ts {
if (kind === "path") {
// Give completions for a relative path
const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length);
return getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/true, span);
return getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/true, span, sourceFile.path);
}
else {
// Give completions based on the typings available
@@ -4876,7 +4871,7 @@ namespace ts {
}
function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string, modulePrefix?: string) {
function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string) {
const result: VisibleModuleInfo[] = [];
findPackageJsons(scriptPath).forEach((packageJson) => {
const package = tryReadingPackageJson(packageJson);
@@ -4888,10 +4883,10 @@ namespace ts {
const foundModuleNames: string[] = [];
if (package.dependencies) {
addPotentialPackageNames(package.dependencies, modulePrefix, foundModuleNames);
addPotentialPackageNames(package.dependencies, foundModuleNames);
}
if (package.devDependencies) {
addPotentialPackageNames(package.devDependencies, modulePrefix, foundModuleNames);
addPotentialPackageNames(package.devDependencies, foundModuleNames);
}
forEach(foundModuleNames, (moduleName) => {
@@ -4916,9 +4911,10 @@ namespace ts {
}
}
function addPotentialPackageNames(dependencies: any, prefix: string, result: string[]) {
function addPotentialPackageNames(dependencies: any, result: string[]) {
for (const dep in dependencies) {
if (dependencies.hasOwnProperty(dep) && (!prefix || startsWith(dep, prefix))) {
if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types") &&
dep.charCodeAt(6) !== CharacterCodes.slash && dep.charCodeAt(6) !== CharacterCodes.backslash) {
result.push(dep);
}
}
@@ -4961,6 +4957,20 @@ namespace ts {
const offset = index !== -1 ? index + 1 : 0;
return { start: textStart + offset, length: text.length - offset }
}
// Returns true if the path is explicitly relative to the script (i.e. relative to . or ..)
function isPathRelativeToScript(path: string) {
if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) {
const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1;
const slashCharCode = path.charCodeAt(slashIndex);
return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash;
}
return false;
}
function normalizeAndPreserveTrailingSlash(path: string) {
return hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalizePath(path)) : normalizePath(path);
}
}
function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {

View File

@@ -2,16 +2,8 @@
// @Filename: dir1/dir2/dir3/dir4/test0.ts
//// import * as foo1 from "f/*import_as0*/
//// import * as foo2 from "a/*import_as1*/
//// import * as foo3 from "fake-module/*import_as2*/
//// import foo4 = require("f/*import_equals0*/
//// import foo5 = require("a/*import_equals1*/
//// import foo6 = require("fake-module/*import_equals2*/
//// var foo7 = require("f/*require0*/
//// var foo8 = require("a/*require1*/
//// var foo9 = require("fake-module/*require2*/
// @Filename: package.json
//// { "dependencies": { "fake-module": "latest" } }
@@ -21,7 +13,7 @@
// @Filename: dir1/package.json
//// { "dependencies": { "fake-module2": "latest" } }
// @Filename: dir1/node_modules/fake-module2/index.ts
//// declare module "ambient-module-test" {}
//// /*module2*/
// @Filename: dir1/dir2/dir3/package.json
//// { "dependencies": { "fake-module3": "latest" } }
@@ -37,16 +29,4 @@ for (const kind of kinds) {
verify.importModuleCompletionListContains("fake-module2");
verify.importModuleCompletionListContains("fake-module3/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(3);
goTo.marker(kind + "1");
verify.importModuleCompletionListContains("ambient-module-test");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(1);
goTo.marker(kind + "2");
verify.importModuleCompletionListContains("fake-module/");
verify.importModuleCompletionListContains("fake-module2");
verify.importModuleCompletionListContains("fake-module3/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(3);
}

View File

@@ -3,28 +3,21 @@
// @Filename: test0.ts
//// 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*/
//// import * as foo4 from "./folder//*import_as2*/
//// 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*/
//// import foo9 = require("./folder//*import_equals2*/
//// var foo11 = require("./*require0*/
//// var foo12 = require(".//*require1*/
//// var foo13 = require("./f/*require2*/
//// var foo14 = require("./folder//*require3*/
//// var foo15 = require("./folder/h/*require4*/
//// var foo14 = require("./folder//*require2*/
// @Filename: parentTest/sub/test5.ts
//// import * as foo16 from "../g/*import_as5*/
//// import * as foo16 from "../g/*import_as3*/
//// import foo17 = require("../g/*import_equals3*/
//// var foo18 = require("../g/*require3*/
//// import foo17 = require("../g/*import_equals5*/
//// var foo18 = require("../g/*require5*/
// @Filename: f1.ts
//// /*f1*/
@@ -40,11 +33,11 @@
//// /*f4*/
// @Filename: e1.ts
//// /*e1*/
// @Filename: folder/f1.ts
// @Filename: folder/f3.ts
//// /*subf1*/
// @Filename: folder/h1.ts
//// /*subh1*/
// @Filename: parentTest/f1.ts
// @Filename: parentTest/f4.ts
//// /*parentf1*/
// @Filename: parentTest/g1.ts
//// /*parentg1*/
@@ -58,27 +51,18 @@ for (const kind of kinds) {
verify.importModuleCompletionListContains("f1");
verify.importModuleCompletionListContains("f2");
verify.importModuleCompletionListContains("e1");
verify.importModuleCompletionListContains("test0");
verify.importModuleCompletionListContains("folder/");
verify.importModuleCompletionListContains("parentTest/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(6);
verify.not.importModuleCompletionListItemsCountIsGreaterThan(5);
goTo.marker(kind + "2");
verify.importModuleCompletionListContains("f1");
verify.importModuleCompletionListContains("f2");
verify.importModuleCompletionListContains("folder/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(3);
goTo.marker(kind + "3");
verify.importModuleCompletionListContains("f1");
verify.importModuleCompletionListContains("f3");
verify.importModuleCompletionListContains("h1");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(2);
goTo.marker(kind + "4");
verify.importModuleCompletionListContains("h1");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(1);
goTo.marker(kind + "5");
goTo.marker(kind + "3");
verify.importModuleCompletionListContains("f4");
verify.importModuleCompletionListContains("g1");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(1);
verify.importModuleCompletionListContains("sub/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(3);
}

View File

@@ -37,13 +37,14 @@ for (const kind of kinds) {
verify.importModuleCompletionListContains("f4");
verify.importModuleCompletionListContains("e1");
verify.importModuleCompletionListContains("e2");
verify.importModuleCompletionListContains("test0");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(7);
verify.not.importModuleCompletionListItemsCountIsGreaterThan(6);
goTo.marker(kind + "1");
verify.importModuleCompletionListContains("f1");
verify.importModuleCompletionListContains("f2");
verify.importModuleCompletionListContains("f3");
verify.importModuleCompletionListContains("f4");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(4);
verify.importModuleCompletionListContains("e1");
verify.importModuleCompletionListContains("e2");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(6);
}

View File

@@ -44,5 +44,7 @@ for (const kind of kinds) {
verify.importModuleCompletionListContains("module1");
verify.importModuleCompletionListContains("module2");
verify.importModuleCompletionListContains("more/");
// Should not contain itself
verify.not.importModuleCompletionListItemsCountIsGreaterThan(4);
}

View File

@@ -1,22 +1,15 @@
/// <reference path='fourslash.ts' />
// @Filename: test0.ts
//// /// <reference path="./*0*/
//// /// <reference path="/*0*/
//// /// <reference path="./*1*/
//// /// <reference path="../*2*/
//// /// <reference path=".//*3*/
//// /// <reference path="./f/*4*/" />
//// /// <reference path="./parentTest//*5*/
// @Filename: test1.ts
//// /// <reference path=".//*1*/
// @Filename: test2.ts
//// /// <reference path="./f/*2*/" />
// @Filename: test3.ts
//// /// <reference path="./folder//*3*/
// @Filename: test4.ts
//// /// <reference path="./folder/h/*4*/
// @Filename: parentTest/sub/test5.ts
//// /// <reference path="../g/*5*/
// @Filename: parentTest/sub/test1.ts
//// /// <reference path="../g/*6*/
// @Filename: f1.ts
//// /*f1*/
@@ -32,48 +25,25 @@
//// /*f4*/
// @Filename: e1.ts
//// /*e1*/
// @Filename: folder/f1.ts
//// /*subf1*/
// @Filename: folder/h1.ts
//// /*subh1*/
// @Filename: parentTest/f1.ts
//// /*parentf1*/
// @Filename: parentTest/g1.ts
//// /*parentg1*/
goTo.marker("0");
verify.importModuleCompletionListIsEmpty();
goTo.marker("1");
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("e1.ts");
verify.importModuleCompletionListContains("test0.ts");
verify.importModuleCompletionListContains("test1.ts");
verify.importModuleCompletionListContains("test2.ts");
verify.importModuleCompletionListContains("test3.ts");
verify.importModuleCompletionListContains("test4.ts");
verify.importModuleCompletionListContains("folder/");
verify.importModuleCompletionListContains("parentTest/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(11);
goTo.marker("2");
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("folder/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(4);
goTo.marker("3");
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("h1.ts");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(2);
goTo.marker("4");
verify.importModuleCompletionListContains("h1.ts");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(1);
for (let i = 0; i < 5; i++) {
goTo.marker("" + i);
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("e1.ts");
verify.importModuleCompletionListContains("parentTest/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(5);
}
goTo.marker("5");
verify.importModuleCompletionListContains("g1.ts");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(1);
verify.importModuleCompletionListContains("sub/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(2);
goTo.marker("6");
verify.importModuleCompletionListContains("g1.ts");
verify.importModuleCompletionListContains("sub/");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(2);

View File

@@ -2,46 +2,29 @@
// @allowJs: true
// @Filename: test0.ts
//// /// <reference path=".//*0*/
// @Filename: test1.ts
//// /// <reference path="./f/*1*/
//// /// <reference path="/*0*/
//// /// <reference path="./*1*/
//// /// <reference path="../*2*/
//// /// <reference path=".//*3*/
//// /// <reference path="./f/*4*/" />
// @Filename: f1.ts
//// /f1*/
//// /*f1*/
// @Filename: f1.js
//// /*f1j*/
// @Filename: f1.d.ts
//// /*f1d*/
// @Filename: f2.tsx
//// /*f2*/
// @Filename: f3.js
//// /*f3*/
//// /f2*/
// @Filename: f4.jsx
//// /*f4*/
// @Filename: e1.ts
//// /*e1*/
// @Filename: e2.js
//// /*e2*/
goTo.marker("0");
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.js");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("f3.js");
verify.importModuleCompletionListContains("f4.jsx");
verify.importModuleCompletionListContains("e1.ts");
verify.importModuleCompletionListContains("e2.js");
verify.importModuleCompletionListContains("test0.ts");
verify.importModuleCompletionListContains("test1.ts");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(10);
goTo.marker("1");
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.js");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("f3.js");
verify.importModuleCompletionListContains("f4.jsx");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(6);
for (let i = 0; i < 5; i++) {
goTo.marker("" + i);
verify.importModuleCompletionListContains("f1.ts");
verify.importModuleCompletionListContains("f1.js");
verify.importModuleCompletionListContains("f1.d.ts");
verify.importModuleCompletionListContains("f2.tsx");
verify.importModuleCompletionListContains("f4.jsx");
verify.not.importModuleCompletionListItemsCountIsGreaterThan(5);
}