Skip to content

Commit 112ffc6

Browse files
committed
support textdocument/diagnostic
Fix #
1 parent 93dd7e1 commit 112ffc6

File tree

11 files changed

+157
-57
lines changed

11 files changed

+157
-57
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use lsp_types::ClientCapabilities;
2+
3+
#[derive(Debug)]
4+
pub struct LspFeatures {
5+
client_capabilities: ClientCapabilities,
6+
}
7+
8+
#[allow(unused)]
9+
impl LspFeatures {
10+
pub fn new(client_capabilities: ClientCapabilities) -> Self {
11+
Self {
12+
client_capabilities,
13+
}
14+
}
15+
16+
pub fn supports_multiline_tokens(&self) -> bool {
17+
if let Some(semantic) = &self.client_capabilities.text_document {
18+
if let Some(semantic) = &semantic.semantic_tokens {
19+
if let Some(supports) = semantic.multiline_token_support {
20+
return supports;
21+
}
22+
}
23+
}
24+
false
25+
}
26+
27+
pub fn supports_config_request(&self) -> bool {
28+
if let Some(workspace) = &self.client_capabilities.workspace {
29+
if let Some(supports) = workspace.configuration {
30+
return supports;
31+
}
32+
}
33+
false
34+
}
35+
36+
pub fn supports_pull_diagnostics(&self) -> bool {
37+
if let Some(text_document) = &self.client_capabilities.text_document {
38+
return text_document.diagnostic.is_some();
39+
}
40+
false
41+
}
42+
}

crates/emmylua_ls/src/context/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod client;
22
mod client_id;
33
mod file_diagnostic;
4+
mod lsp_features;
45
mod snapshot;
56
mod status_bar;
67
mod workspace_manager;
@@ -21,6 +22,7 @@ pub use workspace_manager::WorkspaceFileMatcher;
2122
pub use workspace_manager::WorkspaceManager;
2223
pub use workspace_manager::load_emmy_config;
2324

25+
use crate::context::lsp_features::LspFeatures;
2426
use crate::context::snapshot::ServerContextInner;
2527

