Skip to content

Commit 4ab9c5d

Browse files
committed
修改为语言服务3.17版本的诊断实现
1 parent b7c637b commit 4ab9c5d

File tree

11 files changed

+417
-62
lines changed

11 files changed

+417
-62
lines changed

CodeFormatServer/src/LanguageClient.cpp

Lines changed: 145 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "CodeFormatServer/LanguageClient.h"
22
#include <iterator>
3+
#include <fstream>
34
#include "CodeService/LuaEditorConfig.h"
45
#include "CodeService/LuaFormatter.h"
56
#include "LuaParser/LuaParser.h"
@@ -22,7 +23,8 @@ LanguageClient& LanguageClient::GetInstance()
2223
LanguageClient::LanguageClient()
2324
: _defaultOptions(std::make_shared<LuaCodeStyleOptions>()),
2425
_idCounter(0),
25-
_ioc(1)
26+
_ioc(1),
27+
_configVersion(0)
2628
{
2729
}
2830

@@ -60,7 +62,14 @@ void LanguageClient::SendNotification(std::string_view method, std::shared_ptr<v
6062
auto json = nlohmann::json::object();
6163
json["jsonrpc"] = "2.0";
6264
json["method"] = method;
63-
json["params"] = param->Serialize();
65+
if (param != nullptr)
66+
{
67+
json["params"] = param->Serialize();
68+
}
69+
else
70+
{
71+
json["params"] = nullptr;
72+
}
6473

6574
if (_session)
6675
{
@@ -130,75 +139,135 @@ void LanguageClient::ClearFile(std::string_view uri)
130139
}
131140
}
132141

133-
void LanguageClient::DiagnosticFile(std::string_view uri)
142+
void LanguageClient::DiagnosticFile(std::string_view uri, std::string_view prevId,
143+
std::shared_ptr<vscode::DocumentDiagnosticReport> report)
134144
{
145+
report->kind = vscode::DocumentDiagnosticReportKind::Unchanged;
135146
auto filename = url::UrlToFilePath(uri);
136147
auto it = _fileMap.find(filename);
137148
if (it == _fileMap.end())
138149
{
139150
return;
140151
}
152+
auto& virtualFile = it->second;
141153

142-
auto vscodeDiagnosis = std::make_shared<vscode::PublishDiagnosticsParams>();
143-
vscodeDiagnosis->uri = uri;
154+
auto resultId = std::to_string(_configVersion) + "|" + std::to_string(virtualFile->GetVersion());
155+
report->resultId = resultId;
156+
if(resultId == prevId)
157+
{
158+
return;
159+
}
144160

145161
auto options = GetOptions(uri);
146162
if (!options->enable_check_codestyle)
147163
{
148-
SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
164+
report->kind = vscode::DocumentDiagnosticReportKind::Full;
149165
return;
150166
}
151167

152168
std::shared_ptr<LuaParser> parser = it->second->GetLuaParser();
153169

154170
if (parser->HasError())
155171
{
172+
report->kind = vscode::DocumentDiagnosticReportKind::Unchanged;
156173
return;
157174
}
158175

176+
report->kind = vscode::DocumentDiagnosticReportKind::Full;
177+
159178
// TODO move spell check to SpellService
160179
auto formatDiagnostic = GetService<CodeFormatService>()->Diagnose(filename, parser, options);
161-
std::copy(formatDiagnostic.begin(), formatDiagnostic.end(), std::back_inserter(vscodeDiagnosis->diagnostics));
180+
std::copy(formatDiagnostic.begin(), formatDiagnostic.end(), std::back_inserter(report->items));
162181

163182
if (_vscodeSettings.lintModule)
164183
{
165184
auto moduleDiagnosis = GetService<ModuleService>()->Diagnose(filename, parser);
166-
std::copy(moduleDiagnosis.begin(), moduleDiagnosis.end(), std::back_inserter(vscodeDiagnosis->diagnostics));
185+
std::copy(moduleDiagnosis.begin(), moduleDiagnosis.end(), std::back_inserter(report->items));
167186
}
168-
169-
SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
170187
}
171188

