diff --git a/client/src/extension.ts b/client/src/extension.ts index aba76db5..4550bfe2 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,5 +1,6 @@ import * as path from "path"; import { promises as fs } from "fs"; +import glob from "glob"; import { workspace, @@ -42,11 +43,22 @@ import { DenoPluginConfigurationField, } from "../../core/configuration"; +import { + TypescriptDenoPluginMessage, + TypescriptDenoPluginConfig, +} from "../../core/typescript_deno_plugin_config"; + const TYPESCRIPT_EXTENSION_NAME = "vscode.typescript-language-features"; const TYPESCRIPT_DENO_PLUGIN_ID = "typescript-deno-plugin"; type TypescriptAPI = { - configurePlugin(pluginId: string, configuration: ConfigurationField): void; + /** + * This method will `reset` the plugin by the msg + * see [this issue](https://github.com/microsoft/vscode/issues/106402) + * @param pluginId The ID of plugin send to + * @param msg the message that will send to plugin + */ + configurePlugin(pluginId: string, msg: TypescriptDenoPluginMessage): void; }; type DenoInfo = { @@ -113,6 +125,9 @@ export class Extension { }, executablePath: "", }; + + private enable = false; + // get configuration of Deno public getConfiguration(uri?: Uri): ConfigurationField { const config: ConfigurationField = {}; @@ -140,6 +155,21 @@ export class Extension { return config; } + + private resetTypescriptDenoPlugin( + config?: ConfigurationField, + plugin_config?: TypescriptDenoPluginConfig + ) { + this.tsAPI.configurePlugin(TYPESCRIPT_DENO_PLUGIN_ID, { + project_config: config ?? this.getConfiguration(), + plugin_config: + plugin_config ?? + ({ enable: this.enable } as TypescriptDenoPluginConfig), + }); + + commands.executeCommand("typescript.reloadProjects"); + } + // register command for deno extension private registerCommand( command: string, @@ -227,7 +257,7 @@ export class Extension { progressOnInitialization: true, middleware: { provideCodeActions: (document, range, context, token, next) => { - if (!this.getConfiguration(document.uri).enable) { + if (!this.enable) { return []; } // do not ask server for code action when the diagnostic isn't from deno @@ -258,14 +288,14 @@ export class Extension { token, next ) => { - if (!this.getConfiguration(document.uri).enable) { + if (!this.enable) { return []; } return next(document, position, context, token); }, provideCodeLenses: (document, token, next) => { - if (!isInDeno(document.uri.fsPath)) { + if (!this.enable || !isInDeno(document.uri.fsPath)) { return; } return next(document, token); @@ -324,14 +354,8 @@ export class Extension { this.statusBar.hide(); return; } - - const uri = document.uri; - const enabled = workspace - .getConfiguration(this.configurationSection, uri) - .get("enable"); - // if vscode-deno have been disable for workspace - if (!enabled) { + if (!this.enable) { this.statusBar.hide(); return; } @@ -392,6 +416,34 @@ Executable ${this.denoInfo.executablePath}`; this.client.sendNotification(Notification.diagnostic, uri.toString()); } } + + private isPartOfProject( + config: ConfigurationField, + entry_path: string, + workspace_path?: string + ): boolean { + if (workspace_path === undefined) { + return false; + } + + const includes = + config.include?.some((it) => + glob + .sync(path.join(workspace_path, it)) + .map((it) => path.normalize(it)) + .includes(entry_path) + ) ?? true; + + const excludes = !config.exclude?.some((it) => + glob + .sync(path.join(workspace_path, it)) + .map((it) => path.normalize(it)) + .includes(entry_path) + ); + + return includes && excludes; + } + private sync(document?: TextDocument) { if (document) { const relativeFilepath = workspace.asRelativePath( @@ -404,13 +456,24 @@ Executable ${this.denoInfo.executablePath}`; ) { const config = this.getConfiguration(document.uri); + this.enable = + !!config.enable && + this.isPartOfProject( + config, + document.uri.fsPath, + workspace.getWorkspaceFolder(document.uri)?.uri?.fsPath + ); + commands.executeCommand( "setContext", "denoExtensionActivated", - !!config.enable + this.enable ); - this.tsAPI.configurePlugin(TYPESCRIPT_DENO_PLUGIN_ID, config); + this.client?.sendNotification("_setEnable", this.enable); + + // Reset the plugin + this.resetTypescriptDenoPlugin(); this.updateDiagnostic(document.uri); } } @@ -444,10 +507,7 @@ Executable ${this.denoInfo.executablePath}`; this.context = context; this.tsAPI = await getTypescriptAPI(); - this.tsAPI.configurePlugin( - TYPESCRIPT_DENO_PLUGIN_ID, - this.getConfiguration(window.activeTextEditor?.document.uri) - ); + this.resetTypescriptDenoPlugin(); this.statusBar = window.createStatusBarItem(StatusBarAlignment.Right, 0); diff --git a/core/configuration.test.ts b/core/configuration.test.ts index e0418b0e..54322288 100644 --- a/core/configuration.test.ts +++ b/core/configuration.test.ts @@ -12,10 +12,10 @@ test("core / configuration / resolveFromVscode if it is a valid file", async () configManager.resolveFromVscode(vscodeDir); expect(configManager.config).toEqual({ + ...Configuration.defaultConfiguration, enable: true, unstable: true, import_map: "./import_map.json", - lint: false, } as ConfigurationField); }); @@ -27,10 +27,8 @@ test("core / configuration / resolveFromVscode if valid section", async () => { configManager.resolveFromVscode(vscodeDir); expect(configManager.config).toEqual({ + ...Configuration.defaultConfiguration, enable: true, - unstable: false, - import_map: null, - lint: false, } as ConfigurationField); }); @@ -49,12 +47,7 @@ test("core / configuration / resolveFromVscode if config file is empty", async ( configManager.resolveFromVscode(vscodeDir); - expect(configManager.config).toEqual({ - enable: false, - unstable: false, - import_map: null, - lint: false, - } as ConfigurationField); + expect(configManager.config).toEqual(Configuration.defaultConfiguration); }); test("core / configuration / resolveFromVscode if field is invalid", async () => { @@ -65,10 +58,10 @@ test("core / configuration / resolveFromVscode if field is invalid", async () => configManager.resolveFromVscode(vscodeDir); expect(configManager.config).toEqual({ + ...Configuration.defaultConfiguration, enable: true, unstable: true, import_map: "1,2,3", - lint: false, } as ConfigurationField); }); @@ -88,9 +81,7 @@ test("core / configuration / update", async () => { expect(hasTriggerListener).toBe(true); expect(configManager.config).toEqual({ + ...Configuration.defaultConfiguration, enable: true, - unstable: false, - import_map: null, - lint: false, } as ConfigurationField); }); diff --git a/core/configuration.ts b/core/configuration.ts index cc29a043..1b450d3e 100644 --- a/core/configuration.ts +++ b/core/configuration.ts @@ -12,6 +12,8 @@ export const DenoPluginConfigurationField: (keyof ConfigurationField)[] = [ "unstable", "import_map", "lint", + "include", + "exclude", ]; export type ConfigurationField = { @@ -19,6 +21,8 @@ export type ConfigurationField = { unstable?: boolean; import_map?: string | null; lint?: boolean; + include?: string[]; + exclude?: string[]; }; interface ConfigurationInterface { @@ -34,6 +38,8 @@ export class Configuration implements ConfigurationInterface { unstable: false, import_map: null, lint: false, + include: ["**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx", "**/*.mjs"], + exclude: [], }; private readonly _configUpdatedListeners = new Set<() => void>(); diff --git a/core/typescript_deno_plugin_config.ts b/core/typescript_deno_plugin_config.ts new file mode 100644 index 00000000..d756f2a1 --- /dev/null +++ b/core/typescript_deno_plugin_config.ts @@ -0,0 +1,10 @@ +import { ConfigurationField } from "./configuration"; + +export interface TypescriptDenoPluginConfig { + readonly enable: boolean; +} + +export interface TypescriptDenoPluginMessage { + plugin_config: TypescriptDenoPluginConfig; + project_config: ConfigurationField; +} diff --git a/package.json b/package.json index f604af2a..3547f02a 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,38 @@ true, false ] + }, + "deno.include": { + "type": "array", + "default": [ + "**/*.ts", + "**/*.js", + "**/*.tsx", + "**/*.jsx", + "**/*.mjs" + ], + "markdownDescription": "Controls which file/folder will inlucde in the project.", + "scope": "resource", + "examples": [ + [ + "**/*.ts", + "**/*.js", + "**/*.tsx", + "**/*.jsx", + "**/*.mjs" + ] + ] + }, + "deno.exclude": { + "type": "array", + "default": [], + "markdownDescription": "Controls which file/folder will be exclude from the project.", + "scope": "resource", + "examples": [ + [ + "**/*.d.ts" + ] + ] } } }, @@ -184,11 +216,12 @@ }, "devDependencies": { "@types/deep-equal": "1.0.1", + "@types/glob": "^7.1.3", "@types/jest": "26.0.10", "@types/json5": "0.0.30", "@types/node": "14.6.2", - "@types/which": "1.3.2", "@types/semver": "7.3.3", + "@types/which": "1.3.2", "@typescript-eslint/eslint-plugin": "3.10.1", "@typescript-eslint/parser": "3.10.1", "coveralls": "3.1.0", @@ -204,6 +237,7 @@ "dependencies": { "deep-equal": "2.0.3", "deepmerge": "^4.2.2", + "glob": "^7.1.6", "got": "^11.5.2", "json5": "^2.1.3", "semver": "7.3.2", diff --git a/server/src/dependency_tree.ts b/server/src/dependency_tree.ts index c5a3e7be..71d02d46 100644 --- a/server/src/dependency_tree.ts +++ b/server/src/dependency_tree.ts @@ -12,6 +12,8 @@ import { ImportMap } from "../../core/import_map"; import { isHttpURL } from "../../core/util"; import { Request } from "../../core/const"; +import Plugable from "./plugable"; + interface URLDep { filepath: string; location: { start: Position; end: Position }; @@ -19,14 +21,24 @@ interface URLDep { type DependencyTreeMap = { [key: string]: URLDep[] }; -export class DependencyTree { - constructor(connection: IConnection, private bridge: Bridge) { +export class DependencyTree implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + private bridge: Bridge + ) { + this.enabled = enabled; connection.onRequest( Request.analysisDependency, this.getDependencyTreeOfProject.bind(this) ); } async getDependencyTreeOfProject(uriStr: string): Promise { + if (!this.enabled) return {}; const folderUir = URI.parse(uriStr); const folder = folderUir.fsPath; diff --git a/server/src/language/code_lens.ts b/server/src/language/code_lens.ts index 9cd28b2b..bb1b0aab 100644 --- a/server/src/language/code_lens.ts +++ b/server/src/language/code_lens.ts @@ -10,9 +10,20 @@ import { URI } from "vscode-uri"; import { CacheModule } from "../../../core/deno_cache"; import { isInDeno } from "../../../core/deno"; -export class CodeLens { - constructor(connection: IConnection, documents: TextDocuments) { +import Plugable from "../plugable"; + +export class CodeLens implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + documents: TextDocuments + ) { connection.onCodeLens((params) => { + if (!this.enabled) return; const { textDocument } = params; const document = documents.get(textDocument.uri); diff --git a/server/src/language/completion.ts b/server/src/language/completion.ts index 03843b36..0ce4b6e5 100644 --- a/server/src/language/completion.ts +++ b/server/src/language/completion.ts @@ -14,6 +14,8 @@ import { Cache } from "../../../core/cache"; import { ImportCompletionEnhanced } from "./import_completion_enhanced"; +import Plugable from "../plugable"; + // Cache for 30 second or 30 references const cache = Cache.create(1000 * 30, 30); @@ -25,13 +27,19 @@ getAllDenoCachedDeps() // do nothing }); -export class Completion { +export class Completion implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + constructor( + private enabled: boolean, connection: IConnection, documents: TextDocuments, import_enhanced: ImportCompletionEnhanced ) { connection.onCompletion(async (params) => { + if (!this.enabled) return; const { position, partialResultToken, textDocument } = params; const doc = documents.get(textDocument.uri); diff --git a/server/src/language/definition.ts b/server/src/language/definition.ts index ea8212a8..647ea2fd 100644 --- a/server/src/language/definition.ts +++ b/server/src/language/definition.ts @@ -10,9 +10,20 @@ import { URI } from "vscode-uri"; import { getDenoTypesHintsFromDocument } from "../deno_types"; import { ModuleResolver } from "../../../core/module_resolver"; -export class Definition { - constructor(connection: IConnection, documents: TextDocuments) { +import Plugable from "../plugable"; + +export class Definition implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + documents: TextDocuments + ) { connection.onDefinition(async (params) => { + if (!this.enabled) return; const { textDocument, position } = params; const document = documents.get(textDocument.uri); diff --git a/server/src/language/diagnostics.ts b/server/src/language/diagnostics.ts index f06602bd..71974a6a 100644 --- a/server/src/language/diagnostics.ts +++ b/server/src/language/diagnostics.ts @@ -23,6 +23,8 @@ import { getImportModules } from "../../../core/deno_deps"; import { Notification } from "../../../core/const"; import { deno } from "../deno"; +import Plugable from "../plugable"; + type Fix = { title: string; command: string; @@ -47,14 +49,20 @@ const FixItems: { [code: number]: Fix } = { const DENO_LINT = "deno_lint"; -export class Diagnostics { +export class Diagnostics implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + constructor( + private enabled: boolean, private name: string, private connection: IConnection, private bridge: Bridge, private documents: TextDocuments ) { connection.onCodeAction(async (params) => { + if (!this.enabled) return; const { context, textDocument } = params; const { diagnostics } = context; const denoDiagnostics = diagnostics.filter( @@ -161,6 +169,7 @@ export class Diagnostics { * @param document */ async generate(document: TextDocument): Promise { + if (!this.enabled) return []; if (!isValidDenoDocument(document.languageId)) { return []; } diff --git a/server/src/language/document_formatting.ts b/server/src/language/document_formatting.ts index 18400e88..dff5e39a 100644 --- a/server/src/language/document_formatting.ts +++ b/server/src/language/document_formatting.ts @@ -9,13 +9,21 @@ import { TextDocument } from "vscode-languageserver-textdocument"; import { deno } from "../deno"; import { Bridge } from "../bridge"; -export class DocumentFormatting { +import Plugable from "../plugable"; + +export class DocumentFormatting implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + constructor( + private enabled: boolean, connection: IConnection, documents: TextDocuments, bridge: Bridge ) { connection.onDocumentFormatting(async (params) => { + if (!this.enabled) return; const uri = params.textDocument.uri; const doc = documents.get(uri); diff --git a/server/src/language/document_highlight.ts b/server/src/language/document_highlight.ts index c0ce04ae..0cbaefe3 100644 --- a/server/src/language/document_highlight.ts +++ b/server/src/language/document_highlight.ts @@ -8,9 +8,20 @@ import { TextDocument } from "vscode-languageserver-textdocument"; import { getDenoTypesHintsFromDocument } from "../deno_types"; -export class DocumentHighlight { - constructor(connection: IConnection, documents: TextDocuments) { +import Plugable from "../plugable"; + +export class DocumentHighlight implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + documents: TextDocuments + ) { connection.onDocumentHighlight(async (params) => { + if (!this.enabled) return; const { textDocument, position } = params; const document = documents.get(textDocument.uri); diff --git a/server/src/language/hover.ts b/server/src/language/hover.ts index a9337f8a..1cb3996a 100644 --- a/server/src/language/hover.ts +++ b/server/src/language/hover.ts @@ -8,9 +8,20 @@ import { TextDocument } from "vscode-languageserver-textdocument"; import { getDenoTypesHintsFromDocument } from "../deno_types"; -export class Hover { - constructor(connection: IConnection, documents: TextDocuments) { +import Plugable from "../plugable"; + +export class Hover implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + documents: TextDocuments + ) { connection.onHover(async (params) => { + if (!this.enabled) return; const { textDocument, position } = params; const document = documents.get(textDocument.uri); diff --git a/server/src/language/references.ts b/server/src/language/references.ts index 229fe1e6..97fb15be 100644 --- a/server/src/language/references.ts +++ b/server/src/language/references.ts @@ -10,9 +10,20 @@ import { URI } from "vscode-uri"; import { getDenoTypesHintsFromDocument } from "../deno_types"; import { ModuleResolver } from "../../../core/module_resolver"; -export class References { - constructor(connection: IConnection, documents: TextDocuments) { +import Plugable from "../plugable"; + +export class References implements Plugable { + setEnabled(enabled: boolean): void { + this.enabled = enabled; + } + + constructor( + private enabled: boolean, + connection: IConnection, + documents: TextDocuments + ) { connection.onReferences(async (params) => { + if (!this.enabled) return; const { textDocument, position } = params; const document = documents.get(textDocument.uri); diff --git a/server/src/plugable.ts b/server/src/plugable.ts new file mode 100644 index 00000000..73cbc4e5 --- /dev/null +++ b/server/src/plugable.ts @@ -0,0 +1,3 @@ +export default interface Plugable { + setEnabled(enabled: boolean): void; +} diff --git a/server/src/server.ts b/server/src/server.ts index d211f501..58263d13 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -32,6 +32,7 @@ import { import { getDenoDir, getDenoDts } from "../../core/deno"; import { pathExists } from "../../core/util"; import { Notification } from "../../core/const"; +import Plugable from "./plugable"; const SERVER_NAME = "Deno Language Server"; process.title = SERVER_NAME; @@ -42,21 +43,25 @@ const connection: IConnection = createConnection( new IPCMessageWriter(process) ); +const g_plugables: Plugable[] = []; + // Create a simple text document manager. The text document manager // supports full document sync only const documents = new TextDocuments(TextDocument); const bridge = new Bridge(connection); const import_enhanced = new ImportCompletionEnhanced(connection, documents); -new DependencyTree(connection, bridge); -new Diagnostics(SERVER_NAME, connection, bridge, documents); -new Definition(connection, documents); -new References(connection, documents); -new DocumentHighlight(connection, documents); -new DocumentFormatting(connection, documents, bridge); -new Hover(connection, documents); -new Completion(connection, documents, import_enhanced); -new CodeLens(connection, documents); +g_plugables.push(new DependencyTree(false, connection, bridge)); +g_plugables.push( + new Diagnostics(false, SERVER_NAME, connection, bridge, documents) +); +g_plugables.push(new Definition(false, connection, documents)); +g_plugables.push(new References(false, connection, documents)); +g_plugables.push(new DocumentHighlight(false, connection, documents)); +g_plugables.push(new DocumentFormatting(false, connection, documents, bridge)); +g_plugables.push(new Hover(false, connection, documents)); +g_plugables.push(new Completion(false, connection, documents, import_enhanced)); +g_plugables.push(new CodeLens(false, connection, documents)); connection.onInitialize( (): InitializeResult => { @@ -120,6 +125,12 @@ connection.onInitialized(async () => { connection.sendNotification(Notification.error, err.message); return; } + + connection.onNotification("_setEnable", (enabled: boolean) => { + g_plugables.forEach((it) => it.setEnabled(enabled)); + connection.console.log(`Deno-LSP ${enabled ? "enabled" : "disabled"}`); + }); + connection.sendNotification(Notification.init, { version: deno.version ? deno.version : undefined, executablePath: deno.executablePath, diff --git a/typescript-deno-plugin/src/config.ts b/typescript-deno-plugin/src/config.ts new file mode 100644 index 00000000..c2b31c70 --- /dev/null +++ b/typescript-deno-plugin/src/config.ts @@ -0,0 +1,28 @@ +import { Configuration } from "../../core/configuration"; +import { + TypescriptDenoPluginConfig, + TypescriptDenoPluginMessage, +} from "../../core/typescript_deno_plugin_config"; + +export { + TypescriptDenoPluginConfig, + TypescriptDenoPluginMessage, +} from "../../core/typescript_deno_plugin_config"; + +export class TypescriptDenoPluginConfigManager { + private project_config = new Configuration(); + private plugin_config?: TypescriptDenoPluginConfig; + + getProjectConfig(): Configuration { + return this.project_config; + } + + getPluginConfig(): TypescriptDenoPluginConfig | undefined { + return this.plugin_config; + } + + update(msg: TypescriptDenoPluginMessage): void { + this.project_config.update(msg.project_config); + this.plugin_config = msg.plugin_config; + } +} diff --git a/typescript-deno-plugin/src/plugin.ts b/typescript-deno-plugin/src/plugin.ts index 2f16ff21..29b1af16 100644 --- a/typescript-deno-plugin/src/plugin.ts +++ b/typescript-deno-plugin/src/plugin.ts @@ -8,7 +8,6 @@ import typescript, { } from "typescript/lib/tsserverlibrary"; import { Logger } from "./logger"; -import { Configuration, ConfigurationField } from "../../core/configuration"; import { getDenoDts } from "../../core/deno"; import { ModuleResolver } from "../../core/module_resolver"; import { CacheModule } from "../../core/deno_cache"; @@ -16,6 +15,11 @@ import { normalizeFilepath, isUntitledDocument } from "../../core/util"; import { normalizeImportStatement } from "../../core/deno_normalize_import_statement"; import { getImportModules } from "../../core/deno_deps"; +import { + TypescriptDenoPluginConfigManager, + TypescriptDenoPluginMessage, +} from "./config"; + const ignoredCompilerOptions: readonly string[] = [ "allowSyntheticDefaultImports", "baseUrl", @@ -77,7 +81,7 @@ const ignoredCompilerOptions: readonly string[] = [ export class DenoPlugin implements typescript.server.PluginModule { // plugin name static readonly PLUGIN_NAME = "typescript-deno-plugin"; - private readonly configurationManager = new Configuration(); + private readonly configurationManager = new TypescriptDenoPluginConfigManager(); // see https://github.com/denoland/deno/blob/2debbdacb935cfe1eb7bb8d1f40a5063b339d90b/js/compiler.ts#L159-L170 private readonly DEFAULT_OPTIONS: typescript.CompilerOptions = { allowJs: true, @@ -154,7 +158,13 @@ export class DenoPlugin implements typescript.server.PluginModule { languageServiceHost.getCompilationSettings = () => { const projectConfig = getCompilationSettings(); - if (!this.configurationManager.config.enable) { + this.logger.info( + `getCompilationSettings: ${JSON.stringify( + this.configurationManager.getPluginConfig() + )}` + ); + + if (!this.configurationManager.getPluginConfig()?.enable) { return projectConfig; } @@ -175,33 +185,51 @@ export class DenoPlugin implements typescript.server.PluginModule { }; languageServiceHost.getScriptFileNames = () => { - const scriptFileNames = getScriptFileNames(); + let scriptFileNames = getScriptFileNames(); - if (!this.configurationManager.config.enable) { + this.logger.info( + `getScriptFileNames: ${ + this.configurationManager.getPluginConfig()?.enable + } ${scriptFileNames}` + ); + + if (!this.configurationManager.getPluginConfig()?.enable) { return scriptFileNames; } // Get typescript declaration File const dtsFiles = [ - getDenoDts(!!this.configurationManager.config.unstable), + getDenoDts( + !!this.configurationManager.getProjectConfig().config.unstable + ), ]; - const iterator = new Set(dtsFiles).entries(); + const iterator = new Set(dtsFiles); + scriptFileNames = [...iterator, ...scriptFileNames]; - for (const [, filepath] of iterator) { - scriptFileNames.push(filepath); - } + this.logger.info( + `getScriptFileNames--dtsFiles: ${JSON.stringify( + dtsFiles + )} getScriptFileNames--scriptFileNames: ${JSON.stringify( + scriptFileNames + )}` + ); return scriptFileNames; }; + languageServiceHost.getProjectVersion = () => { + this.logger.info(`getProjectVersion: ${new Date().toUTCString()}`); + return new Date().toUTCString(); + }; + if (resolveTypeReferenceDirectives) { languageServiceHost.resolveTypeReferenceDirectives = ( typeDirectiveNames: string[], containingFile: string, ...rest ) => { - if (!this.configurationManager.config.enable) { + if (!this.configurationManager.getPluginConfig()?.enable) { return resolveTypeReferenceDirectives( typeDirectiveNames, containingFile, @@ -223,13 +251,12 @@ export class DenoPlugin implements typescript.server.PluginModule { return []; } - const importMapsFilepath = this.configurationManager.config.import_map - ? path.isAbsolute(this.configurationManager.config.import_map) - ? this.configurationManager.config.import_map - : path.resolve( - project.getCurrentDirectory(), - this.configurationManager.config.import_map - ) + const import_map = this.configurationManager.getProjectConfig().config + .import_map; + const importMapsFilepath = import_map + ? path.isAbsolute(import_map) + ? import_map + : path.resolve(project.getCurrentDirectory(), import_map) : undefined; const resolver = ModuleResolver.create( @@ -273,7 +300,7 @@ export class DenoPlugin implements typescript.server.PluginModule { languageService.getSemanticDiagnostics = (filename: string) => { const diagnostics = getSemanticDiagnostics(filename); - if (!this.configurationManager.config.enable) { + if (!this.configurationManager.getPluginConfig()?.enable) { return diagnostics; } @@ -329,7 +356,7 @@ export class DenoPlugin implements typescript.server.PluginModule { preferences ); - if (!this.configurationManager.config.enable) { + if (!this.configurationManager.getPluginConfig()?.enable) { return fixActions; } @@ -369,7 +396,7 @@ export class DenoPlugin implements typescript.server.PluginModule { preferences ); - if (!this.configurationManager.config.enable) { + if (!this.configurationManager.getPluginConfig()?.enable) { return details; } @@ -436,7 +463,13 @@ export class DenoPlugin implements typescript.server.PluginModule { | typescript.ResolvedModuleFull | undefined )[] => { - if (!this.configurationManager.config.enable) { + this.logger.info( + `resolveModuleNames: ${JSON.stringify( + this.configurationManager.getPluginConfig() + )}` + ); + + if (!this.configurationManager.getPluginConfig()?.enable) { return resolveModuleNames(moduleNames, containingFile, ...rest); } @@ -450,13 +483,12 @@ export class DenoPlugin implements typescript.server.PluginModule { // It will cause a series of bugs, so here we get the real file path getRealPath(containingFile); - const importMapsFilepath = this.configurationManager.config.import_map - ? path.isAbsolute(this.configurationManager.config.import_map) - ? this.configurationManager.config.import_map - : path.resolve( - project.getCurrentDirectory(), - this.configurationManager.config.import_map - ) + const import_map = this.configurationManager.getProjectConfig().config + .import_map; + const importMapsFilepath = import_map + ? path.isAbsolute(import_map) + ? import_map + : path.resolve(project.getCurrentDirectory(), import_map) : undefined; const resolver = ModuleResolver.create( @@ -543,9 +575,11 @@ export class DenoPlugin implements typescript.server.PluginModule { }; } - this.configurationManager.resolveFromVscode(projectDirectory); + this.configurationManager + .getProjectConfig() + .resolveFromVscode(projectDirectory); - this.configurationManager.onUpdatedConfig(() => { + this.configurationManager.getProjectConfig().onUpdatedConfig(() => { project.refreshDiagnostics(); project.updateGraph(); languageService.getProgram()?.emit(); @@ -554,7 +588,7 @@ export class DenoPlugin implements typescript.server.PluginModule { return languageService; } - onConfigurationChanged(c: ConfigurationField): void { + onConfigurationChanged(c: TypescriptDenoPluginMessage): void { this.logger.info(`onConfigurationChanged: ${JSON.stringify(c)}`); this.configurationManager.update(c); }