diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index e8fda5178..6d83b6e92 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -1,10 +1,12 @@ using System; using System.Diagnostics; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OmniSharp.Extensions.LanguageServer; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Server; +using Serilog; namespace SampleServer { @@ -22,19 +24,56 @@ static async Task MainAsync(string[] args) // await Task.Delay(100); // } + Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day) + .CreateLogger(); + + Log.Logger.Information("This only goes file..."); + var server = await LanguageServer.From(options => options .WithInput(Console.OpenStandardInput()) .WithOutput(Console.OpenStandardOutput()) - .WithLoggerFactory(new LoggerFactory()) + .ConfigureLogging(x => x.AddSerilog()) .AddDefaultLoggingProvider() - .WithMinimumLogLevel(LogLevel.Trace) .WithHandler() .WithHandler() .WithHandler() + .WithServices(services => { + services.AddSingleton(provider => { + var loggerFactory = provider.GetService(); + var logger = loggerFactory.CreateLogger(); + + logger.LogInformation("Configuring"); + + return new Foo(logger); + }); + }).OnInitialize((s, request) => { + var serviceProvider = s.Services; + var foo = serviceProvider.GetService(); + + return Task.CompletedTask; + }) ); await server.WaitForExit; } } + + internal class Foo + { + private readonly ILogger _logger; + + public Foo(ILogger logger) + { + logger.LogInformation("inside ctor"); + _logger = logger; + } + + public void SayFoo() + { + _logger.LogInformation("Fooooo!"); + } + } } diff --git a/sample/SampleServer/SampleServer.csproj b/sample/SampleServer/SampleServer.csproj index afcea196b..42a242247 100644 --- a/sample/SampleServer/SampleServer.csproj +++ b/sample/SampleServer/SampleServer.csproj @@ -3,13 +3,15 @@ Exe false - netcoreapp2.0 + netcoreapp2.1 win7-x64 + + diff --git a/sample/SampleServer/TextDocumentHandler.cs b/sample/SampleServer/TextDocumentHandler.cs index 9e72f1b9a..df3703ce2 100644 --- a/sample/SampleServer/TextDocumentHandler.cs +++ b/sample/SampleServer/TextDocumentHandler.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using OmniSharp.Extensions.Embedded.MediatR; using OmniSharp.Extensions.LanguageServer; using OmniSharp.Extensions.LanguageServer.Protocol; @@ -15,7 +16,7 @@ namespace SampleServer { class TextDocumentHandler : ITextDocumentSyncHandler { - private readonly OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer _router; + private readonly ILogger _logger; private readonly DocumentSelector _documentSelector = new DocumentSelector( new DocumentFilter() { @@ -25,19 +26,17 @@ class TextDocumentHandler : ITextDocumentSyncHandler private SynchronizationCapability _capability; - public TextDocumentHandler(OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer router) + public TextDocumentHandler(ILogger logger, Foo foo) { - _router = router; + _logger = logger; + foo.SayFoo(); } public TextDocumentSyncKind Change { get; } = TextDocumentSyncKind.Full; public Task Handle(DidChangeTextDocumentParams notification, CancellationToken token) { - _router.Window.LogMessage(new LogMessageParams() { - Type = MessageType.Log, - Message = "Hello World!!!!" - }); + _logger.LogInformation("Hello world!"); return Unit.Task; } @@ -57,10 +56,7 @@ public void SetCapability(SynchronizationCapability capability) public async Task Handle(DidOpenTextDocumentParams notification, CancellationToken token) { await Task.Yield(); - _router.Window.LogMessage(new LogMessageParams() { - Type = MessageType.Log, - Message = "Hello World!!!!" - }); + _logger.LogInformation("Hello world!"); return Unit.Value; } diff --git a/src/JsonRpc/RequestRouterBase.cs b/src/JsonRpc/RequestRouterBase.cs index ddfe0aaf5..99bf1fc8d 100644 --- a/src/JsonRpc/RequestRouterBase.cs +++ b/src/JsonRpc/RequestRouterBase.cs @@ -148,7 +148,7 @@ public virtual async Task RouteRequest(TDescriptor descriptor, Re return new JsonRpc.Client.Response(request.Id, responseValue, request); } - catch (TaskCanceledException e) + catch (TaskCanceledException) { _logger.LogDebug("Request {Id} was cancelled", id); return new RequestCancelled(); diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 4f82627d6..ff5c23246 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -89,12 +89,11 @@ public static async Task From(LanguageServerOptions options, Ca /// public static ILanguageServer PreInit(LanguageServerOptions options) { - var server = new LanguageServer( + return new LanguageServer( options.Input, options.Output, options.Reciever, options.RequestProcessIdentifier, - options.LoggerFactory, options.Serializer, options.Services, options.HandlerTypes.Select(x => x.Assembly) @@ -106,13 +105,10 @@ public static ILanguageServer PreInit(LanguageServerOptions options) options.TextDocumentIdentifiers, options.TextDocumentIdentifierTypes, options.InitializeDelegates, - options.InitializedDelegates + options.InitializedDelegates, + options.LoggingBuilderAction, + options.AddDefaultLoggingProvider ); - - if (options.AddDefaultLoggingProvider) - options.LoggerFactory.AddProvider(new LanguageServerLoggerProvider(server)); - - return server; } internal LanguageServer( @@ -120,7 +116,6 @@ internal LanguageServer( Stream output, ILspReciever reciever, IRequestProcessIdentifier requestProcessIdentifier, - ILoggerFactory loggerFactory, ISerializer serializer, IServiceCollection services, IEnumerable assemblies, @@ -131,11 +126,22 @@ internal LanguageServer( IEnumerable textDocumentIdentifiers, IEnumerable textDocumentIdentifierTypes, IEnumerable initializeDelegates, - IEnumerable initializedDelegates) + IEnumerable initializedDelegates, + Action loggingBuilderAction, + bool addDefaultLoggingProvider) { var outputHandler = new OutputHandler(output, serializer); - services.AddLogging(); + services.AddLogging(builder => + { + loggingBuilderAction(builder); + + if (addDefaultLoggingProvider) + { + builder.AddProvider(new LanguageServerLoggerProvider(this)); + } + }); + _reciever = reciever; _serializer = serializer; _supportedCapabilities = new SupportedCapabilities(); @@ -153,7 +159,7 @@ internal LanguageServer( services.AddSingleton(requestProcessIdentifier); services.AddSingleton(reciever); services.AddSingleton(reciever); - services.AddSingleton(loggerFactory); + foreach (var item in handlers) { services.AddSingleton(item); @@ -209,6 +215,12 @@ internal LanguageServer( _exitHandler = new ServerExitHandler(_shutdownHandler); + // We need to at least create Window here in case any handler does loggin in their constructor + Document = new LanguageServerDocument(_responseRouter); + Client = new LanguageServerClient(_responseRouter); + Window = new LanguageServerWindow(_responseRouter); + Workspace = new LanguageServerWorkspace(_responseRouter); + _disposable.Add( AddHandlers(this, _shutdownHandler, _exitHandler, new CancelRequestHandler(_requestRouter)) ); @@ -226,12 +238,6 @@ internal LanguageServer( { _disposable.Add(_collection.Add(name, handlerFunc(_serviceProvider))); } - - - Document = new LanguageServerDocument(_responseRouter); - Client = new LanguageServerClient(_responseRouter); - Window = new LanguageServerWindow(_responseRouter); - Workspace = new LanguageServerWorkspace(_responseRouter); } public ILanguageServerDocument Document { get; } diff --git a/src/Server/LanguageServerOptions.cs b/src/Server/LanguageServerOptions.cs index fc51563cd..c5a190dc6 100644 --- a/src/Server/LanguageServerOptions.cs +++ b/src/Server/LanguageServerOptions.cs @@ -22,8 +22,6 @@ public LanguageServerOptions() public Stream Input { get; set; } public Stream Output { get; set; } - public LogLevel MinimumLogLevel { get; set; } = LogLevel.Information; - public ILoggerFactory LoggerFactory { get; set; } = new LoggerFactory(); public ISerializer Serializer { get; set; } = Protocol.Serialization.Serializer.Instance; public IRequestProcessIdentifier RequestProcessIdentifier { get; set; } = new RequestProcessIdentifier(); public ILspReciever Reciever { get; set; } = new LspReciever(); @@ -36,6 +34,7 @@ public LanguageServerOptions() internal List TextDocumentIdentifierTypes { get; set; } = new List(); internal List HandlerAssemblies { get; set; } = new List(); internal bool AddDefaultLoggingProvider { get; set; } + internal Action LoggingBuilderAction { get; set; } = new Action(_ => { }); internal readonly List InitializeDelegates = new List(); internal readonly List InitializedDelegates = new List(); diff --git a/src/Server/LanguageServerOptionsExtensions.cs b/src/Server/LanguageServerOptionsExtensions.cs index 055cd6215..1113fdc9d 100644 --- a/src/Server/LanguageServerOptionsExtensions.cs +++ b/src/Server/LanguageServerOptionsExtensions.cs @@ -22,18 +22,6 @@ public static LanguageServerOptions WithOutput(this LanguageServerOptions option return options; } - public static LanguageServerOptions WithMinimumLogLevel(this LanguageServerOptions options, LogLevel logLevel) - { - options.MinimumLogLevel = logLevel; - return options; - } - - public static LanguageServerOptions WithLoggerFactory(this LanguageServerOptions options, ILoggerFactory loggerFactory) - { - options.LoggerFactory = loggerFactory; - return options; - } - public static LanguageServerOptions WithRequestProcessIdentifier(this LanguageServerOptions options, IRequestProcessIdentifier requestProcessIdentifier) { options.RequestProcessIdentifier = requestProcessIdentifier; @@ -109,5 +97,11 @@ public static LanguageServerOptions OnInitialized(this LanguageServerOptions opt options.InitializedDelegates.Add(@delegate); return options; } + + public static LanguageServerOptions ConfigureLogging(this LanguageServerOptions options, Action builderAction) + { + options.LoggingBuilderAction = builderAction; + return options; + } } } diff --git a/test/Lsp.Tests/LanguageServerTests.cs b/test/Lsp.Tests/LanguageServerTests.cs index 28012c9b9..1b9231ec3 100644 --- a/test/Lsp.Tests/LanguageServerTests.cs +++ b/test/Lsp.Tests/LanguageServerTests.cs @@ -37,10 +37,10 @@ public async Task Works_With_IWorkspaceSymbolsHandler() var serverStart = LanguageServer.From(x => x //.WithHandler(handler) .WithInput(process.ClientOutputStream) - .WithOutput(process.ClientInputStream) - .WithLoggerFactory(LoggerFactory) - .AddDefaultLoggingProvider() - .WithMinimumLogLevel(LogLevel.Trace), + .WithOutput(process.ClientInputStream), + //.WithLoggerFactory(LoggerFactory) + //.AddDefaultLoggingProvider() + //.WithMinimumLogLevel(LogLevel.Trace), cts.Token ); @@ -63,9 +63,9 @@ public async Task GH141_CrashesWithEmptyInitializeParams() var server = LanguageServer.PreInit(x => x .WithInput(process.ClientOutputStream) .WithOutput(process.ClientInputStream) - .WithLoggerFactory(LoggerFactory) - .AddDefaultLoggingProvider() - .WithMinimumLogLevel(LogLevel.Trace) + //.WithLoggerFactory(LoggerFactory) + //.AddDefaultLoggingProvider() + //.WithMinimumLogLevel(LogLevel.Trace) .AddHandlers(TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp")) ) as IRequestHandler; diff --git a/vscode-testextension/.vscode/tasks.json b/vscode-testextension/.vscode/tasks.json index d31b15910..67ef04203 100644 --- a/vscode-testextension/.vscode/tasks.json +++ b/vscode-testextension/.vscode/tasks.json @@ -8,23 +8,14 @@ // A task runner that calls a custom npm script that compiles the extension. { - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isWatching": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" -} \ No newline at end of file + "version": "2.0.0", + "tasks": [ + { + "label": "npm", + "command": "npm", + "args": ["run", "compile", "--loglevel", "silent"], + "type": "shell", + "problemMatcher": "$tsc-watch" + } + ] +} diff --git a/vscode-testextension/src/extension.ts b/vscode-testextension/src/extension.ts index a29f2c5c6..7856d1395 100644 --- a/vscode-testextension/src/extension.ts +++ b/vscode-testextension/src/extension.ts @@ -20,11 +20,10 @@ import { Trace } from "vscode-jsonrpc"; export function activate(context: ExtensionContext) { // The server is implemented in node - // let serverExe = 'dotnet'; + let serverExe = 'dotnet'; // let serverExe = 'D:\\Development\\Omnisharp\\csharp-language-server-protocol\\sample\\SampleServer\\bin\\Debug\\netcoreapp2.0\\win7-x64\\SampleServer.exe'; - let serverExe = - "D:/Development/Omnisharp/omnisharp-roslyn/artifacts/publish/OmniSharp.Stdio.Driver/win7-x64/OmniSharp.exe"; + // let serverExe = "D:/Development/Omnisharp/omnisharp-roslyn/artifacts/publish/OmniSharp.Stdio.Driver/win7-x64/OmniSharp.exe"; // The debug options for the server // let debugOptions = { execArgv: ['-lsp', '-d' };5 @@ -32,9 +31,9 @@ export function activate(context: ExtensionContext) { // Otherwise the run options are used let serverOptions: ServerOptions = { // run: { command: serverExe, args: ['-lsp', '-d'] }, - run: { command: serverExe, args: ["-lsp"] }, + run: { command: serverExe, args: ["C:/src/gh/csharp-language-server-protocol/sample/SampleServer/bin/Debug/netcoreapp2.1/win7-x64/SampleServer.dll"] }, // debug: { command: serverExe, args: ['-lsp', '-d'] } - debug: { command: serverExe, args: ["-lsp"] } + debug: { command: serverExe, args: ["C:/src/gh/csharp-language-server-protocol/sample/SampleServer/bin/Debug/netcoreapp2.1/win7-x64/SampleServer.dll"] } }; // Options to control the language client @@ -65,7 +64,7 @@ export function activate(context: ExtensionContext) { serverOptions, clientOptions ); - // client.trace = Trace.Verbose; + client.trace = Trace.Verbose; client.clientOptions.errorHandler; let disposable = client.start();