Mid edits
This commit is contained in:
parent
2131d5727e
commit
7a67cf1796
|
@ -400,49 +400,64 @@ namespace ts.Completions {
|
|||
|
||||
/**
|
||||
* Check all of the declared modules and those in node modules. Possible sources of modules:
|
||||
* Modules that are found by the type checker
|
||||
* Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option)
|
||||
* Modules from node_modules (i.e. those listed in package.json)
|
||||
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions
|
||||
* * Modules that are found by the type checker
|
||||
* * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option)
|
||||
* * Modules from node_modules (i.e. those listed in package.json)
|
||||
*
|
||||
* We include all files that are found in node_modules/moduleName/ with acceptable file extensions.
|
||||
* Note that we do not traverse the path through all of its ancestors and node_modules subdirectories as that is too
|
||||
* slow and the above should include all intended packages.
|
||||
*/
|
||||
function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, span: TextSpan): CompletionEntry[] {
|
||||
const { baseUrl, paths } = compilerOptions;
|
||||
|
||||
let result: CompletionEntry[];
|
||||
// TODO: (arozga) do completions by path fragment
|
||||
|
||||
const dirPathFragment = getDirectoryPath(normalizeSlashes(fragment));
|
||||
|
||||
if (baseUrl) {
|
||||
const fileExtensions = getSupportedExtensions(compilerOptions);
|
||||
const projectDir = compilerOptions.project || host.getCurrentDirectory();
|
||||
const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl);
|
||||
result = getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span);
|
||||
|
||||
if (paths) {
|
||||
if (!paths) {
|
||||
result = getCompletionEntriesForDirectoryFragment(dirPathFragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span);
|
||||
}
|
||||
else {
|
||||
result = [];
|
||||
for (const path in paths) {
|
||||
if (paths.hasOwnProperty(path)) {
|
||||
if (path === "*") {
|
||||
if (paths[path]) {
|
||||
for (const pattern of paths[path]) {
|
||||
for (const match of getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions)) {
|
||||
result.push(createCompletionEntryForModule(match, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
if (!paths.hasOwnProperty(path)) {
|
||||
continue;
|
||||
}
|
||||
const patterns = paths[path];
|
||||
if (!patterns) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const pathPattern = hasZeroOrOneAsteriskCharacter(path) ? tryParsePattern(path) : undefined;
|
||||
|
||||
if (pathPattern) {
|
||||
for (const pattern of patterns) {
|
||||
// TODO: (arozga) Need to match fragment against path-pattern to see if we have already partially-completed the path.
|
||||
const matches = getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions);
|
||||
// TODO: (arozga)
|
||||
if (matches) {
|
||||
for (const match of matches) {
|
||||
// TODO: (arozga) need to figure out which fragment to add based on
|
||||
result.push(createCompletionEntryForModule(pathPattern.prefix + match + pathPattern.suffix, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (startsWith(path, fragment)) {
|
||||
const entry = paths[path] && paths[path].length === 1 && paths[path][0];
|
||||
if (entry) {
|
||||
result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: (arozga) Check if target of pattern exists.
|
||||
result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = [];
|
||||
}
|
||||
|
||||
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result);
|
||||
result = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result);
|
||||
|
||||
for (const moduleName of enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions)) {
|
||||
result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span));
|
||||
|
@ -451,7 +466,14 @@ namespace ts.Completions {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: string[]): string[] {
|
||||
/**
|
||||
* ???
|
||||
*
|
||||
* TODO: (arozga) Make the fragment a path (as an argument)
|
||||
* TODO: (arozga) Make the result returned be the only the last bit of the path (like in getDirFragment).
|
||||
* TODO: (arozga) Draw pictures of what we think the various components look like.
|
||||
*/
|
||||
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: string[]): string[] | undefined {
|
||||
if (host.readDirectory) {
|
||||
const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined;
|
||||
if (parsed) {
|
||||
|
@ -486,6 +508,7 @@ namespace ts.Completions {
|
|||
continue;
|
||||
}
|
||||
|
||||
// TODO: (arozga) simplify.
|
||||
const start = completePrefix.length;
|
||||
const length = normalizedMatch.length - start - normalizedSuffix.length;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// Should give completions for node modules and files within those modules with ts file extensions/
|
||||
// When baseURL isn't specified, _________________??????????????????
|
||||
// We don't walk the filesystem to search for modules. Instead we use cheap heuristics.
|
||||
|
||||
// @moduleResolution: node
|
||||
|
||||
|
@ -9,8 +8,8 @@
|
|||
//// import {I as I0} from "/*0*/
|
||||
//// import * as IModule0 from "/*1*/
|
||||
//// import IRequireModule0 from "/*2*/
|
||||
//// // TODO:(arozga) require syntax?
|
||||
|
||||
//// import foo2 = require("/*3*/
|
||||
//// var foo3 = require("/*4*/
|
||||
|
||||
// @Filename: src/not_present.ts
|
||||
// @Filename: src/node_modules/1.ts
|
||||
|
@ -28,26 +27,8 @@
|
|||
// @Filename: src/node_modules/@types/13/index.tsx
|
||||
// @Filename: src/node_modules/@types/14/index.d.ts
|
||||
|
||||
// @Filename: not_present.ts
|
||||
// @Filename: node_modules/15.ts
|
||||
// @Filename: node_modules/16.tsx
|
||||
// @Filename: node_modules/17.d.ts
|
||||
// @Filename: node_modules/18/package.json
|
||||
// @Filename: node_modules/19/index.ts
|
||||
// @Filename: node_modules/20/index.tsx
|
||||
// @Filename: node_modules/21/index.d.ts
|
||||
// @Filename: node_modules/@types/22.ts
|
||||
// @Filename: node_modules/@types/23.tsx
|
||||
// @Filename: node_modules/@types/24.d.ts
|
||||
// @Filename: node_modules/@types/25/package.json
|
||||
// @Filename: node_modules/@types/26/index.ts
|
||||
// @Filename: node_modules/@types/27/index.tsx
|
||||
// @Filename: node_modules/@types/28/index.d.ts
|
||||
|
||||
for (let marker = 0; marker < 3; marker++) {
|
||||
for (let marker = 0; marker < 5; marker++) {
|
||||
goTo.marker(marker.toString());
|
||||
for (let i = 1; i < 29; i++) {
|
||||
verify.completionListContains(i.toString());
|
||||
verify.not.completionListItemsCountIsGreaterThan(28);
|
||||
}
|
||||
verify.completionListIsEmpty();
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// if baseURL is specified but paths is not, then we offer completions for non-relative imports
|
||||
// relative to the baseURL.
|
||||
|
||||
// @Filename: tsconfig.json
|
||||
//// {
|
||||
//// "compilerOptions": {
|
||||
//// "baseUrl": "./modules"
|
||||
//// }
|
||||
//// }
|
||||
|
||||
// @Filename: test.ts
|
||||
//// import * as a from "/*0*/
|
||||
//// import * as b from "dir//*1*/"
|
||||
|
||||
// @Filename: node_modules/bad.ts
|
||||
|
||||
// @Filename: modules/a.ts
|
||||
//// /*marker_a*/
|
||||
|
||||
// @Filename: modules/a.d.ts
|
||||
//// /*marker_a_d*/
|
||||
|
||||
// @Filename: modules/dir/b.ts
|
||||
//// /*marker_b*/
|
||||
|
||||
goTo.marker("0");
|
||||
verify.completionListContains("a");
|
||||
verify.completionListContains("dir");
|
||||
verify.not.completionListItemsCountIsGreaterThan(2);
|
||||
|
||||
goTo.marker("1");
|
||||
verify.completionListContains("b");
|
||||
verify.not.completionListItemsCountIsGreaterThan(1);
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1,95 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// If baseURL and paths is specified, we compare against the baseUrl/paths rule.
|
||||
// We do NOT do a raw comparison against baseUrl unless we specified such a paths rule.
|
||||
|
||||
// @Filename: tsconfig.json
|
||||
//// {
|
||||
//// "compilerOptions": {
|
||||
//// "baseUrl": "./modules"
|
||||
//// }
|
||||
//// }
|
||||
|
||||
// @Filename: tsconfig.json
|
||||
//// {
|
||||
//// "compilerOptions": {
|
||||
//// "baseUrl": "./modules",
|
||||
//// "paths": {
|
||||
//// "a": ["a.ts"],
|
||||
//// "b": ["b.ts"],
|
||||
//// "c": ["c.ts", "c.d.ts"],
|
||||
//// "d": ["dir/d.ts"],
|
||||
//// "e/e": ["dir/e.ts"],
|
||||
//// "*": ["dir_star/*"],
|
||||
//// "prefix_*_suffix": ["dir_star/*"],
|
||||
//// "i": ["i.ts"], // Target does not exist.
|
||||
//// "j/j": ["dir/j.ts"] // Target does not exist.
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
|
||||
// @Filename: test.ts
|
||||
//// import * as a from "/*0*/
|
||||
//// import * as b from "e//*1*/
|
||||
//// import * as c from "g//*2*/
|
||||
//// import * as d from "prefix_dir2//*3*/_suffix
|
||||
|
||||
// @Filename: node_modules/bad.ts
|
||||
//// /*marker_bad*/
|
||||
|
||||
// @Filename: modules/also_bad.ts
|
||||
//// /*marker_also_bad*/
|
||||
|
||||
// @Filename: modules/a.ts
|
||||
//// /*marker_a*/
|
||||
|
||||
// @Filename: modules/b.ts
|
||||
//// /*marker_b*/
|
||||
|
||||
// @Filename: modules/c.ts
|
||||
//// /*marker_c*/
|
||||
|
||||
// @Filename: modules/c.d.ts
|
||||
//// /*marker_c_d*/
|
||||
|
||||
// @Filename: modules/dir/d.ts
|
||||
//// /*marker_d*/
|
||||
|
||||
// @Filename: modules/dir/e.ts
|
||||
//// /*marker_e*/
|
||||
|
||||
// @Filename: modules/dir_star/f.ts
|
||||
//// /*marker_f*/
|
||||
|
||||
// @Filename: modules/dir_star/g.ts
|
||||
//// /*marker_g*/
|
||||
|
||||
// @Filename: modules/dir_star/dir2/h.ts
|
||||
//// /*marker_h*/
|
||||
|
||||
goTo.marker("0");
|
||||
verify.completionListContains("a");
|
||||
verify.completionListContains("b");
|
||||
verify.completionListContains("c");
|
||||
verify.completionListContains("d");
|
||||
verify.completionListContains("e");
|
||||
verify.completionListContains("f");
|
||||
verify.completionListContains("g");
|
||||
verify.completionListContains("dir2");
|
||||
verify.completionListContains("prefix_f_suffix");
|
||||
verify.completionListContains("prefix_g_suffix");
|
||||
verify.completionListContains("prefix_dir2_suffix");
|
||||
verify.completionListContains("h");
|
||||
verify.completionListContains("i");
|
||||
verify.not.completionListItemsCountIsGreaterThan(5);
|
||||
/*
|
||||
goTo.marker("1");
|
||||
verify.completionListContains("d");
|
||||
verify.not.completionListItemsCountIsGreaterThan(1);
|
||||
|
||||
goTo.marker("2");
|
||||
verify.completionListIsEmpty();
|
||||
|
||||
goTo.marker("2");
|
||||
verify.completionListContains("h");
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
|
@ -0,0 +1 @@
|
|||
/// <reference path='fourslash.ts' />
|
Loading…
Reference in a new issue