html_languageservice/
html_language_service.rs

1#[cfg(any(feature = "completion", feature = "hover"))]
2use crate::html_language_types::HTMLLanguageServiceOptions;
3use crate::parser::html_document::HTMLDocument;
4use crate::parser::html_parse::HTMLParser;
5use crate::parser::html_scanner::{Scanner, ScannerState};
6#[cfg(feature = "completion")]
7use crate::participant::ICompletionParticipant;
8#[cfg(feature = "hover")]
9use crate::participant::IHoverParticipant;
10#[cfg(feature = "completion")]
11use crate::services::html_completion::HTMLCompletion;
12#[cfg(feature = "folding")]
13use crate::services::html_folding;
14#[cfg(feature = "formatter")]
15use crate::services::html_formatter;
16#[cfg(feature = "highlight")]
17use crate::services::html_highlight;
18#[cfg(feature = "hover")]
19use crate::services::html_hover::HTMLHover;
20#[cfg(feature = "linked_editing")]
21use crate::services::html_linked_editing;
22#[cfg(feature = "links")]
23use crate::services::html_links;
24#[cfg(feature = "matching_tag_position")]
25use crate::services::html_matching_tag_position;
26#[cfg(feature = "rename")]
27use crate::services::html_rename;
28#[cfg(feature = "selection_range")]
29use crate::services::html_selection_range;
30#[cfg(feature = "symbols")]
31use crate::services::html_symbols;
32
33#[cfg(feature = "formatter")]
34use crate::HTMLFormatConfiguration;
35
36#[cfg(feature = "completion")]
37use crate::CompletionConfiguration;
38#[cfg(any(feature = "completion", feature = "links"))]
39use crate::DocumentContext;
40#[cfg(feature = "folding")]
41use crate::FoldingRangeContext;
42use crate::HTMLDataManager;
43#[cfg(feature = "hover")]
44use crate::HoverSettings;
45
46#[cfg(feature = "completion")]
47use lsp_types::CompletionList;
48#[cfg(feature = "highlight")]
49use lsp_types::DocumentHighlight;
50#[cfg(feature = "links")]
51use lsp_types::DocumentLink;
52#[cfg(feature = "folding")]
53use lsp_types::FoldingRange;
54#[cfg(feature = "hover")]
55use lsp_types::Hover;
56#[cfg(any(
57    feature = "formatter",
58    feature = "completion",
59    feature = "hover",
60    feature = "highlight",
61    feature = "selection_range",
62    feature = "rename",
63    feature = "matching_tag_position",
64    feature = "linked_editing"
65))]
66use lsp_types::Position;
67#[cfg(any(feature = "formatter", feature = "linked_editing"))]
68use lsp_types::Range;
69#[cfg(feature = "selection_range")]
70use lsp_types::SelectionRange;
71#[cfg(feature = "formatter")]
72use lsp_types::TextEdit;
73#[cfg(any(feature = "links", feature = "symbols", feature = "rename"))]
74use lsp_types::Url;
75#[cfg(feature = "rename")]
76use lsp_types::WorkspaceEdit;
77#[cfg(feature = "symbols")]
78use lsp_types::{DocumentSymbol, SymbolInformation};
79
80use lsp_textdocument::FullTextDocument;
81
82/// This is a collection of features necessary to implement an HTML language server
83///
84/// Make sure you activated the features you need of the `html-languageservice` crate on `Cargo.toml`
85///
86/// # Features
87///
88/// - completion
89/// - hover
90/// - formatter
91/// - highlight
92/// - links
93/// - symbols
94/// - folding
95/// - selection_range
96/// - rename
97/// - matching_tag_position
98/// - linked_editing
99pub struct HTMLLanguageService {
100    #[cfg(feature = "completion")]
101    html_completion: HTMLCompletion,
102    #[cfg(feature = "hover")]
103    html_hover: HTMLHover,
104}
105
106impl HTMLLanguageService {
107    #[cfg(any(feature = "completion", feature = "hover"))]
108    pub fn new(options: &HTMLLanguageServiceOptions) -> HTMLLanguageService {
109        HTMLLanguageService {
110            #[cfg(feature = "completion")]
111            html_completion: HTMLCompletion::new(options),
112            #[cfg(feature = "hover")]
113            html_hover: HTMLHover::new(options),
114        }
115    }
116
117    pub fn create_scanner(input: &str, initial_offset: usize) -> Scanner {
118        Scanner::new(input, initial_offset, ScannerState::WithinContent, false)
119    }
120
121    pub fn parse_html_document(
122        document: &FullTextDocument,
123        data_manager: &HTMLDataManager,
124    ) -> HTMLDocument {
125        HTMLParser::parse_document(document, data_manager)
126    }
127
128    /// Provide completion proposals for a given location
129    #[cfg(feature = "completion")]
130    pub async fn do_complete(
131        &self,
132        document: &FullTextDocument,
133        position: &Position,
134        html_document: &HTMLDocument,
135        document_context: impl DocumentContext,
136        settings: Option<&CompletionConfiguration>,
137        data_manager: &HTMLDataManager,
138    ) -> CompletionList {
139        self.html_completion
140            .do_complete(
141                document,
142                position,
143                html_document,
144                document_context,
145                settings,
146                data_manager,
147            )
148            .await
149    }
150
151    /// Add additional completion items to the completion proposal
152    #[cfg(feature = "completion")]
153    pub fn set_completion_participants(
154        &mut self,
155        completion_participants: Vec<Box<dyn ICompletionParticipant>>,
156    ) {
157        self.html_completion
158            .set_completion_participants(completion_participants);
159    }
160
161    /// Provide quotes completion when `=` is entered
162    #[cfg(feature = "completion")]
163    pub fn do_quote_complete(
164        document: &FullTextDocument,
165        position: &Position,
166        html_document: &HTMLDocument,
167        settings: Option<&CompletionConfiguration>,
168    ) -> Option<String> {
169        HTMLCompletion::do_quote_complete(document, position, html_document, settings)
170    }
171
172    /// Completes the tag when `>` or `/` is entered
173    #[cfg(feature = "completion")]
174    pub fn do_tag_complete(
175        &self,
176        document: &FullTextDocument,
177        position: &Position,
178        html_document: &HTMLDocument,
179        data_manager: &HTMLDataManager,
180    ) -> Option<String> {
181        self.html_completion
182            .do_tag_complete(document, position, html_document, data_manager)
183    }
184
185    /// Provides hover information at a given location
186    #[cfg(feature = "hover")]
187    pub async fn do_hover(
188        &self,
189        document: &FullTextDocument,
190        position: &Position,
191        html_document: &HTMLDocument,
192        options: Option<HoverSettings>,
193        data_manager: &HTMLDataManager,
194    ) -> Option<Hover> {
195        self.html_hover
196            .do_hover(document, position, html_document, options, data_manager)
197            .await
198    }
199
200    /// Add additional hover to the hover proposal
201    #[cfg(feature = "hover")]
202    pub fn set_hover_participants(&mut self, hover_participants: Vec<Box<dyn IHoverParticipant>>) {
203        self.html_hover.set_hover_participants(hover_participants);
204    }
205
206    /// Formats the code at the given range
207    ///
208    /// Note: `format` is not prefect, it's under development
209    #[cfg(feature = "formatter")]
210    pub fn format(
211        document: &FullTextDocument,
212        range: Option<Range>,
213        options: &HTMLFormatConfiguration,
214    ) -> Vec<TextEdit> {
215        html_formatter::format(document, &range, options)
216    }
217
218    /// Provides document highlights capability
219    #[cfg(feature = "highlight")]
220    pub fn find_document_highlights(
221        document: &FullTextDocument,
222        position: &Position,
223        html_document: &HTMLDocument,
224    ) -> Vec<DocumentHighlight> {
225        html_highlight::find_document_highlights(document, position, html_document)
226    }
227
228    /// Finds all links in the document
229    #[cfg(feature = "links")]
230    pub fn find_document_links(
231        uri: &Url,
232        document: &FullTextDocument,
233        document_context: &impl DocumentContext,
234        data_manager: &HTMLDataManager,
235    ) -> Vec<DocumentLink> {
236        html_links::find_document_links(uri, document, document_context, data_manager)
237    }
238
239    /// Finds all the symbols in the document, it returns `SymbolInformation`
240    #[cfg(feature = "symbols")]
241    pub fn find_document_symbols(
242        uri: &Url,
243        document: &FullTextDocument,
244        html_document: &HTMLDocument,
245    ) -> Vec<SymbolInformation> {
246        html_symbols::find_document_symbols(uri, document, html_document)
247    }
248
249    /// Finds all the symbols in the document, it returns `DocumentSymbol`
250    #[cfg(feature = "symbols")]
251    pub fn find_document_symbols2(
252        document: &FullTextDocument,
253        html_document: &HTMLDocument,
254    ) -> Vec<DocumentSymbol> {
255        html_symbols::find_document_symbols2(document, html_document)
256    }
257
258    /// Get folding ranges for the given document
259    #[cfg(feature = "folding")]
260    pub fn get_folding_ranges(
261        document: FullTextDocument,
262        context: FoldingRangeContext,
263        data_manager: &HTMLDataManager,
264    ) -> Vec<FoldingRange> {
265        html_folding::get_folding_ranges(document, context, data_manager)
266    }
267
268    /// Get the selection ranges for the given document
269    #[cfg(feature = "selection_range")]
270    pub fn get_selection_ranges(
271        document: &FullTextDocument,
272        positions: &Vec<Position>,
273        html_document: &HTMLDocument,
274    ) -> Vec<SelectionRange> {
275        html_selection_range::get_selection_ranges(document, positions, html_document)
276    }
277
278    /// Rename the matching tag
279    #[cfg(feature = "rename")]
280    pub fn do_rename(
281        uri: Url,
282        document: &FullTextDocument,
283        position: Position,
284        new_name: &str,
285        html_document: &HTMLDocument,
286    ) -> Option<WorkspaceEdit> {
287        html_rename::do_rename(uri, document, position, new_name, html_document)
288    }
289
290    /// Get the location of the matching tag
291    #[cfg(feature = "matching_tag_position")]
292    pub fn find_matching_tag_position(
293        document: &FullTextDocument,
294        position: Position,
295        html_document: &HTMLDocument,
296    ) -> Option<Position> {
297        html_matching_tag_position::find_matching_tag_position(document, position, html_document)
298    }
299
300    /// Provides linked editing range capability
301    #[cfg(feature = "linked_editing")]
302    pub fn find_linked_editing_ranges(
303        document: &FullTextDocument,
304        position: Position,
305        html_document: &HTMLDocument,
306    ) -> Option<Vec<Range>> {
307        html_linked_editing::find_linked_editing_ranges(document, position, html_document)
308    }
309}