2628
pub struct ServerContext {
@@ -31,7 +33,7 @@ pub struct ServerContext {
3133
}
3234

3335
impl ServerContext {
34-
pub fn new(conn: Connection, client_capabilities: Arc<ClientCapabilities>) -> Self {
36+
pub fn new(conn: Connection, client_capabilities: ClientCapabilities) -> Self {
3537
let client = Arc::new(ClientProxy::new(Connection {
3638
sender: conn.sender.clone(),
3739
receiver: conn.receiver.clone(),
@@ -50,6 +52,7 @@ impl ServerContext {
5052
status_bar.clone(),
5153
file_diagnostic.clone(),
5254
)));
55+
let lsp_features = Arc::new(LspFeatures::new(client_capabilities));
5356

5457
ServerContext {
5558
conn,
@@ -60,7 +63,7 @@ impl ServerContext {
6063
file_diagnostic,
6164
workspace_manager,
6265
status_bar,
63-
client_capabilities,
66+
lsp_features,
6467
}),
6568
}
6669
}

crates/emmylua_ls/src/context/snapshot.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use lsp_types::ClientCapabilities;
21
use std::sync::Arc;
32
use tokio::sync::RwLock;
43

54
use emmylua_code_analysis::EmmyLuaAnalysis;
65

6+
use crate::context::lsp_features::LspFeatures;
7+
78
use super::{
89
client::ClientProxy, file_diagnostic::FileDiagnostic, status_bar::StatusBar,
910
workspace_manager::WorkspaceManager,
@@ -39,8 +40,8 @@ impl ServerContextSnapshot {
3940
&self.inner.status_bar
4041
}
4142

42-
pub fn client_capabilities(&self) -> &ClientCapabilities {
43-
&self.inner.client_capabilities
43+
pub fn lsp_features(&self) -> &LspFeatures {
44+
&self.inner.lsp_features
4445
}
4546
}
4647

@@ -50,5 +51,5 @@ pub struct ServerContextInner {
5051
pub file_diagnostic: Arc<FileDiagnostic>,
5152
pub workspace_manager: Arc<RwLock<WorkspaceManager>>,
5253
pub status_bar: Arc<StatusBar>,
53-
pub client_capabilities: Arc<ClientCapabilities>,
54+
pub lsp_features: Arc<LspFeatures>,
5455
}

crates/emmylua_ls/src/handlers/configuration/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ pub async fn on_did_change_configuration(
2323

2424
drop(workspace_manager);
2525

26-
let supports_config_request = context
27-
.client_capabilities()
28-
.workspace
29-
.as_ref()?
30-
.configuration
31-
.unwrap_or_default();
26+
let supports_config_request = context.lsp_features().supports_config_request();
3227

3328
log::info!("change config client_id: {:?}", client_id);
3429
let new_client_config = get_client_config(&context, client_id, supports_config_request).await;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use lsp_types::{
2+
ClientCapabilities, DiagnosticOptions, DiagnosticServerCapabilities, DocumentDiagnosticParams,
3+
DocumentDiagnosticReport, DocumentDiagnosticReportResult, FullDocumentDiagnosticReport,
4+
RelatedFullDocumentDiagnosticReport, ServerCapabilities,
5+
};
6+
use tokio_util::sync::CancellationToken;
7+
8+
use crate::context::ServerContextSnapshot;
9+
10+
use super::RegisterCapabilities;
11+
12+
pub async fn on_pull_document_diagnostic(
13+
context: ServerContextSnapshot,
14+
params: DocumentDiagnosticParams,
15+
token: CancellationToken,
16+
) -> DocumentDiagnosticReportResult {
17+
let uri = params.text_document.uri;
18+
let analysis = context.analysis().read().await;
19+
let Some(file_id) = analysis.get_file_id(&uri) else {
20+
return default_diagnostic_report();
21+
};
22+
23+
let analysis = context.analysis().read().await;
24+
let diagnostics = analysis.diagnose_file(file_id, token).unwrap_or_default();
25+
26+
DocumentDiagnosticReport::Full(RelatedFullDocumentDiagnosticReport {
27+
related_documents: None,
28+
full_document_diagnostic_report: FullDocumentDiagnosticReport {
29+
result_id: None,
30+
items: diagnostics,
31+
},
32+
})
33+
.into()
34+
}
35+
36+
fn default_diagnostic_report() -> DocumentDiagnosticReportResult {
37+
DocumentDiagnosticReport::Full(RelatedFullDocumentDiagnosticReport {
38+
related_documents: None,
39+
full_document_diagnostic_report: FullDocumentDiagnosticReport {
40+
result_id: None,
41+
items: vec![],
42+
},
43+
})
44+
.into()
45+
}
46+
47+
pub struct DocumentDiagnosticCapabilities;
48+
49+
impl RegisterCapabilities for DocumentDiagnosticCapabilities {
50+
fn register_capabilities(server_capabilities: &mut ServerCapabilities, _: &ClientCapabilities) {
51+
server_capabilities.diagnostic_provider =
52+
Some(DiagnosticServerCapabilities::Options(DiagnosticOptions {
53+
identifier: Some("EmmyLua".to_string()),
54+
inter_file_dependencies: false,
55+
workspace_diagnostics: false,
56+
..Default::default()
57+
}))
58+
}
59+
}

crates/emmylua_ls/src/handlers/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod completion;
66
mod configuration;
77
mod definition;
88
mod document_color;
9+
mod document_diagnostic;
910
mod document_formatting;
1011
mod document_highlight;
1112
mod document_link;
@@ -75,6 +76,7 @@ capabilities!(modules: {
7576
document_highlight => DocumentHighlightCapabilities,
7677
document_formatting => DocumentFormattingCapabilities,
7778
document_range_formatting => DocumentRangeFormattingCapabilities,
79+
document_diagnostic => DocumentDiagnosticCapabilities,
7880
// document_type_format => DocumentTypeFormattingCapabilities,
7981
completion => CompletionCapabilities,
8082
inlay_hint => InlayHintCapabilities,

crates/emmylua_ls/src/handlers/request_handler.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@ use lsp_server::{Request, Response};
55
use lsp_types::request::{
66
CallHierarchyIncomingCalls, CallHierarchyOutgoingCalls, CallHierarchyPrepare,
77
CodeActionRequest, CodeLensRequest, CodeLensResolve, ColorPresentationRequest, Completion,
8-
DocumentColor, DocumentHighlightRequest, DocumentLinkRequest, DocumentLinkResolve,
9-
DocumentSymbolRequest, ExecuteCommand, FoldingRangeRequest, Formatting, GotoDefinition,
10-
GotoImplementation, HoverRequest, InlayHintRequest, InlayHintResolveRequest,
8+
DocumentColor, DocumentDiagnosticRequest, DocumentHighlightRequest, DocumentLinkRequest,
9+
DocumentLinkResolve, DocumentSymbolRequest, ExecuteCommand, FoldingRangeRequest, Formatting,
10+
GotoDefinition, GotoImplementation, HoverRequest, InlayHintRequest, InlayHintResolveRequest,
1111
InlineValueRequest, OnTypeFormatting, PrepareRenameRequest, RangeFormatting, References,
1212
Rename, Request as LspRequest, ResolveCompletionItem, SelectionRangeRequest,
1313
SemanticTokensFullRequest, SignatureHelpRequest, WorkspaceSymbolRequest,
1414
};
1515

16-
use crate::{context::ServerContext, handlers::document_type_format::on_type_formatting_handler};
16+
use crate::{
17+
context::ServerContext,
18+
handlers::{
19+
document_diagnostic::on_pull_document_diagnostic,
20+
document_type_format::on_type_formatting_handler,
21+
},
22+
};
1723

1824
use super::{
1925
call_hierarchy::{
@@ -112,6 +118,7 @@ pub async fn on_request_handler(
112118
CallHierarchyPrepare => on_prepare_call_hierarchy_handler,
113119
CallHierarchyIncomingCalls => on_incoming_calls_handler,
114120
CallHierarchyOutgoingCalls => on_outgoing_calls_handler,
121+
DocumentDiagnosticRequest => on_pull_document_diagnostic,
115122
});
116123

117124
Ok(())

crates/emmylua_ls/src/handlers/semantic_token/mod.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,18 @@ pub async fn on_semantic_token_handler(
3232
let client_id = workspace_manager.client_config.client_id;
3333
let _ = workspace_manager;
3434

35-
semantic_token(&analysis, file_id, context.client_capabilities(), client_id)
35+
semantic_token(
36+
&analysis,
37+
file_id,
38+
context.lsp_features().supports_multiline_tokens(),
39+
client_id,
40+
)
3641
}
3742

3843
pub fn semantic_token(
3944
analysis: &EmmyLuaAnalysis,
4045
file_id: FileId,
41-
client_capabilities: &ClientCapabilities,
46+
supports_multiline_tokens: bool,
4247
client_id: ClientId,
4348
) -> Option<SemanticTokensResult> {
4449
let semantic_model = analysis.compilation.get_semantic_model(file_id)?;
@@ -49,7 +54,7 @@ pub fn semantic_token(
4954

5055
let result = build_semantic_tokens(
5156
&semantic_model,
52-
supports_multiline_tokens(client_capabilities),
57+
supports_multiline_tokens,
5358
client_id,
5459
emmyrc,
5560
)?;
@@ -79,14 +84,3 @@ impl RegisterCapabilities for SemanticTokenCapabilities {
7984
);
8085
}
8186
}
82-
83-
fn supports_multiline_tokens(client_capability: &ClientCapabilities) -> bool {
84-
if let Some(text_document) = &client_capability.text_document
85-
&& let Some(support) = &text_document.semantic_tokens
86-
&& let Some(support) = &support.multiline_token_support
87-
{
88-
return *support;
89-
}
90-
91-
false
92-
}

crates/emmylua_ls/src/handlers/test_lib/mod.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ use emmylua_code_analysis::{EmmyLuaAnalysis, Emmyrc, FileId, VirtualUrlGenerator
22
use googletest::prelude::*;
33
use itertools::Itertools;
44
use lsp_types::{
5-
ClientCapabilities, CodeActionOrCommand, CompletionItem, CompletionItemKind,
6-
CompletionResponse, CompletionTriggerKind, GotoDefinitionResponse, Hover, HoverContents,
7-
InlayHintLabel, Location, MarkupContent, Position, SemanticTokenModifier, SemanticTokenType,
8-
SemanticTokensResult, SignatureHelpContext, SignatureHelpTriggerKind, SignatureInformation,
9-
TextEdit,
5+
CodeActionOrCommand, CompletionItem, CompletionItemKind, CompletionResponse,
6+
CompletionTriggerKind, GotoDefinitionResponse, Hover, HoverContents, InlayHintLabel, Location,
7+
MarkupContent, Position, SemanticTokenModifier, SemanticTokenType, SemanticTokensResult,
8+
SignatureHelpContext, SignatureHelpTriggerKind, SignatureInformation, TextEdit,
109
};
1110
use std::collections::HashSet;
1211
use std::{ops::Deref, sync::Arc};
@@ -493,14 +492,9 @@ impl ProviderVirtualWorkspace {
493492
expected: Vec<VirtualSemanticToken>,
494493
) -> Result<()> {
495494
let file_id = self.def(block_str);
496-
let result = semantic_token(
497-
&self.analysis,
498-
file_id,
499-
&ClientCapabilities::default(),
500-
ClientId::VSCode,
501-
)
502-
.ok_or("failed to get semantic tokens")
503-
.or_fail()?;
495+
let result = semantic_token(&self.analysis, file_id, true, ClientId::VSCode)
496+
.ok_or("failed to get semantic tokens")
497+
.or_fail()?;
504498
let SemanticTokensResult::Tokens(result) = result else {
505499
return fail!("expected SemanticTokensResult::Tokens, got {result:?}");
506500
};

crates/emmylua_ls/src/handlers/text_document/text_document_handler.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ pub async fn on_did_open_text_document(
2424
}
2525

2626
let file_id = analysis.update_file_by_uri(&uri, Some(text));
27-
let emmyrc = analysis.get_emmyrc();
28-
let interval = emmyrc.diagnostics.diagnostic_interval.unwrap_or(500);
29-
if let Some(file_id) = file_id {
30-
context
31-
.file_diagnostic()
32-
.add_diagnostic_task(file_id, interval)
33-
.await;
27+
if !context.lsp_features().supports_pull_diagnostics() {
28+
let emmyrc = analysis.get_emmyrc();
29+
let interval = emmyrc.diagnostics.diagnostic_interval.unwrap_or(500);
30+
if let Some(file_id) = file_id {
31+
context
32+
.file_diagnostic()
33+
.add_diagnostic_task(file_id, interval)
34+
.await;
35+
}
3436
}
3537

3638
let mut workspace = context.workspace_manager().write().await;
@@ -87,13 +89,14 @@ pub async fn on_did_change_text_document(
8789
workspace.extend_reindex_delay().await;
8890
drop(workspace);
8991
}
90-
if let Some(file_id) = file_id {
91-
context
92-
.file_diagnostic()
93-
.add_diagnostic_task(file_id, interval)
94-
.await;
92+
if !context.lsp_features().supports_pull_diagnostics() {
93+
if let Some(file_id) = file_id {
94+
context
95+
.file_diagnostic()
96+
.add_diagnostic_task(file_id, interval)
97+
.await;
98+
}
9599
}
96-
97100
Some(())
98101
}
99102

0 commit comments

Comments
 (0)