Skip to content

Commit 01776cb

Browse files
committed
translate project
1 parent 88f45c1 commit 01776cb

File tree

10 files changed

+146
-81
lines changed

10 files changed

+146
-81
lines changed

LanguageServer.Framework.Tests/Handlers/CompletionHandlerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private class TestCompletionHandler : CompletionHandlerBase
4242

4343
protected override Task<CompletionItem> Resolve(CompletionItem item, CancellationToken token)
4444
{
45-
// 为 resolve 添加额外信息
45+
// Add additional information for resolve
4646
item.Documentation = item.Documentation ?? "Resolved documentation";
4747
return Task.FromResult(item);
4848
}

LanguageServer.Framework.Tests/TestBase/MockLanguageServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace EmmyLua.LanguageServer.Framework.Tests.TestBase;
55

66
/// <summary>
7-
/// 用于测试的模拟语言服务器
7+
/// Mock language server for testing
88
/// </summary>
99
public class MockLanguageServer : LanguageServerType
1010
{
@@ -18,7 +18,7 @@ public static MockLanguageServer Create()
1818
}
1919

2020
/// <summary>
21-
/// 获取输出流内容
21+
/// Get output stream content
2222
/// </summary>
2323
public string GetOutput()
2424
{

LanguageServer.Framework.Tests/TestBase/TestHandlerBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace EmmyLua.LanguageServer.Framework.Tests.TestBase;
44

55
/// <summary>
6-
/// Handler 测试基类
6+
/// Base class for handler tests
77
/// </summary>
88
public abstract class TestHandlerBase
99
{
@@ -15,7 +15,7 @@ protected TestHandlerBase()
1515
}
1616

1717
/// <summary>
18-
/// 添加 Handler 到服务器
18+
/// Add handler to server
1919
/// </summary>
2020
protected void AddHandler(IJsonHandler handler)
2121
{

LanguageServer.Framework/LSPCommunicationBase.cs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
namespace EmmyLua.LanguageServer.Framework;
1616

17+
// ReSharper disable once InconsistentNaming
1718
public abstract class LSPCommunicationBase : IDisposable
1819
{
1920
public JsonSerializerOptions JsonSerializerOptions { get; } = new()
@@ -45,15 +46,15 @@ public abstract class LSPCommunicationBase : IDisposable
4546
public ClientCapabilities ClientCapabilities { get; set; } = null!;
4647

4748
/// <summary>
48-
/// 性能指标收集器
49+
/// Performance metrics collector
4950
/// </summary>
5051
public IPerformanceMetricsCollector? MetricsCollector
5152
{
5253
get => _metricsCollector;
5354
set
5455
{
5556
_metricsCollector = value;
56-
// 同步到Writer
57+
// Synchronize to Writer
5758
Writer.MetricsCollector = value;
5859
}
5960
}
@@ -97,13 +98,38 @@ public LSPCommunicationBase AddHandler(IJsonHandler handler)
9798
}
9899

99100
/// <summary>
100-
/// 获取当前的性能指标快照
101+
/// Get current performance metrics snapshot
101102
/// </summary>
102103
public PerformanceMetrics? GetMetrics()
103104
{
104105
return MetricsCollector?.GetMetrics();
105106
}
106107

108+
/// <summary>
109+
/// Print performance metrics summary to console error output
110+
/// </summary>
111+
public void PrintMetrics()
112+
{
113+
var metrics = GetMetrics();
114+
if (metrics == null)
115+
{
116+
Console.Error.WriteLine("Performance metrics not enabled.");
117+
return;
118+
}
119+
120+
Console.Error.WriteLine("=== Performance Metrics ===");
121+
Console.Error.WriteLine($"Uptime: {metrics.Uptime}");
122+
Console.Error.WriteLine($"Total Requests Handled: {metrics.TotalRequestsHandled}");
123+
Console.Error.WriteLine($"Total Notifications Handled: {metrics.TotalNotificationsHandled}");
124+
Console.Error.WriteLine($"Total Requests Failed: {metrics.TotalRequestsFailed}");
125+
Console.Error.WriteLine($"Average Request Duration: {metrics.AverageRequestDurationMs:F2}ms");
126+
Console.Error.WriteLine($"Max Request Duration: {metrics.MaxRequestDurationMs:F2}ms");
127+
Console.Error.WriteLine($"Pending Requests: {metrics.PendingRequestsCount}");
128+
Console.Error.WriteLine($"Total Messages Sent: {metrics.TotalMessagesSent}");
129+
Console.Error.WriteLine($"Total Messages Received: {metrics.TotalMessagesReceived}");
130+
Console.Error.WriteLine("===========================");
131+
}
132+
107133
public Task SendNotification(NotificationMessage notification)
108134
{
109135
Writer.WriteNotification(notification);
@@ -202,14 +228,14 @@ private async Task OnDispatch(Message message)
202228

203229
try
204230
{
205-
// 创建取消令牌以支持通知处理的取消
231+
// Create cancellation token to support notification handling cancellation
206232
using var cts = CancellationTokenSource.CreateLinkedTokenSource(
207233
ExitTokenSource?.Token ?? CancellationToken.None);
208234
await handler(notification, cts.Token);
209235
}
210236
catch (OperationCanceledException)
211237
{
212-
// Notification 被取消,忽略
238+
// Notification cancelled, ignore
213239
}
214240
catch (Exception e)
215241
{
@@ -303,7 +329,7 @@ protected virtual void Dispose(bool disposing)
303329

304330
if (disposing)
305331
{
306-
// 取消运行
332+
// Cancel running
307333
try
308334
{
309335
Exit();
@@ -313,7 +339,7 @@ protected virtual void Dispose(bool disposing)
313339
// Ignore if not running
314340
}
315341

316-
// 释放资源
342+
// Release resources
317343
ExitTokenSource?.Dispose();
318344
_exitTokenLock.Dispose();
319345

LanguageServer.Framework/Server/JsonProtocol/JsonProtocolReader.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public async Task<Message> ReadAsync(CancellationToken token = default)
2323

2424
try
2525
{
26-
// 对于小消息使用 SmallBuffer 避免 ArrayPool 的开销
26+
// Use SmallBuffer for small messages to avoid ArrayPool overhead
2727
if (totalLength + contentStart <= SmallBuffer.Length)
2828
{
2929
return await ReadSmallJsonRpcMessageAsync(totalLength, contentStart, readContentLength, token);
@@ -35,7 +35,7 @@ public async Task<Message> ReadAsync(CancellationToken token = default)
3535
}
3636
finally
3737
{
38-
// 使用 totalLength 而不是 readContentLength,因为消息可能已经完全读取
38+
// Use totalLength instead of readContentLength as the message may be fully read
3939
if (contentStart + totalLength < _currentValidLength)
4040
{
4141
var remaining = _currentValidLength - (contentStart + totalLength);
@@ -70,19 +70,19 @@ private bool TryGetContentLength(int startIndex, out int contentLength, out int
7070
var headerEnd = i;
7171
if (headerEnd > 0)
7272
{
73-
// 使用 Span 避免字符串分配
73+
// Use Span to avoid string allocation
7474
var headerSpan = buffer[..headerEnd];
7575

76-
// 直接在 byte span 上查找 "Content-Length:"
76+
// Find "Content-Length:" directly on byte span
7777
ReadOnlySpan<byte> contentLengthPrefix = "Content-Length:"u8;
7878

7979
if (headerSpan.Length >= contentLengthPrefix.Length &&
8080
headerSpan[..contentLengthPrefix.Length].SequenceEqual(contentLengthPrefix))
8181
{
82-
// 解析数字部分
82+
// Parse number part
8383
var numberSpan = headerSpan[contentLengthPrefix.Length..];
8484

85-
// 跳过空格
85+
// Skip spaces
8686
int numberStart = 0;
8787
while (numberStart < numberSpan.Length && numberSpan[numberStart] == ' ')
8888
{
@@ -91,10 +91,10 @@ private bool TryGetContentLength(int startIndex, out int contentLength, out int
9191

9292
if (numberStart < numberSpan.Length)
9393
{
94-
// 使用 Utf8Parser 高效解析数字
94+
// Use Utf8Parser to efficiently parse numbers
9595
if (TryParseInt32(numberSpan[numberStart..], out contentLength))
9696
{
97-
// 找到了 Content-Length
97+
// Found Content-Length
9898
}
9999
else
100100
{
@@ -118,7 +118,7 @@ private bool TryGetContentLength(int startIndex, out int contentLength, out int
118118
return false;
119119
}
120120

121-
// 快速 UTF8 整数解析
121+
// Fast UTF8 integer parsing
122122
private static bool TryParseInt32(ReadOnlySpan<byte> utf8Bytes, out int value)
123123
{
124124
value = 0;
@@ -128,7 +128,7 @@ private static bool TryParseInt32(ReadOnlySpan<byte> utf8Bytes, out int value)
128128
{
129129
if (b < '0' || b > '9')
130130
{
131-
return value > 0; // 如果已经解析了一些数字,返回 true
131+
return value > 0; // Return true if some digits have been parsed
132132
}
133133
value = value * 10 + (b - '0');
134134
}
@@ -158,7 +158,7 @@ private async Task<Message> ReadSmallJsonRpcMessageAsync(int totalContentLength,
158158
{
159159
try
160160
{
161-
// 继续读取剩余的消息内容
161+
// Continue reading remaining message content
162162
while (readContentLength < totalContentLength)
163163
{
164164
var bytesToRead = totalContentLength - readContentLength;
@@ -173,7 +173,7 @@ private async Task<Message> ReadSmallJsonRpcMessageAsync(int totalContentLength,
173173
if (read == 0) throw new InvalidOperationException("Stream closed before all data could be read.");
174174
readContentLength += read;
175175

176-
// 更新 _currentValidLength 以反映实际读取的数据
176+
// Update _currentValidLength to reflect actually read data
177177
var newValidLength = contentStart + readContentLength;
178178
if (newValidLength > _currentValidLength)
179179
{
@@ -194,7 +194,7 @@ private async Task<Message> ReadLargeJsonRpcMessageAsync(int totalContentLength,
194194
int readContentLength, CancellationToken token = default)
195195
{
196196
var buffer = ArrayPool<byte>.Shared.Rent(totalContentLength);
197-
// 将smallbuffer中的数据拷贝到buffer中
197+
// Copy data from smallbuffer to buffer
198198
SmallBuffer.AsSpan(contentStart, readContentLength).CopyTo(buffer);
199199
try
200200
{

LanguageServer.Framework/Server/JsonProtocol/JsonProtocolWriter.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class JsonProtocolWriter : IDisposable
1616
private bool _disposed;
1717

1818
/// <summary>
19-
/// 性能指标收集器
19+
/// Performance metrics collector
2020
/// </summary>
2121
public IPerformanceMetricsCollector? MetricsCollector { get; set; }
2222

@@ -46,35 +46,35 @@ private void WriteMessage<T>(T message)
4646
{
4747
ObjectDisposedException.ThrowIf(_disposed, this);
4848

49-
// 使用线程安全的写入
49+
// Use thread-safe writing
5050
_writeLock.Wait();
5151
try
5252
{
53-
// 序列化到内存
53+
// Serialize to memory
5454
var json = JsonSerializer.Serialize(message, _jsonSerializerOptions);
5555
var contentLength = Encoding.UTF8.GetByteCount(json);
5656

57-
// 计算header大小
57+
// Calculate header size
5858
var headerText = $"Content-Length: {contentLength}\r\n\r\n";
5959
var headerBytes = Encoding.UTF8.GetByteCount(headerText);
6060

61-
// 使用ArrayPool减少分配
61+
// Use ArrayPool to reduce allocations
6262
var totalLength = headerBytes + contentLength;
6363
var buffer = ArrayPool<byte>.Shared.Rent(totalLength);
6464

6565
try
6666
{
67-
// 写入header
67+
// Write header
6868
var written = Encoding.UTF8.GetBytes(headerText, buffer);
6969

70-
// 写入content
70+
// Write content
7171
written += Encoding.UTF8.GetBytes(json, buffer.AsSpan(written));
7272

73-
// 一次性写入到流
73+
// Write to stream at once
7474
_output.Write(buffer, 0, written);
7575
_output.Flush();
7676

77-
// 记录消息发送
77+
// Record message sent
7878
MetricsCollector?.RecordMessageSent();
7979
}
8080
finally

LanguageServer.Framework/Server/LanguageServer.cs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,36 @@ private RunningState State
3131

3232
public ClientProxy Client { get; }
3333

34+
public LanguageServerOptions Options { get; }
3435

35-
public LanguageServer(Stream input, Stream output) : base(input, output)
36+
private Timer? _metricsTimer;
37+
38+
public LanguageServer(Stream input, Stream output, LanguageServerOptions? options = null) : base(input, output)
3639
{
40+
Options = options ?? LanguageServerOptions.Default;
3741
Client = new ClientProxy(this);
3842
AddHandler(new InitializeHandler(this));
43+
44+
// Initialize performance metrics collector based on options
45+
if (Options.EnablePerformanceTracing)
46+
{
47+
MetricsCollector = new Metrics.DefaultPerformanceMetricsCollector();
48+
49+
// Start timer if periodic print interval is set
50+
if (Options.PerformanceMetricsPrintInterval.HasValue)
51+
{
52+
_metricsTimer = new Timer(
53+
_ => PrintMetrics(),
54+
null,
55+
Options.PerformanceMetricsPrintInterval.Value,
56+
Options.PerformanceMetricsPrintInterval.Value
57+
);
58+
}
59+
}
3960
}
4061

41-
public static LanguageServer From(Stream input, Stream output) => new(input, output);
62+
public static LanguageServer From(Stream input, Stream output, LanguageServerOptions? options = null)
63+
=> new(input, output, options);
4264

4365
public delegate Task InitializeEvent(InitializeParams request, ServerInfo serverInfo);
4466

@@ -67,22 +89,21 @@ public void OnShutdown(ShutdownEvent handler)
6789
ShutdownEventDelegate += handler;
6890
}
6991

70-
// public delegate void StartEvent();
71-
//
72-
// internal StartEvent? StartEventDelegate;
73-
//
74-
// public void OnStart(StartEvent handler)
75-
// {
76-
// StartEventDelegate += handler;
77-
// }
78-
7992
protected override bool BaseHandle(Message message)
8093
{
8194
if (message is RequestMessage requestMessage)
8295
{
8396
if (requestMessage.Method == "shutdown")
8497
{
8598
State = RunningState.Shutdown;
99+
100+
// Print final performance metrics on shutdown
101+
if (Options.EnablePerformanceTracing)
102+
{
103+
Console.Error.WriteLine("\n=== Final Performance Metrics (on shutdown) ===");
104+
PrintMetrics();
105+
}
106+
86107
ShutdownEventDelegate?.Invoke();
87108
Writer.WriteResponse(requestMessage.Id, null);
88109
return true;
@@ -114,4 +135,13 @@ protected override bool BaseHandle(Message message)
114135

115136
return false;
116137
}
138+
139+
protected override void Dispose(bool disposing)
140+
{
141+
if (disposing)
142+
{
143+
_metricsTimer?.Dispose();
144+
}
145+
base.Dispose(disposing);
146+
}
117147
}

0 commit comments

Comments
 (0)