172-
void LanguageClient::DelayDiagnosticFile(std::string_view uri)
189+
std::optional<uint64_t> LanguageClient::GetFileVersion(std::string_view uri)
173190
{
174-
auto stringUri = std::string(uri);
175-
auto task = std::make_shared<asio::steady_timer>(GetIOContext(), std::chrono::milliseconds(300));
176-
auto it = _fileDiagnosticTask.find(uri);
177-
if (it != _fileDiagnosticTask.end())
178-
{
179-
it->second->cancel();
180-
it->second = task;
181-
}
182-
else
191+
auto filename = url::UrlToFilePath(uri);
192+
auto it = _fileMap.find(filename);
193+
if (it == _fileMap.end())
183194
{
184-
_fileDiagnosticTask.insert({stringUri, task});
195+
return {};
185196
}
186-
187-
task->async_wait([this, stringUri](const asio::error_code& code)
188-
{
189-
if (code == asio::error::operation_aborted)
190-
{
191-
return;
192-
}
193-
DiagnosticFile(stringUri);
194-
auto it = _fileDiagnosticTask.find(stringUri);
195-
if (it != _fileDiagnosticTask.end())
196-
{
197-
_fileDiagnosticTask.erase(it);
198-
}
199-
});
197+
auto& virtualFile = it->second;
198+
return virtualFile->GetVersion();
200199
}
201200

