diff --git a/packages/_integrationTests/src/ExtensionApi.mts b/packages/_integrationTests/src/ExtensionApi.mts index d06be6f92..7d048f50f 100644 --- a/packages/_integrationTests/src/ExtensionApi.mts +++ b/packages/_integrationTests/src/ExtensionApi.mts @@ -1,3 +1,3 @@ export type { OnSpellCheckDocumentStep } from '../../_server/dist/api.cjs'; -export type { CSpellClient } from '../../client/dist/client/index.mjs'; -export type { ExtensionApi } from '../../client/dist/extensionApi.mjs'; +export type { CSpellClient } from '../../client/out/client/index.mjs'; +export type { ExtensionApi } from '../../client/out/extensionApi.mjs'; diff --git a/packages/client/src/configWatcher.mts b/packages/client/src/configWatcher.mts index 9058e5570..10a201f54 100644 --- a/packages/client/src/configWatcher.mts +++ b/packages/client/src/configWatcher.mts @@ -1,9 +1,10 @@ import { opMap, pipe } from '@cspell/cspell-pipe/sync'; -import { defaultConfigFilenames } from 'cspell-lib'; import { createDisposableList } from 'utils-disposables'; import type { Disposable, Event, Uri } from 'vscode'; import * as vscode from 'vscode'; +import { defaultConfigFilenames } from './defaultConfigFilenames.mjs'; + export interface ConfigWatcher extends Disposable { on: Event; onDidChangeConfig: Event; diff --git a/packages/client/src/defaultConfigFilenames.mts b/packages/client/src/defaultConfigFilenames.mts new file mode 100644 index 000000000..2329e5a98 --- /dev/null +++ b/packages/client/src/defaultConfigFilenames.mts @@ -0,0 +1,52 @@ +export const defaultConfigFilenames = [ + 'package.json', + '.cspell.json', + 'cspell.json', + '.cSpell.json', + 'cSpell.json', + '.cspell.jsonc', + 'cspell.jsonc', + '.vscode/cspell.json', + '.vscode/cSpell.json', + '.vscode/.cspell.json', + '.cspell.config.json', + '.cspell.config.jsonc', + '.cspell.config.yaml', + '.cspell.config.yml', + 'cspell.config.json', + 'cspell.config.jsonc', + 'cspell.config.yaml', + 'cspell.config.yml', + 'cspell.config.mjs', + 'cspell.config.cjs', + 'cspell.config.js', + '.cspell.config.mjs', + '.cspell.config.cjs', + '.cspell.config.js', + '.cspell.yaml', + '.cspell.yml', + 'cspell.yaml', + 'cspell.yml', + '.config/.cspell.json', + '.config/cspell.json', + '.config/.cSpell.json', + '.config/cSpell.json', + '.config/.cspell.jsonc', + '.config/cspell.jsonc', + '.config/cspell.config.json', + '.config/cspell.config.jsonc', + '.config/cspell.config.yaml', + '.config/cspell.config.yml', + '.config/cspell.config.mjs', + '.config/cspell.config.cjs', + '.config/cspell.config.js', + '.config/.cspell.config.json', + '.config/.cspell.config.jsonc', + '.config/.cspell.config.yaml', + '.config/.cspell.config.yml', + '.config/.cspell.config.mjs', + '.config/.cspell.config.cjs', + '.config/.cspell.config.js', + '.config/cspell.yaml', + '.config/cspell.yml', +] as const; diff --git a/packages/client/src/defaultConfigFilenames.test.mts b/packages/client/src/defaultConfigFilenames.test.mts new file mode 100644 index 000000000..a022873bb --- /dev/null +++ b/packages/client/src/defaultConfigFilenames.test.mts @@ -0,0 +1,10 @@ +import { defaultConfigFilenames as cspellDefaultConfigFilenames } from 'cspell-lib'; +import { describe, expect, test } from 'vitest'; + +import { defaultConfigFilenames } from './defaultConfigFilenames.mjs'; + +describe('defaultConfigFilenames', () => { + test('defaultConfigFilenames', () => { + expect(new Set(defaultConfigFilenames)).toEqual(new Set(cspellDefaultConfigFilenames)); + }); +}); diff --git a/packages/client/src/extension.mts b/packages/client/src/extension.mts index b8a74fb6d..28594226a 100644 --- a/packages/client/src/extension.mts +++ b/packages/client/src/extension.mts @@ -43,21 +43,34 @@ let currLogLevel: CSpellSettings['logLevel'] = undefined; modules.init(); export function activate(context: ExtensionContext): Promise { - performance.mark('cspell_activate_start'); - di.set('extensionContext', context); - const eventLogger = createEventLogger(context.globalStorageUri); - di.set('eventLogger', eventLogger); - eventLogger.logActivate(); + try { + performance.mark('cspell_activate_start'); + di.set('extensionContext', context); + const eventLogger = createEventLogger(context.globalStorageUri); + di.set('eventLogger', eventLogger); + eventLogger.logActivate(); - setOutputChannelLogLevel(); + setOutputChannelLogLevel(); - const eIssueTracker = new vscode.EventEmitter(); - const pIssueTracker = new Promise((resolve) => eIssueTracker.event(resolve)); + const eIssueTracker = new vscode.EventEmitter(); + const pIssueTracker = new Promise((resolve) => eIssueTracker.event(resolve)); - activateIssueViewer(context, pIssueTracker); - activateFileIssuesViewer(context, pIssueTracker); + performance.mark('activateIssueViewer'); + activateIssueViewer(context, pIssueTracker); + performance.mark('activateFileIssuesViewer'); + activateFileIssuesViewer(context, pIssueTracker); - return _activate(context, eIssueTracker); + performance.mark('start_async_activate'); + return _activate(context, eIssueTracker).catch((e) => { + throw activationError(e); + }); + } catch (e) { + throw activationError(e); + } +} + +function activationError(e: unknown) { + return new Error(`Failed to activate: (${performance.getLastEventName()}) ${e}`, { cause: e }); } async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventEmitter): Promise { @@ -65,6 +78,7 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE const dLogger = bindLoggerToOutput(logOutput); // Get the cSpell Client + performance.mark('create client'); const client = await CSpellClient.create(context); context.subscriptions.push(client, logOutput, dLogger); @@ -84,10 +98,13 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE }); } + performance.mark('ExtensionRegEx.activate'); ExtensionRegEx.activate(context, client); // Start the client. + performance.mark('start client'); await client.start(); + performance.mark('start IssueTracker'); const issueTracker = new IssueTracker(client); di.set('issueTracker', issueTracker); eIssueTracker.fire(issueTracker); @@ -112,6 +129,7 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE triggerGetSettings(); } + performance.mark('createConfigWatcher'); const configWatcher = createConfigWatcher(); // console.log('config files: %o', await configWatcher.scanWorkspaceForConfigFiles()); const decorator = new SpellingIssueDecorator(context, issueTracker); @@ -125,6 +143,8 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE 'cSpell.createCSpellTerminal': createTerminal, }; + performance.mark('register'); + // Push the disposable to the context's subscriptions so that the // client can be deactivated on extension deactivation context.subscriptions.push( @@ -161,6 +181,7 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE client.onBlockFile(notifyUserOfBlockedFile), ); + performance.mark('registerCspellInlineCompletionProviders'); await registerCspellInlineCompletionProviders(context.subscriptions).catch(() => undefined); function handleOnDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) { @@ -240,6 +261,8 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE const getConfigurationForDocument = (doc: vscode.TextDocument, fields: ConfigFieldSelector) => client.getConfigurationForDocument(doc, fields); + performance.mark('setup Extension API'); + const server = { registerConfig, triggerGetSettings, @@ -263,6 +286,7 @@ async function _activate(context: ExtensionContext, eIssueTracker: vscode.EventE disableCurrentLanguage: commands.disableCurrentFileType, } as const satisfies ExtensionApi & { getConfigurationForDocument: typeof getConfigurationForDocument }; + performance.mark('activateWebview'); activateWebview(context); performance.mark('cspell_activate_end'); diff --git a/packages/client/src/util/perf.ts b/packages/client/src/util/perf.ts index f02ac5fa7..b21476e78 100644 --- a/packages/client/src/util/perf.ts +++ b/packages/client/src/util/perf.ts @@ -34,6 +34,14 @@ export class PerformanceTimeline { this.addEvent(event); } + getLastEvent(): TimeLineEvent { + return this.timeLine[this.timeLine.length - 1]; + } + + getLastEventName(): string { + return this.getLastEvent().name || ''; + } + private addEvent(event: TimeLineEvent) { this.timeLine.push(event); this.timeLineEvents.set(event.name, event); diff --git a/packages/client/tsconfig.api.json b/packages/client/tsconfig.api.json index 1bd352e74..fad5d3326 100644 --- a/packages/client/tsconfig.api.json +++ b/packages/client/tsconfig.api.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "outDir": "./out", "emitDeclarationOnly": true }, "files": ["src/extensionApi.mts"] diff --git a/packages/client/tsconfig.test.json b/packages/client/tsconfig.test.json index 7275d0a67..2cacfbd3d 100644 --- a/packages/client/tsconfig.test.json +++ b/packages/client/tsconfig.test.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "noEmit": true, "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "temp/dist"