diff --git a/AnyText/AnyText.Lsp/AnyTextJsonRpcServerUtil.cs b/AnyText/AnyText.Lsp/AnyTextJsonRpcServerUtil.cs
index c4ad0986..634b3313 100644
--- a/AnyText/AnyText.Lsp/AnyTextJsonRpcServerUtil.cs
+++ b/AnyText/AnyText.Lsp/AnyTextJsonRpcServerUtil.cs
@@ -11,8 +11,6 @@ namespace NMF.AnyText
///
public static class AnyTextJsonRpcServerUtil
{
- private static readonly TraceSource _traceSource = CreateTraceSource();
-
///
/// Creates a StreamJSON RPC object for the given transport
///
@@ -22,7 +20,6 @@ public static class AnyTextJsonRpcServerUtil
public static JsonRpc CreateServer(WebSocket webSocket, ILspServer server)
{
var rpc = new JsonRpc(new WebSocketMessageHandler(webSocket, CreateFormatter()));
- rpc.TraceSource = _traceSource;
rpc.AddLocalRpcTarget(server, CreateTargetOptions());
return rpc;
}
@@ -36,7 +33,6 @@ public static JsonRpc CreateServer(WebSocket webSocket, ILspServer server)
public static JsonRpc CreateServer(IDuplexPipe pipe, ILspServer server)
{
var rpc = new JsonRpc(new HeaderDelimitedMessageHandler(pipe, CreateFormatter()));
- rpc.TraceSource = _traceSource;
rpc.AddLocalRpcTarget(server, CreateTargetOptions());
return rpc;
}
@@ -50,7 +46,6 @@ public static JsonRpc CreateServer(IDuplexPipe pipe, ILspServer server)
public static JsonRpc CreateServer(Stream stream, ILspServer server)
{
var rpc = new JsonRpc(new HeaderDelimitedMessageHandler(stream, CreateFormatter()));
- rpc.TraceSource = _traceSource;
rpc.AddLocalRpcTarget(server, CreateTargetOptions());
return rpc;
}
@@ -62,7 +57,6 @@ public static JsonRpc CreateServer(Stream stream, ILspServer server)
public static JsonRpc CreateServer(Stream stream)
{
var rpc = new JsonRpc(new HeaderDelimitedMessageHandler(stream, CreateFormatter()));
- rpc.TraceSource = _traceSource;
return rpc;
}
@@ -84,15 +78,20 @@ private static JsonRpcTargetOptions CreateTargetOptions()
EventNameTransform = name => name.ToLowerInvariant()
};
}
-
- private static TraceSource CreateTraceSource()
+ ///
+ /// Creates and configures a instance for logging trace information.
+ ///
+ /// The SourceLevel used to filter messages by type and severity. Defaults to .
+ /// A instance configured for the specified logging level.
+ public static TraceSource CreateTraceSource(SourceLevels sourceLevels = SourceLevels.All)
{
- var traceSource = new TraceSource("LSP", SourceLevels.All);
- // use error stream such that VS Code can see the stdout
- traceSource.Listeners.Add(new ConsoleTraceListener(true));
+ var traceSource = new TraceSource("LSP", sourceLevels);
+ // Use error stream (stderr) so that VS Code can capture the output
+ traceSource.Listeners.Add(new ConsoleTraceListener(useErrorStream: true));
return traceSource;
}
+
private static IJsonRpcMessageFormatter CreateFormatter()
{
return new JsonMessageFormatter();
diff --git a/AnyText/AnyText.Lsp/ILspServer.cs b/AnyText/AnyText.Lsp/ILspServer.cs
index 0a0cb29c..5919e241 100644
--- a/AnyText/AnyText.Lsp/ILspServer.cs
+++ b/AnyText/AnyText.Lsp/ILspServer.cs
@@ -41,5 +41,13 @@ public InitializeResult Initialize(
[JsonRpcMethod(Methods.ShutdownName)]
void Shutdown();
+
+ ///
+ /// Handles the */setTrace request from the client. This is used to set the trace setting of the server.
+ ///
+ /// The JSON token containing the parameters of the request. (SetTraceParams)
+ [JsonRpcMethod(MethodConstants.SetTrace)]
+ public void SetTrace(JToken arg);
+
}
}
\ No newline at end of file
diff --git a/AnyText/AnyText.Lsp/LspServer.Diagnostics.cs b/AnyText/AnyText.Lsp/LspServer.Diagnostics.cs
index 1afcce79..e05e2878 100644
--- a/AnyText/AnyText.Lsp/LspServer.Diagnostics.cs
+++ b/AnyText/AnyText.Lsp/LspServer.Diagnostics.cs
@@ -10,6 +10,7 @@ public partial class LspServer
private async void SendDiagnostics(string uri, ParseContext context)
{
+ SendLogMessage(MessageType.Info, $"Starting diagnostics generation for URI: {uri}");
var diagnostics = new List();
var errors = context.Errors;
foreach (var error in errors)
@@ -38,10 +39,13 @@ private async void SendDiagnostics(string uri, ParseContext context)
try
{
await _rpc.NotifyWithParameterObjectAsync(Methods.TextDocumentPublishDiagnosticsName, diagnosticsParams);
+ SendLogMessage(MessageType.Info, $"Diagnostics published successfully for URI: {uri} with {diagnostics.Count} issue(s).");
}
catch (Exception ex)
{
- Console.Error.WriteLine($"Error publishing Diagnostics: {ex.Message}");
+ var errorMessage = $"Error publishing diagnostics for URI: {uri}. Exception: {ex.Message}";
+ SendLogMessage(MessageType.Error, errorMessage);
+ Console.Error.WriteLine(errorMessage);
}
}
}
diff --git a/AnyText/AnyText.Lsp/LspServer.Registration.cs b/AnyText/AnyText.Lsp/LspServer.Registration.cs
index ddaed1b7..a005b221 100644
--- a/AnyText/AnyText.Lsp/LspServer.Registration.cs
+++ b/AnyText/AnyText.Lsp/LspServer.Registration.cs
@@ -35,11 +35,15 @@ private async void RegisterCapabilities(Registration[] registrations)
try
{
+ SendLogMessage(MessageType.Info, "Sending capabilities registration request to client.");
await _rpc.InvokeWithParameterObjectAsync(Methods.ClientRegisterCapabilityName, registrationParams);
+ SendLogMessage(MessageType.Info, "Capabilities registration request completed successfully.");
}
catch (Exception ex)
{
- Console.Error.WriteLine($"Error register capabilities: {ex.Message}");
+ var errorMessage = $"Error registering capabilities: {ex.Message}";
+ SendLogMessage(MessageType.Error, errorMessage);
+ Console.Error.WriteLine(errorMessage);
}
}
diff --git a/AnyText/AnyText.Lsp/LspServer.SemanticToken.cs b/AnyText/AnyText.Lsp/LspServer.SemanticToken.cs
index d103a14e..4697dd9f 100644
--- a/AnyText/AnyText.Lsp/LspServer.SemanticToken.cs
+++ b/AnyText/AnyText.Lsp/LspServer.SemanticToken.cs
@@ -13,6 +13,7 @@ public partial class LspServer
///
public SemanticTokens QuerySemanticTokens(JToken arg)
{
+ SendLogMessage(MessageType.Info, "Received request for full semantic tokens.");
var semanticTokensParams = arg.ToObject();
var uri = semanticTokensParams.TextDocument.Uri;
@@ -33,6 +34,7 @@ public SemanticTokens QuerySemanticTokens(JToken arg)
///
public SemanticTokensDelta QuerySemanticTokensDelta(JToken arg)
{
+ SendLogMessage(MessageType.Info, "Received request for semantic tokens delta.");
var semanticTokensParams = arg.ToObject();
var uri = semanticTokensParams.TextDocument.Uri;
@@ -74,6 +76,7 @@ public SemanticTokensDelta QuerySemanticTokensDelta(JToken arg)
///
public SemanticTokens QuerySemanticTokensRange(JToken arg)
{
+ SendLogMessage(MessageType.Info, "Received request for semantic tokens in a range.");
var semanticTokensRangeParams = arg.ToObject();
var uri = semanticTokensRangeParams.TextDocument.Uri;
var range = semanticTokensRangeParams.Range;
diff --git a/AnyText/AnyText.Lsp/LspServer.Trace.cs b/AnyText/AnyText.Lsp/LspServer.Trace.cs
new file mode 100644
index 00000000..61a33a2d
--- /dev/null
+++ b/AnyText/AnyText.Lsp/LspServer.Trace.cs
@@ -0,0 +1,34 @@
+using LspTypes;
+using Newtonsoft.Json.Linq;
+using System.Diagnostics;
+
+namespace NMF.AnyText
+{
+ public partial class LspServer
+ {
+ ///
+ public void SetTrace(JToken arg)
+ {
+ var setTraceParams = arg.ToObject();
+
+ UpdateTraceSource(setTraceParams.Value);
+ SendLogMessage(MessageType.Info, $"Trace level updated to: {setTraceParams.Value}");
+ }
+
+ private void UpdateTraceSource(TraceValue traceValue)
+ {
+ _rpc.TraceSource =
+ AnyTextJsonRpcServerUtil.CreateTraceSource(MapTraceValueToSourceLevels(traceValue));
+ }
+ private static SourceLevels MapTraceValueToSourceLevels(TraceValue traceValue)
+ {
+ return traceValue switch
+ {
+ TraceValue.Off => SourceLevels.Off,
+ TraceValue.Messages => SourceLevels.Information,
+ TraceValue.Verbose => SourceLevels.Verbose,
+ _ => SourceLevels.All
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/AnyText/AnyText.Lsp/LspServer.cs b/AnyText/AnyText.Lsp/LspServer.cs
index ae3b8af8..a2af3d9c 100644
--- a/AnyText/AnyText.Lsp/LspServer.cs
+++ b/AnyText/AnyText.Lsp/LspServer.cs
@@ -1,4 +1,4 @@
-using LspTypes;
+using LspTypes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NMF.AnyText.Grammars;
@@ -39,7 +39,6 @@ public LspServer(IEnumerable grammars)
_languages = grammars?.ToDictionary(sp => sp.LanguageId);
}
- [JsonRpcMethod(Methods.InitializeName)]
public InitializeResult Initialize(
int? processId
, _InitializeParams_ClientInfo clientInfo
@@ -72,8 +71,12 @@ public InitializeResult Initialize(
WorkDoneProgress = false
}
};
+ UpdateTraceSource(trace);
+
+ SendLogMessage(MessageType.Info, "LSP Server initialization completed.");
return new InitializeResult { Capabilities = serverCapabilities };
}
+
public void Initialized() { }
public void Shutdown() { }
@@ -87,11 +90,13 @@ public void DidChange(JToken arg)
{
document.Update(changes.ContentChanges.Select(AsTextEdit));
SendDiagnostics(changes.TextDocument.Uri, document.Context);
+ SendLogMessage(MessageType.Info, $"Document {changes.TextDocument.Uri} updated.");
}
}
public void DidSave(TextDocumentIdentifier textDocument, string text)
{
+ SendLogMessage(MessageType.Info, $"Document {textDocument.Uri} saved.");
}
private static ParsePosition AsParsePosition(Position position) => new ParsePosition((int)position.Line, (int)position.Character);
@@ -108,6 +113,7 @@ public void DidClose(JToken arg)
if (_documents.TryGetValue(closeParams.TextDocument.Uri, out var document))
{
_documents.Remove(closeParams.TextDocument.Uri);
+ SendLogMessage(MessageType.Info, $"Document {closeParams.TextDocument.Uri} closed.");
}
}
@@ -126,20 +132,43 @@ public void DidOpen(JToken arg)
RegisterCapabilitiesOnOpen(openParams.TextDocument.LanguageId, parser);
SendDiagnostics(openParams.TextDocument.Uri, parser.Context);
+ SendLogMessage(MessageType.Info, $"Document {openParams.TextDocument.Uri} opened with language {openParams.TextDocument.LanguageId}.");
}
else
{
- throw new NotSupportedException($"No grammar found for extension {openParams.TextDocument.LanguageId}");
+ var errorMessage = $"No grammar found for extension {openParams.TextDocument.LanguageId}";
+ SendLogMessage(MessageType.Error, errorMessage);
+ throw new NotSupportedException(errorMessage);
}
}
else
{
- throw new NotSupportedException($"Cannot open URI {openParams.TextDocument.Uri}");
+ var errorMessage = $"Cannot open URI {openParams.TextDocument.Uri}";
+ SendLogMessage(MessageType.Error, errorMessage);
+ throw new NotSupportedException(errorMessage);
}
}
public void Exit()
{
+ SendLogMessage(MessageType.Info, "LSP Server exiting.");
throw new NotImplementedException();
}
+
+ //
+ /// Sends a log message to the client.
+ ///
+ /// The type of the message (Info, Warning, Error).
+ /// The message content.
+ private void SendLogMessage(MessageType type, string message)
+ {
+ var logMessageParams = new LogMessageParams
+ {
+ MessageType = type,
+ Message = message
+ };
+
+ _rpc.NotifyWithParameterObjectAsync(Methods.WindowLogMessageName, logMessageParams);
+
+ }
}
}
\ No newline at end of file
diff --git a/AnyText/AnyText.Lsp/MethodConstants.cs b/AnyText/AnyText.Lsp/MethodConstants.cs
index 2327fe9d..3054d8d1 100644
--- a/AnyText/AnyText.Lsp/MethodConstants.cs
+++ b/AnyText/AnyText.Lsp/MethodConstants.cs
@@ -3,5 +3,6 @@ namespace NMF.AnyText
public static class MethodConstants
{
public const string RegisterSemanticTokens = "textDocument/semanticTokens";
+ public const string SetTrace = "$/setTrace";
}
}
\ No newline at end of file
diff --git a/AnyText/Tests/AnyTextExtension/package.json b/AnyText/Tests/AnyTextExtension/package.json
index 14dee364..55fb94a7 100644
--- a/AnyText/Tests/AnyTextExtension/package.json
+++ b/AnyText/Tests/AnyTextExtension/package.json
@@ -38,13 +38,13 @@
"type": "object",
"title": "Example configuration",
"properties": {
- "languageServerExample.maxNumberOfProblems": {
+ "anytext.maxNumberOfProblems": {
"scope": "resource",
"type": "number",
"default": 100,
"description": "Controls the maximum number of problems produced by the server."
},
- "languageServerExample.trace.server": {
+ "anytext.trace.server": {
"scope": "window",
"type": "string",
"enum": [
diff --git a/Glsp/Glsp/Processing/Layouting/LayeredLayoutService.cs b/Glsp/Glsp/Processing/Layouting/LayeredLayoutService.cs
index c96c1dde..8c37aa65 100644
--- a/Glsp/Glsp/Processing/Layouting/LayeredLayoutService.cs
+++ b/Glsp/Glsp/Processing/Layouting/LayeredLayoutService.cs
@@ -20,15 +20,35 @@ public class LayeredLayoutService : AglLayoutService
///
public static readonly LayeredLayoutService Instance = new LayeredLayoutService();
+ private static readonly SugiyamaLayoutSettings _defaultSettings = new SugiyamaLayoutSettings
+ {
+ Transformation = PlaneTransformation.Rotation(Math.PI / 2),
+ EdgeRoutingSettings = { EdgeRoutingMode = EdgeRoutingMode.Rectilinear }
+ };
+
+ ///
+ /// Creates a new instance
+ ///
+ public LayeredLayoutService() : this(null) { }
+
+ ///
+ /// Creates a new instance
+ ///
+ /// layout settings
+ public LayeredLayoutService(SugiyamaLayoutSettings settings)
+ {
+ Settings = settings ?? _defaultSettings;
+ }
+
+ ///
+ /// Gets the layout settings for this layout service
+ ///
+ public SugiyamaLayoutSettings Settings { get; }
+
///
protected override void ProcessLayout(GeometryGraph g)
{
- var settings = new SugiyamaLayoutSettings
- {
- Transformation = PlaneTransformation.Rotation(Math.PI / 2),
- EdgeRoutingSettings = { EdgeRoutingMode = EdgeRoutingMode.Rectilinear }
- };
- var layout = new LayeredLayout(g, settings);
+ var layout = new LayeredLayout(g, Settings);
layout.Run();
}
}
diff --git a/Models/Models/Repository/MetaRepository.cs b/Models/Models/Repository/MetaRepository.cs
index 2ca17999..fce4314d 100644
--- a/Models/Models/Repository/MetaRepository.cs
+++ b/Models/Models/Repository/MetaRepository.cs
@@ -13,11 +13,21 @@ namespace NMF.Models.Repository
///
public sealed class MetaRepository : IModelRepository
{
- private static readonly MetaRepository instance = new MetaRepository();
+ private static readonly MetaRepository instance;
private readonly ModelCollection entries;
private readonly ModelSerializer serializer = new ModelSerializer();
private readonly HashSet traversedAssemblies = new HashSet();
+ ///
+ /// Initializes the type
+ ///
+ static MetaRepository()
+ {
+ // we need an explicit static type constructor because the runtime is sometimes too lazy
+ // to initialize static variables in time, but they are needed for static lookup operations
+ instance = new MetaRepository();
+ }
+
event EventHandler IModelRepository.BubbledChange
{
add { }