201+
//
202+
// void LanguageClient::DiagnosticFile(std::string_view uri)
203+
// {
204+
// auto filename = url::UrlToFilePath(uri);
205+
// auto it = _fileMap.find(filename);
206+
// if (it == _fileMap.end())
207+
// {
208+
// return;
209+
// }
210+
//
211+
// auto vscodeDiagnosis = std::make_shared<vscode::PublishDiagnosticsParams>();
212+
// vscodeDiagnosis->uri = uri;
213+
//
214+
// auto options = GetOptions(uri);
215+
// if (!options->enable_check_codestyle)
216+
// {
217+
// SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
218+
// return;
219+
// }
220+
//
221+
// std::shared_ptr<LuaParser> parser = it->second->GetLuaParser();
222+
//
223+
// if (parser->HasError())
224+
// {
225+
// return;
226+
// }
227+
//
228+
// // TODO move spell check to SpellService
229+
// auto formatDiagnostic = GetService<CodeFormatService>()->Diagnose(filename, parser, options);
230+
// std::copy(formatDiagnostic.begin(), formatDiagnostic.end(), std::back_inserter(vscodeDiagnosis->diagnostics));
231+
//
232+
// if (_vscodeSettings.lintModule)
233+
// {
234+
// auto moduleDiagnosis = GetService<ModuleService>()->Diagnose(filename, parser);
235+
// std::copy(moduleDiagnosis.begin(), moduleDiagnosis.end(), std::back_inserter(vscodeDiagnosis->diagnostics));
236+
// }
237+
//
238+
// SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
239+
// }
240+
241+
// void LanguageClient::DelayDiagnosticFile(std::string_view uri)
242+
// {
243+
// auto stringUri = std::string(uri);
244+
// auto task = std::make_shared<asio::steady_timer>(GetIOContext(), std::chrono::milliseconds(300));
245+
// auto it = _fileDiagnosticTask.find(uri);
246+
// if (it != _fileDiagnosticTask.end())
247+
// {
248+
// it->second->cancel();
249+
// it->second = task;
250+
// }
251+
// else
252+
// {
253+
// _fileDiagnosticTask.insert({stringUri, task});
254+
// }
255+
//
256+
// task->async_wait([this, stringUri](const asio::error_code& code)
257+
// {
258+
// if (code == asio::error::operation_aborted)
259+
// {
260+
// return;
261+
// }
262+
// DiagnosticFile(stringUri);
263+
// auto it = _fileDiagnosticTask.find(stringUri);
264+
// if (it != _fileDiagnosticTask.end())
265+
// {
266+
// _fileDiagnosticTask.erase(it);
267+
// }
268+
// });
269+
// }
270+
202271
std::shared_ptr<LuaParser> LanguageClient::GetFileParser(std::string_view uri)
203272
{
204273
auto filename = url::UrlToFilePath(uri);
@@ -250,6 +319,7 @@ std::shared_ptr<LuaCodeStyleOptions> LanguageClient::GetOptions(std::string_view
250319

251320
void LanguageClient::UpdateCodeStyleOptions(std::string_view workspaceUri, std::string_view configPath)
252321
{
322+
_configVersion++;
253323
auto workspace = url::UrlToFilePath(workspaceUri);
254324
for (auto& pair : _editorConfigVector)
255325
{
@@ -272,6 +342,7 @@ void LanguageClient::UpdateCodeStyleOptions(std::string_view workspaceUri, std::
272342

273343
void LanguageClient::RemoveCodeStyleOptions(std::string_view workspaceUri)
274344
{
345+
++_configVersion;
275346
auto workspace = url::UrlToFilePath(workspaceUri);
276347
for (auto it = _editorConfigVector.begin(); it != _editorConfigVector.end(); it++)
277348
{
@@ -282,18 +353,24 @@ void LanguageClient::RemoveCodeStyleOptions(std::string_view workspaceUri)
282353
}
283354
}
284355
}
285-
286-
void LanguageClient::UpdateAllDiagnosis()
356+
//
357+
// void LanguageClient::UpdateAllDiagnosis()
358+
// {
359+
// for (auto it : _fileMap)
360+
// {
361+
// auto uri = url::FilePathToUrl(it.first);
362+
// DiagnosticFile(uri);
363+
// }
364+
// }
365+
366+
void LanguageClient::RefreshDiagnostic()
287367
{
288-
for (auto it : _fileMap)
289-
{
290-
auto uri = url::FilePathToUrl(it.first);
291-
DiagnosticFile(uri);
292-
}
368+
SendNotification("workspace/diagnostic/refresh", nullptr);
293369
}
294370

295371
void LanguageClient::UpdateModuleInfo()
296372
{
373+
_configVersion++;
297374
FileFinder finder(_root);
298375

299376
finder.AddIgnoreDirectory(".git");
@@ -306,7 +383,8 @@ void LanguageClient::UpdateModuleInfo()
306383
finder.AddFindExtension(".lua");
307384
finder.AddFindExtension(".lua.txt");
308385

309-
GetService<ModuleService>()->GetIndex().RebuildIndex(finder.FindFiles());
386+
_workspaceReadyFiles = finder.FindFiles();
387+
GetService<ModuleService>()->GetIndex().RebuildIndex(_workspaceReadyFiles);
310388
}
311389

312390
void LanguageClient::SetRoot(std::string_view root)
@@ -326,11 +404,35 @@ vscode::VscodeSettings& LanguageClient::GetSettings()
326404

327405
void LanguageClient::SetVscodeSettings(vscode::VscodeSettings& settings)
328406
{
407+
_configVersion++;
329408
_vscodeSettings = settings;
330409

331410
GetService<CodeFormatService>()->SetCustomDictionary(_vscodeSettings.spellDict);
332411
}
333412

413+
void LanguageClient::LoadWorkspace()
414+
{
415+
if(_workspaceReadyFiles.empty())
416+
{
417+
return;
418+
}
419+
420+
for(auto& filename: _workspaceReadyFiles)
421+
{
422+
if(_fileMap.count(filename) == 0)
423+
{
424+
std::fstream fin(filename, std::ios::in);
425+
if (fin.is_open())
426+
{
427+
std::stringstream s;
428+
s << fin.rdbuf();
429+
UpdateFile(url::FilePathToUrl(filename), vscode::Range(), std::move(s.str()));
430+
}
431+
}
432+
}
433+
_workspaceReadyFiles.clear();
434+
}
435+
334436
uint64_t LanguageClient::GetRequestId()
335437
{
336438
return ++_idCounter;

CodeFormatServer/src/LanguageService.cpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ bool LanguageService::Initialize()
4444
JsonProtocol("workspace/didChangeWatchedFiles", &LanguageService::OnDidChangeWatchedFiles);
4545
JsonProtocol("textDocument/completion", &LanguageService::OnCompletion);
4646
JsonProtocol("workspace/didChangeConfiguration", &LanguageService::OnWorkspaceDidChangeConfiguration);
47+
JsonProtocol("textDocument/diagnostic", &LanguageService::OnTextDocumentDiagnostic);
48+
JsonProtocol("workspace/diagnostic", &LanguageService::OnWorkspaceDiagnostic);
4749
return true;
4850
}
4951

@@ -88,6 +90,10 @@ std::shared_ptr<vscode::InitializeResult> LanguageService::OnInitialize(std::sha
8890
// 砍掉代码补全
8991
result->capabilities.completionProvider.supportCompletion = false;
9092

93+
result->capabilities.diagnosticProvider.identifier = "EmmyLuaCodeStyle";
94+
result->capabilities.diagnosticProvider.workspaceDiagnostics = false;
95+
result->capabilities.diagnosticProvider.interFileDependencies = false;
96+
9197
auto& editorConfigFiles = param->initializationOptions.editorConfigFiles;
9298
for (auto& configFile : editorConfigFiles)
9399
{
@@ -179,15 +185,15 @@ std::shared_ptr<vscode::Serializable> LanguageService::OnDidChange(
179185
LanguageClient::GetInstance().UpdateFile(param->textDocument.uri, param->contentChanges);
180186
}
181187

182-
LanguageClient::GetInstance().DelayDiagnosticFile(param->textDocument.uri);
188+
// LanguageClient::GetInstance().DelayDiagnosticFile(param->textDocument.uri);
183189
return nullptr;
184190
}
185191

186192
std::shared_ptr<vscode::Serializable> LanguageService::OnDidOpen(
187193
std::shared_ptr<vscode::DidOpenTextDocumentParams> param)
188194
{
189195
LanguageClient::GetInstance().UpdateFile(param->textDocument.uri, {}, std::move(param->textDocument.text));
190-
LanguageClient::GetInstance().DiagnosticFile(param->textDocument.uri);
196+
// LanguageClient::GetInstance().DiagnosticFile(param->textDocument.uri);
191197
return nullptr;
192198
}
193199

@@ -251,7 +257,7 @@ std::shared_ptr<vscode::Serializable> LanguageService::OnEditorConfigUpdate(
251257
}
252258
}
253259

254-
LanguageClient::GetInstance().UpdateAllDiagnosis();
260+
LanguageClient::GetInstance().RefreshDiagnostic();
255261

256262
return nullptr;
257263
}
@@ -463,5 +469,43 @@ std::shared_ptr<vscode::Serializable> LanguageService::OnWorkspaceDidChangeConfi
463469

464470
LanguageClient::GetInstance().SetVscodeSettings(setting);
465471

472+
// LanguageClient::GetInstance().DelayDiagnosticFile(param->textDocument.uri);
473+
LanguageClient::GetInstance().RefreshDiagnostic();
474+
466475
return nullptr;
467476
}
477+
478+
std::shared_ptr<vscode::DocumentDiagnosticReport> LanguageService::OnTextDocumentDiagnostic(
479+
std::shared_ptr<vscode::DocumentDiagnosticParams> param)
480+
{
481+
auto report = std::make_shared<vscode::DocumentDiagnosticReport>();
482+
LanguageClient::GetInstance().DiagnosticFile(param->textDocument.uri, param->previousResultId, report);
483+
484+
return report;
485+
}
486+
487+
488+
std::shared_ptr<vscode::WorkspaceDiagnosticReport> LanguageService::OnWorkspaceDiagnostic(
489+
std::shared_ptr<vscode::WorkspaceDiagnosticParams> param)
490+
{
491+
492+
// if(param->previousResultIds.empty())
493+
// {
494+
// LanguageClient::GetInstance().LoadWorkspace();
495+
// }
496+
497+
auto workspaceReport = std::make_shared<vscode::WorkspaceDiagnosticReport>();
498+
for (auto& result : param->previousResultIds)
499+
{
500+
auto documentReport = std::make_shared<vscode::DocumentDiagnosticReport>();
501+
LanguageClient::GetInstance().DiagnosticFile(result.uri, result.value, documentReport);
502+
auto& item = workspaceReport->items.emplace_back();
503+
item.uri = result.uri;
504+
item.kind = documentReport->kind;
505+
item.items = documentReport->items;
506+
item.resultId = documentReport->resultId;
507+
item.version = LanguageClient::GetInstance().GetFileVersion(result.uri);
508+
}
509+
510+
return workspaceReport;
511+
}

0 commit comments

Comments
 (0)