Let AutoImportProviderProject resolve JS when allowJs and maxNodeModulesJsDepth allows (#45524)

* Let AutoImportProviderProject resolve JS when allowJs and maxNodeModulesJsDepth allows

* Simplify function
This commit is contained in:
Andrew Branch
2021-08-25 15:06:14 -07:00
committed by GitHub
parent db0576c251
commit 30103de1dd
9 changed files with 93 additions and 17 deletions

View File

@@ -1078,9 +1078,8 @@ namespace ts {
}
/* @internal */
export function tryResolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string | undefined {
const { resolvedModule } = tryResolveJSModuleWorker(moduleName, initialDir, host);
return resolvedModule && resolvedModule.resolvedFileName;
export function tryResolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost) {
return tryResolveJSModuleWorker(moduleName, initialDir, host).resolvedModule;
}
const jsOnlyExtensions = [Extensions.JavaScript];

View File

@@ -138,6 +138,13 @@ namespace ts.server {
this.processResponse(request, /*expectEmptyBody*/ true);
}
/*@internal*/
setCompilerOptionsForInferredProjects(options: protocol.CompilerOptions) {
const args: protocol.SetCompilerOptionsForInferredProjectsArgs = { options };
const request = this.processRequest(CommandNames.CompilerOptionsForInferredProjects, args);
this.processResponse(request, /*expectEmptyBody*/ false);
}
openFile(file: string, fileContent?: string, scriptKindName?: "TS" | "JS" | "TSX" | "JSX"): void {
const args: protocol.OpenRequestArgs = { file, fileContent, scriptKindName };
this.processRequest(CommandNames.Open, args);

View File

@@ -3935,6 +3935,11 @@ namespace FourSlash {
(this.languageService as ts.server.SessionClient).configurePlugin(pluginName, configuration);
}
public setCompilerOptionsForInferredProjects(options: ts.server.protocol.CompilerOptions) {
ts.Debug.assert(this.testType === FourSlashTestType.Server);
(this.languageService as ts.server.SessionClient).setCompilerOptionsForInferredProjects(options);
}
public toggleLineComment(newFileContent: string): void {
const changes: ts.TextChange[] = [];
for (const range of this.getRanges()) {
@@ -4077,7 +4082,7 @@ namespace FourSlash {
try {
const test = new FourSlashInterface.Test(state);
const goTo = new FourSlashInterface.GoTo(state);
const plugins = new FourSlashInterface.Plugins(state);
const config = new FourSlashInterface.Config(state);
const verify = new FourSlashInterface.Verify(state);
const edit = new FourSlashInterface.Edit(state);
const debug = new FourSlashInterface.Debug(state);
@@ -4085,7 +4090,7 @@ namespace FourSlash {
const cancellation = new FourSlashInterface.Cancellation(state);
// eslint-disable-next-line no-eval
const f = eval(wrappedCode);
f(test, goTo, plugins, verify, edit, debug, format, cancellation, FourSlashInterface.classification, FourSlashInterface.Completion, verifyOperationIsCancelled);
f(test, goTo, config, verify, edit, debug, format, cancellation, FourSlashInterface.classification, FourSlashInterface.Completion, verifyOperationIsCancelled);
}
catch (err) {
// ensure 'source-map-support' is triggered while we still have the handler attached by accessing `error.stack`.

View File

@@ -48,13 +48,17 @@ namespace FourSlashInterface {
}
}
export class Plugins {
export class Config {
constructor(private state: FourSlash.TestState) {
}
public configurePlugin(pluginName: string, configuration: any): void {
this.state.configurePlugin(pluginName, configuration);
}
public setCompilerOptionsForInferredProjects(options: ts.server.protocol.CompilerOptions): void {
this.state.setCompilerOptionsForInferredProjects(options);
}
}
export class GoTo {

View File

@@ -829,7 +829,7 @@ namespace Harness.LanguageService {
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any {
// eslint-disable-next-line no-restricted-globals
return setTimeout(callback, ms, args);
return setTimeout(callback, ms, ...args);
}
clearTimeout(timeoutId: any): void {

View File

@@ -1919,16 +1919,25 @@ namespace ts.server {
}
if (dependencyNames) {
const resolutions = map(arrayFrom(dependencyNames.keys()), name => resolveTypeReferenceDirective(
name,
rootFileName,
compilerOptions,
moduleResolutionHost));
const resolutions = mapDefined(arrayFrom(dependencyNames.keys()), name => {
const types = resolveTypeReferenceDirective(
name,
rootFileName,
compilerOptions,
moduleResolutionHost);
if (types.resolvedTypeReferenceDirective) {
return types.resolvedTypeReferenceDirective;
}
if (compilerOptions.allowJs && compilerOptions.maxNodeModuleJsDepth) {
return tryResolveJSModule(name, hostProject.currentDirectory, moduleResolutionHost);
}
});
const symlinkCache = hostProject.getSymlinkCache();
for (const resolution of resolutions) {
if (!resolution.resolvedTypeReferenceDirective?.resolvedFileName) continue;
const { resolvedFileName, originalPath } = resolution.resolvedTypeReferenceDirective;
if (!resolution.resolvedFileName) continue;
const { resolvedFileName, originalPath } = resolution;
if (!program.getSourceFile(resolvedFileName) && (!originalPath || !program.getSourceFile(originalPath))) {
rootNames = append(rootNames, resolvedFileName);
// Avoid creating a large project that would significantly slow down time to editor interactivity

View File

@@ -111,6 +111,20 @@ declare module ts {
exportName: string;
}
interface CompilerOptions {
module?: string;
target?: string;
jsx?: string;
allowJs?: boolean;
maxNodeModulesJsDepth?: number;
strictNullChecks?: boolean;
sourceMap?: boolean;
allowSyntheticDefaultImports?: boolean;
allowNonTsExtensions?: boolean;
resolveJsonModule?: boolean;
[key: string]: string | number | boolean | undefined;
}
function flatMap<T, U>(array: ReadonlyArray<T>, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[];
}
@@ -200,8 +214,9 @@ declare namespace FourSlashInterface {
symbolsInScope(range: Range): any[];
setTypesRegistry(map: { [key: string]: void }): void;
}
class plugins {
class config {
configurePlugin(pluginName: string, configuration: any): void;
setCompilerOptionsForInferredProjects(options: ts.CompilerOptions)
}
class goTo {
marker(name?: string | Marker): void;
@@ -810,7 +825,7 @@ declare namespace FourSlashInterface {
declare function ignoreInterpolations(diagnostic: string | ts.DiagnosticMessage): FourSlashInterface.DiagnosticIgnoredInterpolations;
declare function verifyOperationIsCancelled(f: any): void;
declare var test: FourSlashInterface.test_;
declare var plugins: FourSlashInterface.plugins;
declare var config: FourSlashInterface.config;
declare var goTo: FourSlashInterface.goTo;
declare var verify: FourSlashInterface.verify;
declare var edit: FourSlashInterface.edit;

View File

@@ -0,0 +1,37 @@
/// <reference path="../fourslash.ts" />
// @Filename: /packages/a/package.json
//// {
//// "name": "package-a",
//// "dependencies": {
//// "package-b": "*"
//// }
//// }
// @Filename: /packages/a/index.js
//// packageB/**/
// @Filename: /packages/b/package.json
//// { "name": "package-b", "main": "index.js" }
// @Filename: /packages/b/index.js
//// export const packageB = "package-b";
// @link: /packages/b -> /packages/a/node_modules/package-b
config.setCompilerOptionsForInferredProjects({ module: "commonjs", allowJs: true, maxNodeModulesJsDepth: 2 });
goTo.marker("");
verify.completions({
marker: "",
includes: [{
name: "packageB",
source: "package-b",
sourceDisplay: "package-b",
hasAction: true,
sortText: completion.SortText.AutoImportSuggestions,
}],
preferences: {
includeCompletionsForModuleExports: true,
allowIncompleteCompletions: true,
}
});

View File

@@ -18,5 +18,5 @@
// Test that plugin adds an error message which is able to be configured
goTo.marker();
verify.getSemanticDiagnostics([{ message: "configured error", code: 9999, range: { pos: 0, end: 3, fileName: "a.ts" } }]);
plugins.configurePlugin("configurable-diagnostic-adder", { message: "new error" });
config.configurePlugin("configurable-diagnostic-adder", { message: "new error" });
verify.getSemanticDiagnostics([{ message: "new error", code: 9999, range: { pos: 0, end: 3, fileName: "a.ts" } }]);