@@ -26,11 +26,15 @@ public void Log<TState>(
2626        Func < TState ,  Exception ? ,  string >  formatter 
2727    ) 
2828    { 
29+         if  ( responseRouter  is  null ) 
30+         { 
31+             throw  new  InvalidOperationException ( "Log received without a valid responseRouter dependency. This is a bug, please report it." ) ; 
32+         } 
2933        // Any Omnisharp or trace logs are directly LSP protocol related and we send them to the trace channel 
3034        // TODO: Dynamically adjust if SetTrace is reported 
31-         // BUG: There is an omnisharp filter incorrectly filtering this. As a workaround we will use logMessage. 
35+         // BUG: There is an omnisharp filter incorrectly filtering this. As a workaround we will use logMessage for now . 
3236        //  https://github.com/OmniSharp/csharp-language-server-protocol/issues/1390 
33-         // if (categoryName.StartsWith("OmniSharp") || logLevel == LogLevel.Trace)  
37+         // 
3438        // { 
3539        //     // Everything with omnisharp goes directly to trace 
3640        //     string eventMessage = string.Empty; 
@@ -47,22 +51,54 @@ public void Log<TState>(
4751        //     }; 
4852        //     responseRouter.Client.LogTrace(trace); 
4953        // } 
50-         if  ( TryGetMessageType ( logLevel ,  out  MessageType  messageType ) ) 
54+ 
55+         // Drop all omnisharp messages to trace. This isn't a MEL filter because it's specific only to this provider. 
56+         if  ( categoryName . StartsWith ( "OmniSharp." ,  StringComparison . OrdinalIgnoreCase ) ) 
57+         { 
58+             logLevel  =  LogLevel . Trace ; 
59+         } 
60+ 
61+         ( MessageType  messageType ,  string  messagePrepend )  =  GetMessageInfo ( logLevel ) ; 
62+ 
63+         // The vscode-languageserver-node client doesn't support LogOutputChannel as of 2024-11-24 and also doesn't 
64+         // provide a way to middleware the incoming log messages, so our output channel has no idea what the logLevel 
65+         // is. As a workaround, we send the severity in-line with the message for the client to parse. 
66+         // BUG: https://github.com/microsoft/vscode-languageserver-node/issues/1116 
67+         if  ( responseRouter . Client ? . ClientSettings ? . ClientInfo ? . Name  ==  "Visual Studio Code" ) 
5168        { 
52-             LogMessageParams   logMessage   =   new ( ) 
69+             messagePrepend   =   logLevel   switch 
5370            { 
54-                 Type  =  messageType , 
55-                 // TODO: Add Critical and Debug delineations 
56-                 Message  =  categoryName  +  ": "  +  formatter ( state ,  exception )  + 
57-                     ( exception  !=  null  ?  " - "  +  exception  :  "" )  +  " | "  + 
58-                     //Hopefully this isn't too expensive in the long run 
59-                     FormatState ( state ,  exception ) 
71+                 LogLevel . Critical  =>  "<Error> CRITICAL: " , 
72+                 LogLevel . Error  =>  "<Error>" , 
73+                 LogLevel . Warning  =>  "<Warning>" , 
74+                 LogLevel . Information  =>  "<Info>" , 
75+                 LogLevel . Debug  =>  "<Debug>" , 
76+                 LogLevel . Trace  =>  "<Trace>" , 
77+                 _ =>  string . Empty 
6078            } ; 
61-             responseRouter . Window . Log ( logMessage ) ; 
6279        } 
63-     } 
6480
81+         LogMessageParams  logMessage  =  new ( ) 
82+         { 
83+             Type  =  messageType , 
84+             Message  =  messagePrepend  +  categoryName  +  ": "  +  formatter ( state ,  exception )  + 
85+                 ( exception  !=  null  ?  " - "  +  exception  :  "" )  +  " | "  + 
86+                 //Hopefully this isn't too expensive in the long run 
87+                 FormatState ( state ,  exception ) 
88+         } ; 
89+         responseRouter . Window . Log ( logMessage ) ; 
90+     } 
6591
92+     /// <summary> 
93+     /// Formats the state object into a string for logging. 
94+     /// </summary> 
95+     /// <remarks> 
96+     /// This is copied from Omnisharp, we can probably do better. 
97+     /// </remarks> 
98+     /// <typeparam name="TState"></typeparam> 
99+     /// <param name="state"></param> 
100+     /// <param name="exception"></param> 
101+     /// <returns></returns> 
66102    private  static string  FormatState < TState > ( TState  state ,  Exception ?  exception ) 
67103    { 
68104        return  state  switch 
@@ -72,29 +108,20 @@ private static string FormatState<TState>(TState state, Exception? exception)
72108        } ; 
73109    } 
74110
75-     private  static bool  TryGetMessageType ( LogLevel  logLevel ,  out  MessageType  messageType ) 
76-     { 
77-         switch  ( logLevel ) 
111+     /// <summary> 
112+     /// Maps MEL log levels to LSP message types 
113+     /// </summary> 
114+     private  static ( MessageType  messageType ,  string  messagePrepend )  GetMessageInfo ( LogLevel  logLevel ) 
115+         =>  logLevel  switch 
78116        { 
79-             case  LogLevel . Critical : 
80-             case  LogLevel . Error : 
81-                 messageType  =  MessageType . Error ; 
82-                 return  true ; 
83-             case  LogLevel . Warning : 
84-                 messageType  =  MessageType . Warning ; 
85-                 return  true ; 
86-             case  LogLevel . Information : 
87-                 messageType  =  MessageType . Info ; 
88-                 return  true ; 
89-             case  LogLevel . Debug : 
90-             case  LogLevel . Trace : 
91-                 messageType  =  MessageType . Log ; 
92-                 return  true ; 
93-         } 
94- 
95-         messageType  =  MessageType . Log ; 
96-         return  false ; 
97-     } 
117+             LogLevel . Critical  =>  ( MessageType . Error ,  "Critical: " ) , 
118+             LogLevel . Error  =>  ( MessageType . Error ,  string . Empty ) , 
119+             LogLevel . Warning  =>  ( MessageType . Warning ,  string . Empty ) , 
120+             LogLevel . Information  =>  ( MessageType . Info ,  string . Empty ) , 
121+             LogLevel . Debug  =>  ( MessageType . Log ,  string . Empty ) , 
122+             LogLevel . Trace  =>  ( MessageType . Log ,  "Trace: " ) , 
123+             _ =>  throw  new  ArgumentOutOfRangeException ( nameof ( logLevel ) ,  logLevel ,  null ) 
124+         } ; 
98125} 
99126
100127internal  class  LanguageServerLoggerProvider ( ILanguageServerFacade  languageServer )  :  ILoggerProvider 
0 commit comments