Skip to content

Commit 6be1aeb

Browse files
committed
语言服务实现的代码格式化和一般代码风格诊断
1 parent f863ca5 commit 6be1aeb

File tree

11 files changed

+360
-156
lines changed

11 files changed

+360
-156
lines changed

.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
[*]
3+
4+
# ReSharper properties
5+
resharper_namespace_indentation = none

CodeFormatServer/src/LanguageClient.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include "CodeFormatServer/LanguageClient.h"
2+
3+
#include "CodeService/LuaFormatter.h"
4+
#include "LuaParser/LuaParser.h"
25
#include "Util/format.h"
36

47
LanguageClient& LanguageClient::GetInstance()
@@ -24,7 +27,7 @@ void LanguageClient::SendNotification(std::string_view method, std::shared_ptr<v
2427
json["method"] = method;
2528
json["params"] = param->Serialize();
2629

27-
if(_session)
30+
if (_session)
2831
{
2932
auto dumpResult = json.dump();
3033
std::string message = format("Content-Length:{}\r\n\r\n", dumpResult.size());
@@ -34,10 +37,71 @@ void LanguageClient::SendNotification(std::string_view method, std::shared_ptr<v
3437
}
3538
}
3639

40+
void LanguageClient::CacheFile(const std::string& uri, std::string text)
41+
{
42+
_fileMap[uri] = std::move(text);
43+
}
44+
45+
void LanguageClient::DiagnosticFile(const std::string& uri)
46+
{
47+
auto it = _fileMap.find(uri);
48+
if (it == _fileMap.end())
49+
{
50+
return;
51+
}
52+
53+
std::string text = it->second;
54+
55+
std::shared_ptr<LuaParser> parser = LuaParser::LoadFromBuffer(std::move(text));
56+
parser->BuildAstWithComment();
57+
58+
LuaFormatter formatter(parser, _options);
59+
formatter.BuildFormattedElement();
60+
61+
auto diagnosisInfos = formatter.GetDiagnosisInfos();
62+
63+
auto vscodeDiagnosis = std::make_shared<vscode::PublishDiagnosticsParams>();
64+
vscodeDiagnosis->uri = uri;
65+
66+
for (auto diagnosisInfo : diagnosisInfos)
67+
{
68+
auto& diagnosis = vscodeDiagnosis->diagnostics.emplace_back();
69+
diagnosis.message = diagnosisInfo.Message;
70+
diagnosis.range = vscode::Range(
71+
vscode::Position(
72+
diagnosisInfo.Range.Start.Line,
73+
diagnosisInfo.Range.Start.Character
74+
),
75+
vscode::Position(
76+
diagnosisInfo.Range.End.Line,
77+
diagnosisInfo.Range.End.Character
78+
));
79+
diagnosis.severity = vscode::DiagnosticSeverity::Warning;
80+
}
81+
82+
SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
83+
}
84+
85+
std::string LanguageClient::GetFile(const std::string& uri)
86+
{
87+
auto it = _fileMap.find(uri);
88+
if(it != _fileMap.end())
89+
{
90+
return it->second;
91+
}
92+
93+
return "";
94+
}
95+
3796
void LanguageClient::Run()
3897
{
3998
if (_session)
4099
{
41100
_session->Run();
42101
}
43102
}
103+
104+
LuaFormatOptions& LanguageClient::GetOptions()
105+
{
106+
return _options;
107+
}

CodeFormatServer/src/LanguageService.cpp

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ bool LanguageService::Initialize()
2121

2222
_handles["initialize"] = DynamicBind(OnInitialize, vscode::InitializeParams);
2323
_handles["textDocument/didChange"] = DynamicBind(OnDidChange, vscode::DidChangeTextDocumentParams);
24-
24+
_handles["textDocument/didOpen"] = DynamicBind(OnDidOpen, vscode::DidOpenTextDocumentParam);
25+
_handles["textDocument/formatting"] = DynamicBind(OnFormatting, vscode::DocumentFormattingParams);
2526
return true;
2627
}
2728

