|
1 | 1 | use crate::{adapters, diagnostics::LspError, session::Session}; |
| 2 | +use pgls_text_size::TextRange; |
2 | 3 | use pgls_workspace::features::semantic_tokens::SemanticTokensParams; |
3 | 4 | use tower_lsp::lsp_types::{self, SemanticToken, SemanticTokens, SemanticTokensRangeResult}; |
4 | 5 |
|
5 | 6 | /// Handles a full semantic tokens request. |
6 | | -/// Returns all semantic tokens for the entire document. |
7 | 7 | #[tracing::instrument(level = "debug", skip(session), err)] |
8 | 8 | pub fn semantic_tokens_full( |
9 | 9 | session: &Session, |
10 | 10 | params: lsp_types::SemanticTokensParams, |
11 | 11 | ) -> Result<Option<lsp_types::SemanticTokensResult>, LspError> { |
12 | 12 | let url = ¶ms.text_document.uri; |
13 | | - let path = session.file_path(url)?; |
14 | | - let doc = session.document(url)?; |
15 | | - let encoding = adapters::negotiated_encoding(session.client_capabilities().unwrap()); |
16 | | - |
17 | | - let workspace_result = session |
18 | | - .workspace |
19 | | - .get_semantic_tokens(SemanticTokensParams { path, range: None })?; |
20 | | - |
21 | | - let lsp_tokens = encode_tokens(&workspace_result.tokens, &doc.line_index, encoding)?; |
22 | | - |
23 | | - Ok(Some(lsp_types::SemanticTokensResult::Tokens( |
24 | | - SemanticTokens { |
25 | | - result_id: None, |
26 | | - data: lsp_tokens, |
27 | | - }, |
28 | | - ))) |
| 13 | + let tokens = get_semantic_tokens(session, url, None)?; |
| 14 | + Ok(Some(lsp_types::SemanticTokensResult::Tokens(tokens))) |
29 | 15 | } |
30 | 16 |
|
31 | 17 | /// Handles a range semantic tokens request. |
32 | | -/// Returns semantic tokens for the specified range only. |
33 | 18 | #[tracing::instrument(level = "debug", skip(session), err)] |
34 | 19 | pub fn semantic_tokens_range( |
35 | 20 | session: &Session, |
36 | 21 | params: lsp_types::SemanticTokensRangeParams, |
37 | 22 | ) -> Result<Option<SemanticTokensRangeResult>, LspError> { |
38 | 23 | let url = ¶ms.text_document.uri; |
| 24 | + let tokens = get_semantic_tokens(session, url, Some(params.range))?; |
| 25 | + Ok(Some(SemanticTokensRangeResult::Tokens(tokens))) |
| 26 | +} |
| 27 | + |
| 28 | +/// Common implementation for semantic tokens requests. |
| 29 | +fn get_semantic_tokens( |
| 30 | + session: &Session, |
| 31 | + url: &lsp_types::Url, |
| 32 | + range: Option<lsp_types::Range>, |
| 33 | +) -> Result<SemanticTokens, LspError> { |
39 | 34 | let path = session.file_path(url)?; |
40 | 35 | let doc = session.document(url)?; |
41 | 36 | let encoding = adapters::negotiated_encoding(session.client_capabilities().unwrap()); |
42 | 37 |
|
43 | | - // Convert LSP range to TextRange |
44 | | - let start_offset = |
45 | | - adapters::from_lsp::offset(&doc.line_index, params.range.start, encoding)?; |
46 | | - let end_offset = adapters::from_lsp::offset(&doc.line_index, params.range.end, encoding)?; |
47 | | - let range = pgls_text_size::TextRange::new(start_offset, end_offset); |
| 38 | + let text_range = range |
| 39 | + .map(|r| -> Result<TextRange, LspError> { |
| 40 | + let start = adapters::from_lsp::offset(&doc.line_index, r.start, encoding)?; |
| 41 | + let end = adapters::from_lsp::offset(&doc.line_index, r.end, encoding)?; |
| 42 | + Ok(TextRange::new(start, end)) |
| 43 | + }) |
| 44 | + .transpose()?; |
48 | 45 |
|
49 | 46 | let workspace_result = session |
50 | 47 | .workspace |
51 | 48 | .get_semantic_tokens(SemanticTokensParams { |
52 | 49 | path, |
53 | | - range: Some(range), |
| 50 | + range: text_range, |
54 | 51 | })?; |
55 | 52 |
|
56 | 53 | let lsp_tokens = encode_tokens(&workspace_result.tokens, &doc.line_index, encoding)?; |
57 | 54 |
|
58 | | - Ok(Some(SemanticTokensRangeResult::Tokens(SemanticTokens { |
| 55 | + Ok(SemanticTokens { |
59 | 56 | result_id: None, |
60 | 57 | data: lsp_tokens, |
61 | | - }))) |
| 58 | + }) |
62 | 59 | } |
63 | 60 |
|
64 | 61 | /// Encodes workspace semantic tokens into the LSP delta-encoded format. |
|
0 commit comments