mod build;
#[cfg(feature = "completion")]
mod completion;
mod cursor;
mod definition;
mod folding;
mod formatting;
mod forward_search;
mod highlight;
mod hover;
mod link;
mod lsp_kinds;
mod reference;
mod rename;
#[cfg(feature = "semantic")]
mod semantic;
mod symbol;
use std::sync::Arc;
use crate::{Document, ServerContext, Workspace, WorkspaceSubset};
#[cfg(feature = "completion")]
pub use self::completion::{complete, CompletionItemData, COMPLETION_LIMIT};
#[cfg(feature = "semantic")]
pub use self::semantic::{find_semantic_tokens_range, legend};
pub use self::{
build::{BuildEngine, BuildParams, BuildResult, BuildStatus},
definition::goto_definition,
folding::find_foldings,
formatting::format_source_code,
forward_search::{execute_forward_search, ForwardSearchResult, ForwardSearchStatus},
highlight::find_document_highlights,
hover::find_hover,
link::find_document_links,
reference::find_all_references,
rename::{prepare_rename_all, rename_all},
symbol::{find_document_symbols, find_workspace_symbols},
};
#[derive(Clone)]
pub struct FeatureRequest
{
pub context: Arc,
pub params: P,
pub workspace: Arc,
pub subset: WorkspaceSubset,
}
impl FeatureRequest
{
pub fn main_document(&self) -> &Document {
&self.subset.documents[0]
}
}
#[cfg(test)]
mod testing {
use std::{path::PathBuf, sync::Arc};
use lsp_types::{
ClientCapabilities, ClientInfo, CompletionParams, DocumentFormattingParams,
DocumentHighlightParams, DocumentLinkParams, FoldingRangeParams, FormattingOptions,
GotoDefinitionParams, HoverParams, PartialResultParams, Position, ReferenceContext,
ReferenceParams, RenameParams, TextDocumentIdentifier, TextDocumentPositionParams,
WorkDoneProgressParams,
};
use typed_builder::TypedBuilder;
use crate::{
create_workspace_fast, distro::Resolver, DocumentLanguage, Options, ServerContext, Uri,
Workspace, WorkspaceSource,
};
use super::*;
#[derive(Debug, Clone, TypedBuilder)]
pub struct FeatureTester<'a> {
main: &'a str,
files: Vec<(&'a str, &'a str)>,
#[builder(default)]
line: u32,
#[builder(default)]
character: u32,
#[builder(default)]
new_name: &'a str,
#[builder(default)]
include_declaration: bool,
#[builder(default)]
client_capabilities: ClientCapabilities,
#[builder(default)]
client_info: Option,
#[builder(default)]
resolver: Resolver,
#[builder(default=std::env::temp_dir())]
current_directory: PathBuf,
#[builder(default, setter(strip_option))]
root_directory: Option,
#[builder(default, setter(strip_option))]
aux_directory: Option,
}
impl<'a> FeatureTester<'a> {
pub fn uri(&self, name: &str) -> Arc {
let path = self.current_directory.join(name);
Arc::new(Uri::from_file_path(path).unwrap())
}
fn options(&self) -> Options {
let mut options = Options::default();
options.aux_directory = self.aux_directory.clone();
options.root_directory = self.root_directory.clone();
options
}
fn identifier(&self) -> TextDocumentIdentifier {
let uri = self.uri(&self.main);
TextDocumentIdentifier::new(uri.as_ref().clone().into())
}
fn context(&self) -> Arc {
let cx = ServerContext::new(self.current_directory.clone());
*cx.client_capabilities.lock().unwrap() = self.client_capabilities.clone();
*cx.client_info.lock().unwrap() = self.client_info.clone();
*cx.options.write().unwrap() = self.options();
*cx.resolver.lock().unwrap() = self.resolver.clone();
Arc::new(cx)
}
fn workspace(&self, cx: Arc) -> Arc {
let workspace = create_workspace_fast(cx).unwrap();
for (name, source_code) in &self.files {
let uri = self.uri(name);
let path = uri.to_file_path().unwrap();
let language = DocumentLanguage::by_path(&path).expect("unknown document language");
workspace.open(
uri,
source_code.trim().to_string(),
language,
WorkspaceSource::Client,
);
}
Arc::new(workspace)
}
fn request(&self, params: P) -> FeatureRequest
{
let cx = self.context();
let workspace = self.workspace(Arc::clone(&cx));
let subset = workspace.subset(self.uri(self.main)).unwrap();
FeatureRequest {
context: cx,
workspace,
subset,
params,
}
}
pub fn link(self) -> FeatureRequest {
let text_document = self.identifier();
let params = DocumentLinkParams {
text_document,
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
self.request(params)
}
pub fn folding(self) -> FeatureRequest {
let text_document = self.identifier();
let params = FoldingRangeParams {
text_document,
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
self.request(params)
}
pub fn reference(self) -> FeatureRequest {
let params = ReferenceParams {
text_document_position: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
context: ReferenceContext {
include_declaration: self.include_declaration,
},
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
self.request(params)
}
pub fn hover(self) -> FeatureRequest {
let params = HoverParams {
text_document_position_params: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
work_done_progress_params: WorkDoneProgressParams::default(),
};
self.request(params)
}
pub fn completion(self) -> FeatureRequest {
let params = CompletionParams {
text_document_position: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
context: None,
};
self.request(params)
}
pub fn definition(self) -> FeatureRequest {
let params = GotoDefinitionParams {
text_document_position_params: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
self.request(params)
}
pub fn rename(self) -> FeatureRequest {
let params = RenameParams {
text_document_position: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
new_name: self.new_name.to_string(),
work_done_progress_params: WorkDoneProgressParams::default(),
};
self.request(params)
}
pub fn formatting(self) -> FeatureRequest {
let params = DocumentFormattingParams {
text_document: self.identifier(),
work_done_progress_params: WorkDoneProgressParams::default(),
options: FormattingOptions::default(),
};
self.request(params)
}
pub fn highlight(self) -> FeatureRequest {
let params = DocumentHighlightParams {
text_document_position_params: TextDocumentPositionParams::new(
self.identifier(),
Position::new(self.line, self.character),
),
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
self.request(params)
}
}
}