@@ -49,36 +50,52 @@ std::shared_ptr<vscode::InitializeResult> LanguageService::OnInitialize(std::sha
4950
std::shared_ptr<vscode::Serializable> LanguageService::OnDidChange(
5051
std::shared_ptr<vscode::DidChangeTextDocumentParams> param)
5152
{
52-
LuaFormatOptions options;
53+
for (auto& content : param->contentChanges)
54+
{
55+
LanguageClient::GetInstance().CacheFile(param->textDocument.uri, content.text);
5356

54-
std::shared_ptr<LuaParser> parser = LuaParser::LoadFromBuffer(std::move(param->contentChanges[0].text));
55-
parser->BuildAstWithComment();
57+
LanguageClient::GetInstance().DiagnosticFile(param->textDocument.uri);
58+
}
59+
return nullptr;
60+
}
5661

57-
LuaFormatter formatter(parser, options);
58-
formatter.BuildFormattedElement();
62+
std::shared_ptr<vscode::Serializable> LanguageService::OnDidOpen(
63+
std::shared_ptr<vscode::DidOpenTextDocumentParam> param)
64+
{
65+
LanguageClient::GetInstance().CacheFile(param->textDocument.uri, param->textDocument.text);
66+
LanguageClient::GetInstance().DiagnosticFile(param->textDocument.uri);
5967

60-
auto diagnosisInfos = formatter.GetDiagnosisInfos();
68+
return nullptr;
69+
}
6170

62-
auto vscodeDiagnosis = std::make_shared<vscode::PublishDiagnosticsParams>();
63-
vscodeDiagnosis->uri = param->textDocument.uri;
71+
std::shared_ptr<vscode::Serializable> LanguageService::OnFormatting(
72+
std::shared_ptr<vscode::DocumentFormattingParams> param)
73+
{
74+
auto text = LanguageClient::GetInstance().GetFile(param->textDocument.uri);
75+
76+
auto lastOffset = text.size();
77+
78+
auto result = std::make_shared<vscode::DocumentFormattingResult>();
6479

65-
for (auto diagnosisInfo : diagnosisInfos)
80+
if (text.empty())
6681
{
67-
auto& diagnosis = vscodeDiagnosis->diagnostics.emplace_back();
68-
diagnosis.message = diagnosisInfo.Message;
69-
diagnosis.range = vscode::Range(
70-
vscode::Position(
71-
diagnosisInfo.Range.Start.Line,
72-
diagnosisInfo.Range.Start.Character
73-
),
74-
vscode::Position(
75-
diagnosisInfo.Range.End.Line,
76-
diagnosisInfo.Range.End.Character
77-
));
78-
diagnosis.severity = vscode::DiagnosticSeverity::Warning;
82+
result->hasError = true;
83+
return result;
7984
}
8085

81-
LanguageClient::GetInstance().SendNotification("textDocument/publishDiagnostics", vscodeDiagnosis);
86+
auto& options = LanguageClient::GetInstance().GetOptions();
8287

83-
return nullptr;
88+
std::shared_ptr<LuaParser> parser = LuaParser::LoadFromBuffer(std::move(text));
89+
parser->BuildAstWithComment();
90+
91+
LuaFormatter formatter(parser, options);
92+
formatter.BuildFormattedElement();
93+
94+
auto& edit = result->edits.emplace_back();
95+
edit.newText = formatter.GetFormattedText();
96+
edit.range = vscode::Range(
97+
vscode::Position(0, 0),
98+
vscode::Position(parser->GetLine(lastOffset), parser->GetColumn(lastOffset))
99+
);
100+
return result;
84101
}

CodeFormatServer/src/VSCode.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ std::shared_ptr<vscode::Serializable> vscode::MakeFromRequest(std::string_view m
2323
{
2424
return MakeRequestObject<DidChangeTextDocumentParams>(json);
2525
}
26+
else if (method == "textDocument/didOpen")
27+
{
28+
return MakeRequestObject<DidOpenTextDocumentParam>(json);
29+
}
30+
else if (method == "textDocument/formatting")
31+
{
32+
return MakeRequestObject<DocumentFormattingParams>(json);
33+
}
2634

2735
return nullptr;
2836
}
@@ -118,6 +126,15 @@ void vscode::TextDocument::Deserialize(nlohmann::json json)
118126
uri = json["uri"];
119127
}
120128

