Compare commits
3 commits
main
...
aozgaa/non
Author | SHA1 | Date | |
---|---|---|---|
|
7a67cf1796 | ||
|
2131d5727e | ||
|
70885ed301 |
|
@ -318,7 +318,7 @@ namespace ts {
|
|||
result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host);
|
||||
break;
|
||||
case ModuleResolutionKind.Classic:
|
||||
result = classicNameResolver(moduleName, containingFile, compilerOptions, host);
|
||||
result = classicModuleNameResolver(moduleName, containingFile, compilerOptions, host);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -749,7 +749,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
export function classicModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
const failedLookupLocations: string[] = [];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// We don't walk the filesystem to search for modules. Instead we use cheap heuristics.
|
||||
|
||||
// @moduleResolution: node
|
||||
|
||||
// @Filename: src/test.ts
|
||||
//// import {I as I0} from "/*0*/
|
||||
//// import * as IModule0 from "/*1*/
|
||||
//// import IRequireModule0 from "/*2*/
|
||||
//// import foo2 = require("/*3*/
|
||||
//// var foo3 = require("/*4*/
|
||||
|
||||
// @Filename: src/not_present.ts
|
||||
// @Filename: src/node_modules/1.ts
|
||||
// @Filename: src/node_modules/2.tsx
|
||||
// @Filename: src/node_modules/3.d.ts
|
||||
// @Filename: src/node_modules/4/package.json
|
||||
// @Filename: src/node_modules/5/index.ts
|
||||
// @Filename: src/node_modules/6/index.tsx
|
||||
// @Filename: src/node_modules/7/index.d.ts
|
||||
// @Filename: src/node_modules/@types/8.ts
|
||||
// @Filename: src/node_modules/@types/9.tsx
|
||||
// @Filename: src/node_modules/@types/10.d.ts
|
||||
// @Filename: src/node_modules/@types/11/package.json
|
||||
// @Filename: src/node_modules/@types/12/index.ts
|
||||
// @Filename: src/node_modules/@types/13/index.tsx
|
||||
// @Filename: src/node_modules/@types/14/index.d.ts
|
||||
|
||||
|
||||
for (let marker = 0; marker < 5; marker++) {
|
||||
goTo.marker(marker.toString());
|
||||
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' />
|
|
@ -0,0 +1,73 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// Should give completions for ts files only when allowJs is false.
|
||||
|
||||
// @Filename: d/exportInterface.ts
|
||||
//// export interface I { x: number; }
|
||||
|
||||
// @Filename: d/dd/onlyHereToCreateDir.ts
|
||||
//// /*dummyMarker*/
|
||||
|
||||
// @Filename: d/importInterface.ts
|
||||
//// import {I as I0} from "/*named0*/"
|
||||
//// import {I as I1} from "./*named1*/"
|
||||
//// import {I as I2} from ".//*named2*/"
|
||||
//// import {I as I3} from "../*named3*/"
|
||||
//// import {I as I4} from "..//*named4*/"
|
||||
//// import {I as I5} from "../d/*named5*/"
|
||||
//// import {I as I6} from "../d//*named6*/"
|
||||
//// import {I as I7} from "/tests/cases/fourslash/d//*named7*/"
|
||||
//// import {I as I8} from "/tests/cases/fourslash/d/../d/../../fourslash/d//*named8*/"
|
||||
////
|
||||
//// import * as IModule0 from "/*module0*/"
|
||||
//// import * as IModule1 from "./*module1*/"
|
||||
//// import * as IModule2 from ".//*module2*/"
|
||||
//// import * as IModule3 from "../*module3*/"
|
||||
//// import * as IModule4 from "..//*module4*/"
|
||||
//// import * as IModule5 from "../d/*module5*/"
|
||||
//// import * as IModule6 from "../d//*module6*/"
|
||||
//// import * as IModule7 from "/tests/cases/fourslash/d//*module7*/"
|
||||
//// import * as IModule8 from "/tests/cases/fourslash/d/../d/../../fourslash/d//*module8*/"
|
||||
////
|
||||
//// import IRequireModule0 from "/*requireModule0*/"
|
||||
//// import IRequireModule1 from "./*requireModule1*/"
|
||||
//// import IRequireModule2 from ".//*requireModule2*/"
|
||||
//// import IRequireModule3 from "../*requireModule3*/"
|
||||
//// import IRequireModule4 from "..//*requireModule4*/"
|
||||
//// import IRequireModule5 from "../d/*requireModule5*/"
|
||||
//// import IRequireModule6 from "../d//*requireModule6*/"
|
||||
//// import IRequireModule7 from "/tests/cases/fourslash/d//*requireModule7*/"
|
||||
//// import IRequireModule8 from "/tests/cases/fourslash/d/../d/../../fourslash/d//*requireModule8*/"
|
||||
|
||||
const kinds = ["named", "module", "requireModule"];
|
||||
|
||||
function hasCurDirCompletions() {
|
||||
verify.completionListContains("dd");
|
||||
verify.completionListContains("exportInterface");
|
||||
verify.not.completionListItemsCountIsGreaterThan(2);
|
||||
}
|
||||
|
||||
function hasParentCompletions() {
|
||||
verify.completionListContains("d");
|
||||
verify.not.completionListItemsCountIsGreaterThan(1);
|
||||
}
|
||||
|
||||
for (const kind of kinds) {
|
||||
goTo.marker(`${kind}0`);
|
||||
verify.completionListIsEmpty();
|
||||
|
||||
goTo.marker(`${kind}1`);
|
||||
goTo.marker(`${kind}2`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}3`);
|
||||
goTo.marker(`${kind}4`);
|
||||
hasParentCompletions();
|
||||
goTo.marker(`${kind}5`);
|
||||
hasParentCompletions();
|
||||
goTo.marker(`${kind}6`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}7`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}8`);
|
||||
hasCurDirCompletions();
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// Should give completions for ts files only when allowJs is false.
|
||||
|
||||
// @Filename: d/exportInterface.ts
|
||||
//// export interface I { x: number; }
|
||||
|
||||
// @Filename: d/dd/onlyHereToCreateDir.ts
|
||||
//// /*dummyMarker*/
|
||||
|
||||
// @Filename: d/importInterface.ts
|
||||
//// import {I as I0} from "/*named0*/
|
||||
//// import {I as I1} from "./*named1*/
|
||||
//// import {I as I2} from ".//*named2*/
|
||||
//// import {I as I3} from "../*named3*/
|
||||
//// import {I as I4} from "..//*named4*/
|
||||
//// import {I as I5} from "../d/*named5*/
|
||||
//// import {I as I6} from "../d//*named6*/
|
||||
//// import {I as I7} from "/tests/cases/fourslash/d//*named7*/
|
||||
//// import {I as I8} from "/tests/cases/fourslash/d/../d/../../fourslash/d//*named8*/
|
||||
////
|
||||
//// import * as IModule0 from "/*module0*/
|
||||
//// import * as IModule1 from "./*module1*/
|
||||
//// import * as IModule2 from ".//*module2*/
|
||||
//// import * as IModule3 from "../*module3*/
|
||||
//// import * as IModule4 from "..//*module4*/
|
||||
//// import * as IModule5 from "../d/*module5*/
|
||||
//// import * as IModule6 from "../d//*module6*/
|
||||
//// import * as IModule7 from "/tests/cases/fourslash/d//*module7*/
|
||||
//// import * as IModule8 from "/tests/cases/fourslash/d/../d/../../fourslash/d//*module8*/
|
||||
////
|
||||
//// import IRequireModule0 from "/*requireModule0*/
|
||||
//// import IRequireModule1 from "./*requireModule1*/
|
||||
//// import IRequireModule2 from ".//*requireModule2*/
|
||||
//// import IRequireModule3 from "../*requireModule3*/
|
||||
//// import IRequireModule4 from "..//*requireModule4*/
|
||||
//// import IRequireModule5 from "../d/*requireModule5*/
|
||||
//// import IRequireModule6 from "../d//*requireModule6*/
|
||||
//// import IRequireModule7 from "/tests/cases/fourslash/d//*requireModule7*/
|
||||
//// import IRequireModule8 from "/tests/cases/fourslash/d/../d/../../fourslash/d//*requireModule8*/
|
||||
|
||||
const kinds = ["named", "module", "requireModule"];
|
||||
|
||||
function hasCurDirCompletions() {
|
||||
verify.completionListContains("dd");
|
||||
verify.completionListContains("exportInterface");
|
||||
verify.not.completionListItemsCountIsGreaterThan(2);
|
||||
}
|
||||
|
||||
function hasParentCompletions() {
|
||||
verify.completionListContains("d");
|
||||
verify.not.completionListItemsCountIsGreaterThan(1);
|
||||
}
|
||||
|
||||
for (const kind of kinds) {
|
||||
goTo.marker(`${kind}0`);
|
||||
verify.completionListIsEmpty();
|
||||
|
||||
goTo.marker(`${kind}1`);
|
||||
goTo.marker(`${kind}2`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}3`);
|
||||
goTo.marker(`${kind}4`);
|
||||
hasParentCompletions();
|
||||
goTo.marker(`${kind}5`);
|
||||
hasParentCompletions();
|
||||
goTo.marker(`${kind}6`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}7`);
|
||||
hasCurDirCompletions();
|
||||
goTo.marker(`${kind}8`);
|
||||
hasCurDirCompletions();
|
||||
}
|
Loading…
Reference in a new issue