diff --git a/src/activateOmniSharp.ts b/src/activateOmniSharp.ts index 30e25b3345..dd78570ccb 100644 --- a/src/activateOmniSharp.ts +++ b/src/activateOmniSharp.ts @@ -13,6 +13,7 @@ import { activateOmniSharpLanguageServer } from './omnisharp/omnisharpLanguageSe import { EventStream } from './eventStream'; import { razorOptions } from './shared/options'; import { activateRazorExtension } from './razor/razor'; +import { RazorLogger } from './razor/src/razorLogger'; export function activateOmniSharp( context: vscode.ExtensionContext, @@ -39,6 +40,7 @@ export function activateOmniSharp( reporter ); + const razorLogger = new RazorLogger(); let omnisharpRazorPromise: Promise | undefined = undefined; if (!razorOptions.razorDevMode) { omnisharpRazorPromise = activateRazorExtension( @@ -48,7 +50,8 @@ export function activateOmniSharp( reporter, undefined, platformInfo, - /* useOmnisharpServer */ true + /* useOmnisharpServer */ true, + razorLogger ); } diff --git a/src/activateRoslyn.ts b/src/activateRoslyn.ts index 8ea90c8baf..3b2244f845 100644 --- a/src/activateRoslyn.ts +++ b/src/activateRoslyn.ts @@ -25,6 +25,7 @@ import { GlobalBrokeredServiceContainer } from '@microsoft/servicehub-framework' import { SolutionSnapshotProvider } from './lsptoolshost/solutionSnapshot/solutionSnapshotProvider'; import { BuildResultDiagnostics } from './lsptoolshost/diagnostics/buildResultReporterService'; import { getComponentFolder } from './lsptoolshost/extensions/builtInComponents'; +import { RazorLogger } from './razor/src/razorLogger'; export function activateRoslyn( context: vscode.ExtensionContext, @@ -39,6 +40,8 @@ export function activateRoslyn( const roslynLanguageServerEvents = new RoslynLanguageServerEvents(); context.subscriptions.push(roslynLanguageServerEvents); + const razorLogger = new RazorLogger(); + // Activate Razor. Needs to be activated before Roslyn so commands are registered in the correct order. // Otherwise, if Roslyn starts up first, they could execute commands that don't yet exist on Razor's end. // @@ -54,7 +57,8 @@ export function activateRoslyn( reporter, csharpDevkitExtension, platformInfo, - /* useOmnisharpServer */ false + /* useOmnisharpServer */ false, + razorLogger ); // Setup a listener for project initialization complete before we start the server. @@ -73,7 +77,8 @@ export function activateRoslyn( optionStream, csharpChannel, reporter, - roslynLanguageServerEvents + roslynLanguageServerEvents, + razorLogger ); debugSessionTracker.initializeDebugSessionHandlers(context); diff --git a/src/lsptoolshost/activate.ts b/src/lsptoolshost/activate.ts index 22dc536947..789a3b1d48 100644 --- a/src/lsptoolshost/activate.ts +++ b/src/lsptoolshost/activate.ts @@ -29,6 +29,8 @@ import { ProjectContextStatus } from './projectContext/projectContextStatus'; import { RoslynLanguageServer } from './server/roslynLanguageServer'; import { registerCopilotRelatedFilesProvider } from './copilot/relatedFilesProvider'; import { registerCopilotContextProviders } from './copilot/contextProviders'; +import { RazorLogger } from '../razor/src/razorLogger'; +import { registerRazorEndpoints } from './razor/razorEndpoints'; let _channel: vscode.LogOutputChannel; let _traceChannel: vscode.OutputChannel; @@ -43,7 +45,8 @@ export async function activateRoslynLanguageServer( optionObservable: Observable, outputChannel: vscode.LogOutputChannel, reporter: TelemetryReporter, - languageServerEvents: RoslynLanguageServerEvents + languageServerEvents: RoslynLanguageServerEvents, + razorLogger: RazorLogger ): Promise { // Create a channel for outputting general logs from the language server. _channel = outputChannel; @@ -83,6 +86,7 @@ export async function activateRoslynLanguageServer( registerCodeActionFixAllCommands(context, languageServer, _channel); registerRazorCommands(context, languageServer); + registerRazorEndpoints(context, languageServer, razorLogger); registerUnitTestingCommands(context, languageServer); diff --git a/src/lsptoolshost/razor/razorEndpoints.ts b/src/lsptoolshost/razor/razorEndpoints.ts new file mode 100644 index 0000000000..01eeec44aa --- /dev/null +++ b/src/lsptoolshost/razor/razorEndpoints.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RoslynLanguageServer } from '../server/roslynLanguageServer'; +import * as vscode from 'vscode'; +import { LogMessageParams, NotificationType } from 'vscode-languageclient'; +import { RazorLogger } from '../../razor/src/razorLogger'; + +export function registerRazorEndpoints( + context: vscode.ExtensionContext, + languageServer: RoslynLanguageServer, + razorLogger: RazorLogger +) { + const logNotificationType = new NotificationType('razor/log'); + languageServer.registerOnNotificationWithParams(logNotificationType, (params) => + razorLogger.log(params.message, params.type) + ); +} diff --git a/src/lsptoolshost/server/roslynLanguageServer.ts b/src/lsptoolshost/server/roslynLanguageServer.ts index 6716cbdc5d..2c5796563d 100644 --- a/src/lsptoolshost/server/roslynLanguageServer.ts +++ b/src/lsptoolshost/server/roslynLanguageServer.ts @@ -8,7 +8,14 @@ import * as path from 'path'; import * as cp from 'child_process'; import * as uuid from 'uuid'; import * as net from 'net'; -import { LanguageClientOptions, MessageTransports, ProtocolRequestType, ServerOptions } from 'vscode-languageclient'; +import { + LanguageClientOptions, + MessageTransports, + NotificationHandler, + NotificationType, + ProtocolRequestType, + ServerOptions, +} from 'vscode-languageclient'; import { Trace, RequestType, @@ -437,6 +444,13 @@ export class RoslynLanguageServer { this._languageClient.addDisposable(this._languageClient.onNotification(method, handler)); } + public registerOnNotificationWithParams( + type: NotificationType, + handler: NotificationHandler + ) { + this._languageClient.addDisposable(this._languageClient.onNotification(type, handler)); + } + public async registerSolutionSnapshot(token: vscode.CancellationToken): Promise { const response = await this.sendRequest0(RoslynProtocol.RegisterSolutionSnapshotRequest.type, token); if (response) { diff --git a/src/razor/razor.ts b/src/razor/razor.ts index 8223d4815e..0fe92db802 100644 --- a/src/razor/razor.ts +++ b/src/razor/razor.ts @@ -12,6 +12,7 @@ import { EventStream } from '../eventStream'; import TelemetryReporter from '@vscode/extension-telemetry'; import { PlatformInformation } from '../shared/platform'; import { showWarningMessage } from '../shared/observers/utils/showMessage'; +import { RazorLogger } from './src/razorLogger'; export async function activateRazorExtension( context: vscode.ExtensionContext, @@ -20,7 +21,8 @@ export async function activateRazorExtension( vscodeTelemetryReporter: TelemetryReporter, csharpDevkitExtension: vscode.Extension | undefined, platformInfo: PlatformInformation, - useOmnisharpServer: boolean + useOmnisharpServer: boolean, + logger: RazorLogger ) { const razorConfig = vscode.workspace.getConfiguration('razor'); const configuredLanguageServerDir = razorConfig.get('languageServer.directory', ''); @@ -49,6 +51,7 @@ export async function activateRazorExtension( vscodeTelemetryReporter, csharpDevkitExtension, platformInfo, + logger, /* enableProposedApis: */ false ); } diff --git a/src/razor/src/extension.ts b/src/razor/src/extension.ts index 214ec7c3e2..604337a652 100644 --- a/src/razor/src/extension.ts +++ b/src/razor/src/extension.ts @@ -62,6 +62,7 @@ export async function activate( vscodeTelemetryReporter: TelemetryReporter, csharpDevkitExtension: vscode.Extension | undefined, platformInfo: PlatformInformation, + logger: RazorLogger, enableProposedApis = false ) { const razorTelemetryReporter = new RazorTelemetryReporter(eventStream); @@ -69,8 +70,6 @@ export async function activate( create: () => new vscode.EventEmitter(), }; - const logger = new RazorLogger(eventEmitterFactory); - try { const razorOptions: RazorLanguageServerOptions = resolveRazorLanguageServerOptions( vscodeType, @@ -82,6 +81,10 @@ export async function activate( // TODO: We still need a document manager for Html, so need to do _some_ of the below, just not sure what yet, // and it needs to be able to take a roslynLanguageServerClient instead of a razorLanguageServerClient I guess. + logger.logVerbose( + 'Razor cohosting is enabled, skipping language server activation. No rzls process will be created.' + ); + return; } diff --git a/src/razor/src/razorLogger.ts b/src/razor/src/razorLogger.ts index 985f5af3db..f0947468de 100644 --- a/src/razor/src/razorLogger.ts +++ b/src/razor/src/razorLogger.ts @@ -7,8 +7,8 @@ import * as fs from 'fs'; import * as path from 'path'; import * as vscodeAdapter from './vscodeAdapter'; import * as vscode from 'vscode'; -import { IEventEmitterFactory } from './IEventEmitterFactory'; import { RazorLanguageServerClient } from './razorLanguageServerClient'; +import { MessageType } from 'vscode-languageserver-protocol'; export class RazorLogger implements vscodeAdapter.Disposable { public static readonly logName = 'Razor Log'; @@ -19,9 +19,9 @@ export class RazorLogger implements vscodeAdapter.Disposable { private readonly onLogEmitter: vscodeAdapter.EventEmitter; - constructor(eventEmitterFactory: IEventEmitterFactory) { + constructor() { this.outputChannel = vscode.window.createOutputChannel(vscode.l10n.t('Razor Log'), { log: true }); - this.onLogEmitter = eventEmitterFactory.create(); + this.onLogEmitter = new vscode.EventEmitter(); this.processTraceLevel(); this.outputChannel.onDidChangeLogLevel(async () => { @@ -96,6 +96,24 @@ export class RazorLogger implements vscodeAdapter.Disposable { } } + public log(message: string, level: MessageType) { + switch (level) { + case MessageType.Error: + this.logError(message, new Error(message)); + break; + case MessageType.Warning: + this.logWarning(message); + break; + case MessageType.Info: + this.logMessage(message); + break; + case MessageType.Debug: + case MessageType.Log: + default: + this.logVerbose(message); + } + } + public dispose() { this.outputChannel.dispose(); }