129+
nlohmann::json vscode::TextEdit::Serialize()
130+
{
131+
auto object = nlohmann::json::object();
132+
object["range"] = range.Serialize();
133+
object["newText"] = newText;
134+
135+
return object;
136+
}
137+
121138
nlohmann::json vscode::PublishDiagnosticsParams::Serialize()
122139
{
123140
auto object = nlohmann::json::object();
@@ -236,3 +253,40 @@ void vscode::DidChangeTextDocumentParams::Deserialize(nlohmann::json json)
236253

237254
textDocument.Deserialize(json["textDocument"]);
238255
}
256+
257+
void vscode::TextDocumentItem::Deserialize(nlohmann::json json)
258+
{
259+
uri = json["uri"];
260+
261+
languageId = json["languageId"];
262+
263+
text = json["text"];
264+
}
265+
266+
void vscode::DidOpenTextDocumentParam::Deserialize(nlohmann::json json)
267+
{
268+
textDocument.Deserialize(json["textDocument"]);
269+
}
270+
271+
void vscode::DocumentFormattingParams::Deserialize(nlohmann::json json)
272+
{
273+
textDocument.Deserialize(json["textDocument"]);
274+
}
275+
276+
nlohmann::json vscode::DocumentFormattingResult::Serialize()
277+
{
278+
if(hasError)
279+
{
280+
return nullptr;
281+
}
282+
else
283+
{
284+
auto array = nlohmann::json::array();
285+
for(auto& edit: edits)
286+
{
287+
array.push_back(edit.Serialize());
288+
}
289+
290+
return array;
291+
}
292+
}

include/CodeFormatServer/LanguageClient.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <memory>
44
#include "Session/IOSession.h"
5+
#include "CodeService/LuaFormatOptions.h"
56

67
class LanguageClient
78
{
@@ -14,7 +15,19 @@ class LanguageClient
1415

1516
void SendNotification(std::string_view method, std::shared_ptr<vscode::Serializable> param);
1617

18+
void CacheFile(const std::string& uri, std::string text);
19+
20+
void DiagnosticFile(const std::string& uri);
21+
22+
std::string GetFile(const std::string& uri);
23+
1724
void Run();
25+
26+
LuaFormatOptions& GetOptions();
1827
private:
1928
std::shared_ptr<IOSession> _session;
29+
// uri µ½file textµÄÓ³Éä
30+
std::map<std::string, std::string, std::less<>> _fileMap;
31+
32+
LuaFormatOptions _options;
2033
};

include/CodeFormatServer/LanguageService.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ class LanguageService
2323

2424
std::shared_ptr<vscode::Serializable> OnDidChange(std::shared_ptr<vscode::DidChangeTextDocumentParams> param);
2525

26-
// std::shared_ptr<JsonResponseProtocol> OnDocumentFormatting(std::shared_ptr<FormatRequestProtocol> request);
26+
std::shared_ptr<vscode::Serializable> OnDidOpen(std::shared_ptr<vscode::DidOpenTextDocumentParam> param);
27+
28+
std::shared_ptr<vscode::Serializable> OnFormatting(std::shared_ptr<vscode::DocumentFormattingParams> param);
2729

2830
std::map<std::string, MessageHandle, std::less<>> _handles;
2931
};

0 commit comments

Comments
 (0)