mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 18:43:01 +00:00
Merge pull request #18998 from ChayimFriedman2/exclude
fix: Make `rust-analyzer.files.excludeDirs` work, actually
This commit is contained in:
commit
78e7515a30
15 changed files with 262 additions and 131 deletions
|
|
@ -94,7 +94,9 @@ pub fn load_workspace(
|
|||
let contents = loader.load_sync(path);
|
||||
let path = vfs::VfsPath::from(path.to_path_buf());
|
||||
vfs.set_file_contents(path.clone(), contents);
|
||||
vfs.file_id(&path)
|
||||
vfs.file_id(&path).and_then(|(file_id, excluded)| {
|
||||
(excluded == vfs::FileExcluded::No).then_some(file_id)
|
||||
})
|
||||
},
|
||||
extra_env,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ config_data! {
|
|||
completion_snippets_custom: FxHashMap<String, SnippetDef> = Config::completion_snippets_default(),
|
||||
|
||||
|
||||
/// These directories will be ignored by rust-analyzer. They are
|
||||
/// These paths (file/directories) will be ignored by rust-analyzer. They are
|
||||
/// relative to the workspace root, and globs are not supported. You may
|
||||
/// also need to add the folders to Code's `files.watcherExclude`.
|
||||
files_excludeDirs: Vec<Utf8PathBuf> = vec![],
|
||||
files_exclude | files_excludeDirs: Vec<Utf8PathBuf> = vec![],
|
||||
|
||||
|
||||
|
||||
|
|
@ -1792,7 +1792,7 @@ impl Config {
|
|||
|
||||
fn discovered_projects(&self) -> Vec<ManifestOrProjectJson> {
|
||||
let exclude_dirs: Vec<_> =
|
||||
self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect();
|
||||
self.files_exclude().iter().map(|p| self.root_path.join(p)).collect();
|
||||
|
||||
let mut projects = vec![];
|
||||
for fs_proj in &self.discovered_projects_from_filesystem {
|
||||
|
|
@ -1914,10 +1914,14 @@ impl Config {
|
|||
}
|
||||
_ => FilesWatcher::Server,
|
||||
},
|
||||
exclude: self.files_excludeDirs().iter().map(|it| self.root_path.join(it)).collect(),
|
||||
exclude: self.excluded().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn excluded(&self) -> impl Iterator<Item = AbsPathBuf> + use<'_> {
|
||||
self.files_exclude().iter().map(|it| self.root_path.join(it))
|
||||
}
|
||||
|
||||
pub fn notifications(&self) -> NotificationsConfig {
|
||||
NotificationsConfig {
|
||||
cargo_toml_not_found: self.notifications_cargoTomlNotFound().to_owned(),
|
||||
|
|
|
|||
|
|
@ -650,7 +650,8 @@ impl GlobalStateSnapshot {
|
|||
RwLockReadGuard::map(self.vfs.read(), |(it, _)| it)
|
||||
}
|
||||
|
||||
pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result<FileId> {
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result<Option<FileId>> {
|
||||
url_to_file_id(&self.vfs_read(), url)
|
||||
}
|
||||
|
||||
|
|
@ -658,7 +659,8 @@ impl GlobalStateSnapshot {
|
|||
file_id_to_url(&self.vfs_read(), id)
|
||||
}
|
||||
|
||||
pub(crate) fn vfs_path_to_file_id(&self, vfs_path: &VfsPath) -> anyhow::Result<FileId> {
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn vfs_path_to_file_id(&self, vfs_path: &VfsPath) -> anyhow::Result<Option<FileId>> {
|
||||
vfs_path_to_file_id(&self.vfs_read(), vfs_path)
|
||||
}
|
||||
|
||||
|
|
@ -750,14 +752,21 @@ pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
|
|||
url_from_abs_path(path)
|
||||
}
|
||||
|
||||
pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result<FileId> {
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result<Option<FileId>> {
|
||||
let path = from_proto::vfs_path(url)?;
|
||||
let res = vfs.file_id(&path).ok_or_else(|| anyhow::format_err!("file not found: {path}"))?;
|
||||
Ok(res)
|
||||
vfs_path_to_file_id(vfs, &path)
|
||||
}
|
||||
|
||||
pub(crate) fn vfs_path_to_file_id(vfs: &vfs::Vfs, vfs_path: &VfsPath) -> anyhow::Result<FileId> {
|
||||
let res =
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn vfs_path_to_file_id(
|
||||
vfs: &vfs::Vfs,
|
||||
vfs_path: &VfsPath,
|
||||
) -> anyhow::Result<Option<FileId>> {
|
||||
let (file_id, excluded) =
|
||||
vfs.file_id(vfs_path).ok_or_else(|| anyhow::format_err!("file not found: {vfs_path}"))?;
|
||||
Ok(res)
|
||||
match excluded {
|
||||
vfs::FileExcluded::Yes => Ok(None),
|
||||
vfs::FileExcluded::No => Ok(Some(file_id)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use crate::{
|
|||
mem_docs::DocumentData,
|
||||
reload,
|
||||
target_spec::TargetSpec,
|
||||
try_default,
|
||||
};
|
||||
|
||||
pub(crate) fn handle_cancel(state: &mut GlobalState, params: CancelParams) -> anyhow::Result<()> {
|
||||
|
|
@ -74,6 +75,14 @@ pub(crate) fn handle_did_open_text_document(
|
|||
tracing::error!("duplicate DidOpenTextDocument: {}", path);
|
||||
}
|
||||
|
||||
if let Some(abs_path) = path.as_path() {
|
||||
if state.config.excluded().any(|excluded| abs_path.starts_with(&excluded)) {
|
||||
tracing::trace!("opened excluded file {abs_path}");
|
||||
state.vfs.write().0.insert_excluded_file(path);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let contents = params.text_document.text.into_bytes();
|
||||
state.vfs.write().0.set_file_contents(path, Some(contents));
|
||||
if state.config.discover_workspace_config().is_some() {
|
||||
|
|
@ -127,7 +136,8 @@ pub(crate) fn handle_did_close_text_document(
|
|||
tracing::error!("orphan DidCloseTextDocument: {}", path);
|
||||
}
|
||||
|
||||
if let Some(file_id) = state.vfs.read().0.file_id(&path) {
|
||||
// Clear diagnostics also for excluded files, just in case.
|
||||
if let Some((file_id, _)) = state.vfs.read().0.file_id(&path) {
|
||||
state.diagnostics.clear_native_for(file_id);
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +156,7 @@ pub(crate) fn handle_did_save_text_document(
|
|||
) -> anyhow::Result<()> {
|
||||
if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) {
|
||||
let snap = state.snapshot();
|
||||
let file_id = snap.vfs_path_to_file_id(&vfs_path)?;
|
||||
let file_id = try_default!(snap.vfs_path_to_file_id(&vfs_path)?);
|
||||
let sr = snap.analysis.source_root_id(file_id)?;
|
||||
|
||||
if state.config.script_rebuild_on_save(Some(sr)) && state.build_deps_changed {
|
||||
|
|
@ -290,7 +300,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
|
|||
let _p = tracing::info_span!("run_flycheck").entered();
|
||||
|
||||
let file_id = state.vfs.read().0.file_id(&vfs_path);
|
||||
if let Some(file_id) = file_id {
|
||||
if let Some((file_id, vfs::FileExcluded::No)) = file_id {
|
||||
let world = state.snapshot();
|
||||
let invocation_strategy_once = state.config.flycheck(None).invocation_strategy_once();
|
||||
let may_flycheck_workspace = state.config.flycheck_workspace(None);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ use crate::{
|
|||
},
|
||||
target_spec::{CargoTargetSpec, TargetSpec},
|
||||
test_runner::{CargoTestHandle, TestTarget},
|
||||
try_default,
|
||||
};
|
||||
|
||||
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
|
||||
|
|
@ -83,7 +84,8 @@ pub(crate) fn handle_analyzer_status(
|
|||
let mut file_id = None;
|
||||
if let Some(tdi) = params.text_document {
|
||||
match from_proto::file_id(&snap, &tdi.uri) {
|
||||
Ok(it) => file_id = Some(it),
|
||||
Ok(Some(it)) => file_id = Some(it),
|
||||
Ok(None) => {}
|
||||
Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri),
|
||||
}
|
||||
}
|
||||
|
|
@ -141,7 +143,7 @@ pub(crate) fn handle_view_syntax_tree(
|
|||
params: lsp_ext::ViewSyntaxTreeParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let _p = tracing::info_span!("handle_view_syntax_tree").entered();
|
||||
let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let res = snap.analysis.view_syntax_tree(id)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -151,7 +153,7 @@ pub(crate) fn handle_view_hir(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let _p = tracing::info_span!("handle_view_hir").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
let res = snap.analysis.view_hir(position)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -161,7 +163,7 @@ pub(crate) fn handle_view_mir(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let _p = tracing::info_span!("handle_view_mir").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
let res = snap.analysis.view_mir(position)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -171,7 +173,7 @@ pub(crate) fn handle_interpret_function(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let _p = tracing::info_span!("handle_interpret_function").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
let res = snap.analysis.interpret_function(position)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -180,7 +182,7 @@ pub(crate) fn handle_view_file_text(
|
|||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::TextDocumentIdentifier,
|
||||
) -> anyhow::Result<String> {
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.uri)?);
|
||||
Ok(snap.analysis.file_text(file_id)?.to_string())
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ pub(crate) fn handle_view_item_tree(
|
|||
params: lsp_ext::ViewItemTreeParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let _p = tracing::info_span!("handle_view_item_tree").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let res = snap.analysis.view_item_tree(file_id)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -315,7 +317,7 @@ pub(crate) fn handle_expand_macro(
|
|||
params: lsp_ext::ExpandMacroParams,
|
||||
) -> anyhow::Result<Option<lsp_ext::ExpandedMacro>> {
|
||||
let _p = tracing::info_span!("handle_expand_macro").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let offset = from_proto::offset(&line_index, params.position)?;
|
||||
|
||||
|
|
@ -328,7 +330,7 @@ pub(crate) fn handle_selection_range(
|
|||
params: lsp_types::SelectionRangeParams,
|
||||
) -> anyhow::Result<Option<Vec<lsp_types::SelectionRange>>> {
|
||||
let _p = tracing::info_span!("handle_selection_range").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let res: anyhow::Result<Vec<lsp_types::SelectionRange>> = params
|
||||
.positions
|
||||
|
|
@ -371,7 +373,7 @@ pub(crate) fn handle_matching_brace(
|
|||
params: lsp_ext::MatchingBraceParams,
|
||||
) -> anyhow::Result<Vec<Position>> {
|
||||
let _p = tracing::info_span!("handle_matching_brace").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
params
|
||||
.positions
|
||||
|
|
@ -395,7 +397,7 @@ pub(crate) fn handle_join_lines(
|
|||
) -> anyhow::Result<Vec<lsp_types::TextEdit>> {
|
||||
let _p = tracing::info_span!("handle_join_lines").entered();
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let config = snap.config.join_lines();
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
|
|
@ -419,7 +421,7 @@ pub(crate) fn handle_on_enter(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
|
||||
let _p = tracing::info_span!("handle_on_enter").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
let edit = match snap.analysis.on_enter(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
|
|
@ -439,7 +441,8 @@ pub(crate) fn handle_on_type_formatting(
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
let mut position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position)?);
|
||||
let line_index = snap.file_line_index(position.file_id)?;
|
||||
|
||||
// in `ide`, the `on_type` invariant is that
|
||||
|
|
@ -465,32 +468,33 @@ pub(crate) fn handle_on_type_formatting(
|
|||
Ok(Some(change))
|
||||
}
|
||||
|
||||
pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportResult {
|
||||
lsp_types::DocumentDiagnosticReportResult::Report(lsp_types::DocumentDiagnosticReport::Full(
|
||||
lsp_types::RelatedFullDocumentDiagnosticReport {
|
||||
related_documents: None,
|
||||
full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport {
|
||||
result_id: Some("rust-analyzer".to_owned()),
|
||||
items: vec![],
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn handle_document_diagnostics(
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::DocumentDiagnosticParams,
|
||||
) -> anyhow::Result<lsp_types::DocumentDiagnosticReportResult> {
|
||||
let empty = || {
|
||||
lsp_types::DocumentDiagnosticReportResult::Report(
|
||||
lsp_types::DocumentDiagnosticReport::Full(
|
||||
lsp_types::RelatedFullDocumentDiagnosticReport {
|
||||
related_documents: None,
|
||||
full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport {
|
||||
result_id: Some("rust-analyzer".to_owned()),
|
||||
items: vec![],
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
let file_id = match from_proto::file_id(&snap, ¶ms.text_document.uri)? {
|
||||
Some(it) => it,
|
||||
None => return Ok(empty_diagnostic_report()),
|
||||
};
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let source_root = snap.analysis.source_root_id(file_id)?;
|
||||
if !snap.analysis.is_local_source_root(source_root)? {
|
||||
return Ok(empty());
|
||||
return Ok(empty_diagnostic_report());
|
||||
}
|
||||
let config = snap.config.diagnostics(Some(source_root));
|
||||
if !config.enabled {
|
||||
return Ok(empty());
|
||||
return Ok(empty_diagnostic_report());
|
||||
}
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let supports_related = snap.config.text_document_diagnostic_related_document_support();
|
||||
|
|
@ -546,7 +550,7 @@ pub(crate) fn handle_document_symbol(
|
|||
params: lsp_types::DocumentSymbolParams,
|
||||
) -> anyhow::Result<Option<lsp_types::DocumentSymbolResponse>> {
|
||||
let _p = tracing::info_span!("handle_document_symbol").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
let mut parents: Vec<(lsp_types::DocumentSymbol, Option<usize>)> = Vec::new();
|
||||
|
|
@ -760,7 +764,7 @@ pub(crate) fn handle_will_rename_files(
|
|||
}
|
||||
})
|
||||
.filter_map(|(file_id, new_name)| {
|
||||
snap.analysis.will_rename_file(file_id, &new_name).ok()?
|
||||
snap.analysis.will_rename_file(file_id?, &new_name).ok()?
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -782,7 +786,8 @@ pub(crate) fn handle_goto_definition(
|
|||
params: lsp_types::GotoDefinitionParams,
|
||||
) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> {
|
||||
let _p = tracing::info_span!("handle_goto_definition").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
let nav_info = match snap.analysis.goto_definition(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
|
|
@ -797,7 +802,10 @@ pub(crate) fn handle_goto_declaration(
|
|||
params: lsp_types::request::GotoDeclarationParams,
|
||||
) -> anyhow::Result<Option<lsp_types::request::GotoDeclarationResponse>> {
|
||||
let _p = tracing::info_span!("handle_goto_declaration").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params.clone())?;
|
||||
let position = try_default!(from_proto::file_position(
|
||||
&snap,
|
||||
params.text_document_position_params.clone()
|
||||
)?);
|
||||
let nav_info = match snap.analysis.goto_declaration(position)? {
|
||||
None => return handle_goto_definition(snap, params),
|
||||
Some(it) => it,
|
||||
|
|
@ -812,7 +820,8 @@ pub(crate) fn handle_goto_implementation(
|
|||
params: lsp_types::request::GotoImplementationParams,
|
||||
) -> anyhow::Result<Option<lsp_types::request::GotoImplementationResponse>> {
|
||||
let _p = tracing::info_span!("handle_goto_implementation").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
let nav_info = match snap.analysis.goto_implementation(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
|
|
@ -827,7 +836,8 @@ pub(crate) fn handle_goto_type_definition(
|
|||
params: lsp_types::request::GotoTypeDefinitionParams,
|
||||
) -> anyhow::Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> {
|
||||
let _p = tracing::info_span!("handle_goto_type_definition").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
let nav_info = match snap.analysis.goto_type_definition(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
|
|
@ -880,7 +890,7 @@ pub(crate) fn handle_parent_module(
|
|||
}
|
||||
|
||||
// check if invoked at the crate root
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let crate_id = match snap.analysis.crates_for(file_id)?.first() {
|
||||
Some(&crate_id) => crate_id,
|
||||
None => return Ok(None),
|
||||
|
|
@ -904,7 +914,7 @@ pub(crate) fn handle_parent_module(
|
|||
}
|
||||
|
||||
// locate parent module by semantics
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
let navs = snap.analysis.parent_module(position)?;
|
||||
let res = to_proto::goto_definition_response(&snap, None, navs)?;
|
||||
Ok(Some(res))
|
||||
|
|
@ -915,7 +925,7 @@ pub(crate) fn handle_runnables(
|
|||
params: lsp_ext::RunnablesParams,
|
||||
) -> anyhow::Result<Vec<lsp_ext::Runnable>> {
|
||||
let _p = tracing::info_span!("handle_runnables").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let source_root = snap.analysis.source_root_id(file_id).ok();
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok());
|
||||
|
|
@ -1035,7 +1045,7 @@ pub(crate) fn handle_related_tests(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<Vec<lsp_ext::TestInfo>> {
|
||||
let _p = tracing::info_span!("handle_related_tests").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
|
||||
let tests = snap.analysis.related_tests(position, None)?;
|
||||
let mut res = Vec::new();
|
||||
|
|
@ -1053,7 +1063,8 @@ pub(crate) fn handle_completion(
|
|||
lsp_types::CompletionParams { text_document_position, context,.. }: lsp_types::CompletionParams,
|
||||
) -> anyhow::Result<Option<lsp_types::CompletionResponse>> {
|
||||
let _p = tracing::info_span!("handle_completion").entered();
|
||||
let mut position = from_proto::file_position(&snap, text_document_position.clone())?;
|
||||
let mut position =
|
||||
try_default!(from_proto::file_position(&snap, text_document_position.clone())?);
|
||||
let line_index = snap.file_line_index(position.file_id)?;
|
||||
let completion_trigger_character =
|
||||
context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next());
|
||||
|
|
@ -1102,7 +1113,8 @@ pub(crate) fn handle_completion_resolve(
|
|||
|
||||
let resolve_data: lsp_ext::CompletionResolveData = serde_json::from_value(data)?;
|
||||
|
||||
let file_id = from_proto::file_id(&snap, &resolve_data.position.text_document.uri)?;
|
||||
let file_id = from_proto::file_id(&snap, &resolve_data.position.text_document.uri)?
|
||||
.expect("we never provide completions for excluded files");
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
// FIXME: We should fix up the position when retrying the cancelled request instead
|
||||
let Ok(offset) = from_proto::offset(&line_index, resolve_data.position.position) else {
|
||||
|
|
@ -1185,7 +1197,7 @@ pub(crate) fn handle_folding_range(
|
|||
params: FoldingRangeParams,
|
||||
) -> anyhow::Result<Option<Vec<FoldingRange>>> {
|
||||
let _p = tracing::info_span!("handle_folding_range").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let folds = snap.analysis.folding_ranges(file_id)?;
|
||||
let text = snap.analysis.file_text(file_id)?;
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
|
@ -1202,7 +1214,8 @@ pub(crate) fn handle_signature_help(
|
|||
params: lsp_types::SignatureHelpParams,
|
||||
) -> anyhow::Result<Option<lsp_types::SignatureHelp>> {
|
||||
let _p = tracing::info_span!("handle_signature_help").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
let help = match snap.analysis.signature_help(position)? {
|
||||
Some(it) => it,
|
||||
None => return Ok(None),
|
||||
|
|
@ -1221,7 +1234,7 @@ pub(crate) fn handle_hover(
|
|||
PositionOrRange::Position(position) => Range::new(position, position),
|
||||
PositionOrRange::Range(range) => range,
|
||||
};
|
||||
let file_range = from_proto::file_range(&snap, ¶ms.text_document, range)?;
|
||||
let file_range = try_default!(from_proto::file_range(&snap, ¶ms.text_document, range)?);
|
||||
|
||||
let hover = snap.config.hover();
|
||||
let info = match snap.analysis.hover(&hover, file_range)? {
|
||||
|
|
@ -1255,7 +1268,7 @@ pub(crate) fn handle_prepare_rename(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<Option<PrepareRenameResponse>> {
|
||||
let _p = tracing::info_span!("handle_prepare_rename").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
|
||||
let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?;
|
||||
|
||||
|
|
@ -1269,7 +1282,7 @@ pub(crate) fn handle_rename(
|
|||
params: RenameParams,
|
||||
) -> anyhow::Result<Option<WorkspaceEdit>> {
|
||||
let _p = tracing::info_span!("handle_rename").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?);
|
||||
|
||||
let mut change =
|
||||
snap.analysis.rename(position, ¶ms.new_name)?.map_err(to_proto::rename_error)?;
|
||||
|
|
@ -1304,7 +1317,7 @@ pub(crate) fn handle_references(
|
|||
params: lsp_types::ReferenceParams,
|
||||
) -> anyhow::Result<Option<Vec<Location>>> {
|
||||
let _p = tracing::info_span!("handle_references").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?);
|
||||
|
||||
let exclude_imports = snap.config.find_all_refs_exclude_imports();
|
||||
let exclude_tests = snap.config.find_all_refs_exclude_tests();
|
||||
|
|
@ -1375,9 +1388,9 @@ pub(crate) fn handle_code_action(
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?;
|
||||
let frange = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?);
|
||||
let source_root = snap.analysis.source_root_id(file_id)?;
|
||||
|
||||
let mut assists_config = snap.config.assist(Some(source_root));
|
||||
|
|
@ -1455,7 +1468,8 @@ pub(crate) fn handle_code_action_resolve(
|
|||
return Err(invalid_params_error("code action without data".to_owned()).into());
|
||||
};
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?
|
||||
.expect("we never provide code actions for excluded files");
|
||||
if snap.file_version(file_id) != params.version {
|
||||
return Err(invalid_params_error("stale code action".to_owned()).into());
|
||||
}
|
||||
|
|
@ -1551,7 +1565,7 @@ pub(crate) fn handle_code_lens(
|
|||
return Ok(Some(Vec::default()));
|
||||
}
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let target_spec = TargetSpec::for_file(&snap, file_id)?;
|
||||
|
||||
let annotations = snap.analysis.annotations(
|
||||
|
|
@ -1613,7 +1627,8 @@ pub(crate) fn handle_document_highlight(
|
|||
params: lsp_types::DocumentHighlightParams,
|
||||
) -> anyhow::Result<Option<Vec<lsp_types::DocumentHighlight>>> {
|
||||
let _p = tracing::info_span!("handle_document_highlight").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
let line_index = snap.file_line_index(position.file_id)?;
|
||||
let source_root = snap.analysis.source_root_id(position.file_id)?;
|
||||
|
||||
|
|
@ -1639,12 +1654,12 @@ pub(crate) fn handle_ssr(
|
|||
params: lsp_ext::SsrParams,
|
||||
) -> anyhow::Result<lsp_types::WorkspaceEdit> {
|
||||
let _p = tracing::info_span!("handle_ssr").entered();
|
||||
let selections = params
|
||||
let selections = try_default!(params
|
||||
.selections
|
||||
.iter()
|
||||
.map(|range| from_proto::file_range(&snap, ¶ms.position.text_document, *range))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let position = from_proto::file_position(&snap, params.position)?;
|
||||
.collect::<Result<Option<Vec<_>>, _>>()?);
|
||||
let position = try_default!(from_proto::file_position(&snap, params.position)?);
|
||||
let source_change = snap.analysis.structural_search_replace(
|
||||
¶ms.query,
|
||||
params.parse_only,
|
||||
|
|
@ -1660,11 +1675,11 @@ pub(crate) fn handle_inlay_hints(
|
|||
) -> anyhow::Result<Option<Vec<InlayHint>>> {
|
||||
let _p = tracing::info_span!("handle_inlay_hints").entered();
|
||||
let document_uri = ¶ms.text_document.uri;
|
||||
let FileRange { file_id, range } = from_proto::file_range(
|
||||
let FileRange { file_id, range } = try_default!(from_proto::file_range(
|
||||
&snap,
|
||||
&TextDocumentIdentifier::new(document_uri.to_owned()),
|
||||
params.range,
|
||||
)?;
|
||||
)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let range = TextRange::new(
|
||||
range.start().min(line_index.index.len()),
|
||||
|
|
@ -1744,7 +1759,8 @@ pub(crate) fn handle_call_hierarchy_prepare(
|
|||
params: CallHierarchyPrepareParams,
|
||||
) -> anyhow::Result<Option<Vec<CallHierarchyItem>>> {
|
||||
let _p = tracing::info_span!("handle_call_hierarchy_prepare").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let position =
|
||||
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
|
||||
|
||||
let nav_info = match snap.analysis.call_hierarchy(position)? {
|
||||
None => return Ok(None),
|
||||
|
|
@ -1769,7 +1785,7 @@ pub(crate) fn handle_call_hierarchy_incoming(
|
|||
let item = params.item;
|
||||
|
||||
let doc = TextDocumentIdentifier::new(item.uri);
|
||||
let frange = from_proto::file_range(&snap, &doc, item.selection_range)?;
|
||||
let frange = try_default!(from_proto::file_range(&snap, &doc, item.selection_range)?);
|
||||
let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
|
||||
let config = snap.config.call_hierarchy();
|
||||
|
|
@ -1807,7 +1823,7 @@ pub(crate) fn handle_call_hierarchy_outgoing(
|
|||
let item = params.item;
|
||||
|
||||
let doc = TextDocumentIdentifier::new(item.uri);
|
||||
let frange = from_proto::file_range(&snap, &doc, item.selection_range)?;
|
||||
let frange = try_default!(from_proto::file_range(&snap, &doc, item.selection_range)?);
|
||||
let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
let line_index = snap.file_line_index(fpos.file_id)?;
|
||||
|
||||
|
|
@ -1842,7 +1858,7 @@ pub(crate) fn handle_semantic_tokens_full(
|
|||
) -> anyhow::Result<Option<SemanticTokensResult>> {
|
||||
let _p = tracing::info_span!("handle_semantic_tokens_full").entered();
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let text = snap.analysis.file_text(file_id)?;
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
|
|
@ -1872,7 +1888,7 @@ pub(crate) fn handle_semantic_tokens_full_delta(
|
|||
) -> anyhow::Result<Option<SemanticTokensFullDeltaResult>> {
|
||||
let _p = tracing::info_span!("handle_semantic_tokens_full_delta").entered();
|
||||
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let text = snap.analysis.file_text(file_id)?;
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
|
|
@ -1915,7 +1931,7 @@ pub(crate) fn handle_semantic_tokens_range(
|
|||
) -> anyhow::Result<Option<SemanticTokensRangeResult>> {
|
||||
let _p = tracing::info_span!("handle_semantic_tokens_range").entered();
|
||||
|
||||
let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?;
|
||||
let frange = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?);
|
||||
let text = snap.analysis.file_text(frange.file_id)?;
|
||||
let line_index = snap.file_line_index(frange.file_id)?;
|
||||
|
||||
|
|
@ -1940,7 +1956,7 @@ pub(crate) fn handle_open_docs(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<ExternalDocsResponse> {
|
||||
let _p = tracing::info_span!("handle_open_docs").entered();
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let position = try_default!(from_proto::file_position(&snap, params)?);
|
||||
|
||||
let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
|
||||
ProjectWorkspaceKind::Cargo { cargo, .. }
|
||||
|
|
@ -1982,7 +1998,7 @@ pub(crate) fn handle_open_cargo_toml(
|
|||
params: lsp_ext::OpenCargoTomlParams,
|
||||
) -> anyhow::Result<Option<lsp_types::GotoDefinitionResponse>> {
|
||||
let _p = tracing::info_span!("handle_open_cargo_toml").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
|
||||
let cargo_spec = match TargetSpec::for_file(&snap, file_id)? {
|
||||
Some(TargetSpec::Cargo(it)) => it,
|
||||
|
|
@ -2000,8 +2016,8 @@ pub(crate) fn handle_move_item(
|
|||
params: lsp_ext::MoveItemParams,
|
||||
) -> anyhow::Result<Vec<lsp_ext::SnippetTextEdit>> {
|
||||
let _p = tracing::info_span!("handle_move_item").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let range = from_proto::file_range(&snap, ¶ms.text_document, params.range)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let range = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?);
|
||||
|
||||
let direction = match params.direction {
|
||||
lsp_ext::MoveItemDirection::Up => ide::Direction::Up,
|
||||
|
|
@ -2022,7 +2038,7 @@ pub(crate) fn handle_view_recursive_memory_layout(
|
|||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<Option<lsp_ext::RecursiveMemoryLayout>> {
|
||||
let _p = tracing::info_span!("handle_view_recursive_memory_layout").entered();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let offset = from_proto::offset(&line_index, params.position)?;
|
||||
|
||||
|
|
@ -2210,7 +2226,7 @@ fn run_rustfmt(
|
|||
text_document: TextDocumentIdentifier,
|
||||
range: Option<lsp_types::Range>,
|
||||
) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> {
|
||||
let file_id = from_proto::file_id(snap, &text_document.uri)?;
|
||||
let file_id = try_default!(from_proto::file_id(snap, &text_document.uri)?);
|
||||
let file = snap.analysis.file_text(file_id)?;
|
||||
|
||||
// Determine the edition of the crate the file belongs to (if there's multiple, we pick the
|
||||
|
|
@ -2275,7 +2291,7 @@ fn run_rustfmt(
|
|||
.into());
|
||||
}
|
||||
|
||||
let frange = from_proto::file_range(snap, &text_document, range)?;
|
||||
let frange = try_default!(from_proto::file_range(snap, &text_document, range)?);
|
||||
let start_line = line_index.index.line_col(frange.range.start()).line;
|
||||
let end_line = line_index.index.line_col(frange.range.end()).line;
|
||||
|
||||
|
|
@ -2417,15 +2433,15 @@ pub(crate) fn internal_testing_fetch_config(
|
|||
state: GlobalStateSnapshot,
|
||||
params: InternalTestingFetchConfigParams,
|
||||
) -> anyhow::Result<Option<InternalTestingFetchConfigResponse>> {
|
||||
let source_root = params
|
||||
.text_document
|
||||
.map(|it| {
|
||||
let source_root = match params.text_document {
|
||||
Some(it) => Some(
|
||||
state
|
||||
.analysis
|
||||
.source_root_id(from_proto::file_id(&state, &it.uri)?)
|
||||
.map_err(anyhow::Error::from)
|
||||
})
|
||||
.transpose()?;
|
||||
.source_root_id(try_default!(from_proto::file_id(&state, &it.uri)?))
|
||||
.map_err(anyhow::Error::from)?,
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
Ok(Some(match params.config {
|
||||
InternalTestingFetchConfigOption::AssistEmitMustUse => {
|
||||
InternalTestingFetchConfigResponse::AssistEmitMustUse(
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ use vfs::{AbsPathBuf, VfsPath};
|
|||
|
||||
use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
|
||||
|
||||
#[track_caller]
|
||||
fn file_id(vfs: &vfs::Vfs, path: &VfsPath) -> vfs::FileId {
|
||||
match vfs.file_id(path) {
|
||||
Some((file_id, vfs::FileExcluded::No)) => file_id,
|
||||
None | Some((_, vfs::FileExcluded::Yes)) => panic!("can't find virtual file for {path}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integrated_highlighting_benchmark() {
|
||||
if std::env::var("RUN_SLOW_BENCHES").is_err() {
|
||||
|
|
@ -62,7 +70,7 @@ fn integrated_highlighting_benchmark() {
|
|||
let file_id = {
|
||||
let file = workspace_to_load.join(file);
|
||||
let path = VfsPath::from(AbsPathBuf::assert(file));
|
||||
vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
|
||||
file_id(&vfs, &path)
|
||||
};
|
||||
|
||||
{
|
||||
|
|
@ -130,7 +138,7 @@ fn integrated_completion_benchmark() {
|
|||
let file_id = {
|
||||
let file = workspace_to_load.join(file);
|
||||
let path = VfsPath::from(AbsPathBuf::assert(file));
|
||||
vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
|
||||
file_id(&vfs, &path)
|
||||
};
|
||||
|
||||
// kick off parsing and index population
|
||||
|
|
@ -324,7 +332,7 @@ fn integrated_diagnostics_benchmark() {
|
|||
let file_id = {
|
||||
let file = workspace_to_load.join(file);
|
||||
let path = VfsPath::from(AbsPathBuf::assert(file));
|
||||
vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
|
||||
file_id(&vfs, &path)
|
||||
};
|
||||
|
||||
let diagnostics_config = DiagnosticsConfig {
|
||||
|
|
|
|||
|
|
@ -173,3 +173,14 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8;
|
|||
|
||||
hasher.finalize()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
macro_rules! try_default_ {
|
||||
($it:expr $(,)?) => {
|
||||
match $it {
|
||||
Some(it) => it,
|
||||
None => return Ok(Default::default()),
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use try_default_ as try_default;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use vfs::AbsPathBuf;
|
|||
use crate::{
|
||||
global_state::GlobalStateSnapshot,
|
||||
line_index::{LineIndex, PositionEncoding},
|
||||
lsp_ext,
|
||||
lsp_ext, try_default,
|
||||
};
|
||||
|
||||
pub(crate) fn abs_path(url: &lsp_types::Url) -> anyhow::Result<AbsPathBuf> {
|
||||
|
|
@ -61,37 +61,44 @@ pub(crate) fn text_range(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> anyhow::Result<FileId> {
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn file_id(
|
||||
snap: &GlobalStateSnapshot,
|
||||
url: &lsp_types::Url,
|
||||
) -> anyhow::Result<Option<FileId>> {
|
||||
snap.url_to_file_id(url)
|
||||
}
|
||||
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn file_position(
|
||||
snap: &GlobalStateSnapshot,
|
||||
tdpp: lsp_types::TextDocumentPositionParams,
|
||||
) -> anyhow::Result<FilePosition> {
|
||||
let file_id = file_id(snap, &tdpp.text_document.uri)?;
|
||||
) -> anyhow::Result<Option<FilePosition>> {
|
||||
let file_id = try_default!(file_id(snap, &tdpp.text_document.uri)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let offset = offset(&line_index, tdpp.position)?;
|
||||
Ok(FilePosition { file_id, offset })
|
||||
Ok(Some(FilePosition { file_id, offset }))
|
||||
}
|
||||
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn file_range(
|
||||
snap: &GlobalStateSnapshot,
|
||||
text_document_identifier: &lsp_types::TextDocumentIdentifier,
|
||||
range: lsp_types::Range,
|
||||
) -> anyhow::Result<FileRange> {
|
||||
) -> anyhow::Result<Option<FileRange>> {
|
||||
file_range_uri(snap, &text_document_identifier.uri, range)
|
||||
}
|
||||
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn file_range_uri(
|
||||
snap: &GlobalStateSnapshot,
|
||||
document: &lsp_types::Url,
|
||||
range: lsp_types::Range,
|
||||
) -> anyhow::Result<FileRange> {
|
||||
let file_id = file_id(snap, document)?;
|
||||
) -> anyhow::Result<Option<FileRange>> {
|
||||
let file_id = try_default!(file_id(snap, document)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let range = text_range(&line_index, range)?;
|
||||
Ok(FileRange { file_id, range })
|
||||
Ok(Some(FileRange { file_id, range }))
|
||||
}
|
||||
|
||||
pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
|
||||
|
|
@ -108,6 +115,7 @@ pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind>
|
|||
Some(assist_kind)
|
||||
}
|
||||
|
||||
/// Returns `None` if the file was excluded.
|
||||
pub(crate) fn annotation(
|
||||
snap: &GlobalStateSnapshot,
|
||||
range: lsp_types::Range,
|
||||
|
|
@ -121,7 +129,7 @@ pub(crate) fn annotation(
|
|||
return Ok(None);
|
||||
}
|
||||
let pos @ FilePosition { file_id, .. } =
|
||||
file_position(snap, params.text_document_position_params)?;
|
||||
try_default!(file_position(snap, params.text_document_position_params)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
Ok(Annotation {
|
||||
|
|
@ -133,7 +141,7 @@ pub(crate) fn annotation(
|
|||
if snap.url_file_version(¶ms.text_document.uri) != Some(data.version) {
|
||||
return Ok(None);
|
||||
}
|
||||
let pos @ FilePosition { file_id, .. } = file_position(snap, params)?;
|
||||
let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, params)?);
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
|
||||
Ok(Annotation {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ use crate::{
|
|||
FetchWorkspaceResponse, GlobalState,
|
||||
},
|
||||
hack_recover_crate_name,
|
||||
handlers::dispatch::{NotificationDispatcher, RequestDispatcher},
|
||||
handlers::{
|
||||
dispatch::{NotificationDispatcher, RequestDispatcher},
|
||||
request::empty_diagnostic_report,
|
||||
},
|
||||
lsp::{
|
||||
from_proto, to_proto,
|
||||
utils::{notification_is, Progress},
|
||||
|
|
@ -548,6 +551,9 @@ impl GlobalState {
|
|||
self.mem_docs
|
||||
.iter()
|
||||
.map(|path| vfs.file_id(path).unwrap())
|
||||
.filter_map(|(file_id, excluded)| {
|
||||
(excluded == vfs::FileExcluded::No).then_some(file_id)
|
||||
})
|
||||
.filter(|&file_id| {
|
||||
let source_root = db.file_source_root(file_id);
|
||||
// Only publish diagnostics for files in the workspace, not from crates.io deps
|
||||
|
|
@ -632,6 +638,9 @@ impl GlobalState {
|
|||
.mem_docs
|
||||
.iter()
|
||||
.map(|path| self.vfs.read().0.file_id(path).unwrap())
|
||||
.filter_map(|(file_id, excluded)| {
|
||||
(excluded == vfs::FileExcluded::No).then_some(file_id)
|
||||
})
|
||||
.filter(|&file_id| {
|
||||
let source_root = db.file_source_root(file_id);
|
||||
!db.source_root(source_root).is_library
|
||||
|
|
@ -879,7 +888,10 @@ impl GlobalState {
|
|||
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| {
|
||||
let _p = tracing::info_span!("GlobalState::check_if_indexed").entered();
|
||||
tracing::debug!(?uri, "handling uri");
|
||||
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
|
||||
let Some(id) = from_proto::file_id(&snap, &uri).expect("unable to get FileId")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Ok(crates) = &snap.analysis.crates_for(id) {
|
||||
if crates.is_empty() {
|
||||
if snap.config.discover_workspace_config().is_some() {
|
||||
|
|
@ -987,13 +999,14 @@ impl GlobalState {
|
|||
);
|
||||
for diag in diagnostics {
|
||||
match url_to_file_id(&self.vfs.read().0, &diag.url) {
|
||||
Ok(file_id) => self.diagnostics.add_check_diagnostic(
|
||||
Ok(Some(file_id)) => self.diagnostics.add_check_diagnostic(
|
||||
id,
|
||||
&package_id,
|
||||
file_id,
|
||||
diag.diagnostic,
|
||||
diag.fix,
|
||||
),
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
error!(
|
||||
"flycheck {id}: File with cargo diagnostic not found in VFS: {}",
|
||||
|
|
@ -1115,17 +1128,7 @@ impl GlobalState {
|
|||
.on_latency_sensitive::<NO_RETRY, lsp_request::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range)
|
||||
// FIXME: Some of these NO_RETRY could be retries if the file they are interested didn't change.
|
||||
// All other request handlers
|
||||
.on_with_vfs_default::<lsp_request::DocumentDiagnosticRequest>(handlers::handle_document_diagnostics, || lsp_types::DocumentDiagnosticReportResult::Report(
|
||||
lsp_types::DocumentDiagnosticReport::Full(
|
||||
lsp_types::RelatedFullDocumentDiagnosticReport {
|
||||
related_documents: None,
|
||||
full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport {
|
||||
result_id: Some("rust-analyzer".to_owned()),
|
||||
items: vec![],
|
||||
},
|
||||
},
|
||||
),
|
||||
), || lsp_server::ResponseError {
|
||||
.on_with_vfs_default::<lsp_request::DocumentDiagnosticRequest>(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError {
|
||||
code: lsp_server::ErrorCode::ServerCancelled as i32,
|
||||
message: "server cancelled the request".to_owned(),
|
||||
data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData {
|
||||
|
|
|
|||
|
|
@ -705,7 +705,9 @@ impl GlobalState {
|
|||
let load = |path: &AbsPath| {
|
||||
let vfs_path = vfs::VfsPath::from(path.to_path_buf());
|
||||
self.crate_graph_file_dependencies.insert(vfs_path.clone());
|
||||
vfs.file_id(&vfs_path)
|
||||
vfs.file_id(&vfs_path).and_then(|(file_id, excluded)| {
|
||||
(excluded == vfs::FileExcluded::No).then_some(file_id)
|
||||
})
|
||||
};
|
||||
|
||||
ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load)
|
||||
|
|
|
|||
|
|
@ -1438,6 +1438,40 @@ pub fn foo() {}
|
|||
name = "bar"
|
||||
version = "0.0.0"
|
||||
|
||||
[dependencies]
|
||||
foo = { path = "../foo" }
|
||||
|
||||
//- /bar/src/lib.rs
|
||||
"#,
|
||||
)
|
||||
.root("foo")
|
||||
.root("bar")
|
||||
.root("baz")
|
||||
.with_config(json!({
|
||||
"files": {
|
||||
"exclude": ["foo"]
|
||||
}
|
||||
}))
|
||||
.server()
|
||||
.wait_until_workspace_is_loaded();
|
||||
|
||||
server.request::<WorkspaceSymbolRequest>(Default::default(), json!([]));
|
||||
|
||||
let server = Project::with_fixture(
|
||||
r#"
|
||||
//- /foo/Cargo.toml
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.0.0"
|
||||
|
||||
//- /foo/src/lib.rs
|
||||
pub fn foo() {}
|
||||
|
||||
//- /bar/Cargo.toml
|
||||
[package]
|
||||
name = "bar"
|
||||
version = "0.0.0"
|
||||
|
||||
//- /bar/src/lib.rs
|
||||
pub fn bar() {}
|
||||
|
||||
|
|
@ -1454,7 +1488,7 @@ version = "0.0.0"
|
|||
.root("baz")
|
||||
.with_config(json!({
|
||||
"files": {
|
||||
"excludeDirs": ["foo", "bar"]
|
||||
"exclude": ["foo", "bar"]
|
||||
}
|
||||
}))
|
||||
.server()
|
||||
|
|
|
|||
|
|
@ -280,8 +280,9 @@ impl NotifyActor {
|
|||
return false;
|
||||
}
|
||||
|
||||
root == path
|
||||
|| dirs.exclude.iter().chain(&dirs.include).all(|it| it != path)
|
||||
// We want to filter out subdirectories that are roots themselves, because they will be visited separately.
|
||||
dirs.exclude.iter().all(|it| it != path)
|
||||
&& (root == path || dirs.include.iter().all(|it| it != path))
|
||||
});
|
||||
|
||||
let files = walkdir.filter_map(|it| it.ok()).filter_map(|entry| {
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ pub enum FileState {
|
|||
Exists(u64),
|
||||
/// The file is deleted.
|
||||
Deleted,
|
||||
/// The file was specifically excluded by the user. We still include excluded files
|
||||
/// when they're opened (without their contents).
|
||||
Excluded,
|
||||
}
|
||||
|
||||
/// Changed file in the [`Vfs`].
|
||||
|
|
@ -164,10 +167,22 @@ pub enum ChangeKind {
|
|||
Delete,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum FileExcluded {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl Vfs {
|
||||
/// Id of the given path if it exists in the `Vfs` and is not deleted.
|
||||
pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
|
||||
self.interner.get(path).filter(|&it| matches!(self.get(it), FileState::Exists(_)))
|
||||
pub fn file_id(&self, path: &VfsPath) -> Option<(FileId, FileExcluded)> {
|
||||
let file_id = self.interner.get(path)?;
|
||||
let file_state = self.get(file_id);
|
||||
match file_state {
|
||||
FileState::Exists(_) => Some((file_id, FileExcluded::No)),
|
||||
FileState::Deleted => None,
|
||||
FileState::Excluded => Some((file_id, FileExcluded::Yes)),
|
||||
}
|
||||
}
|
||||
|
||||
/// File path corresponding to the given `file_id`.
|
||||
|
|
@ -216,6 +231,7 @@ impl Vfs {
|
|||
}
|
||||
Change::Modify(v, new_hash)
|
||||
}
|
||||
(FileState::Excluded, _) => return false,
|
||||
};
|
||||
|
||||
let mut set_data = |change_kind| {
|
||||
|
|
@ -297,6 +313,13 @@ impl Vfs {
|
|||
fn get(&self, file_id: FileId) -> FileState {
|
||||
self.data[file_id.0 as usize]
|
||||
}
|
||||
|
||||
/// We cannot ignore excluded files, because this will lead to errors when the client
|
||||
/// requests semantic information for them, so we instead mark them specially.
|
||||
pub fn insert_excluded_file(&mut self, path: VfsPath) {
|
||||
let file_id = self.alloc_file_id(path);
|
||||
self.data[file_id.0 as usize] = FileState::Excluded;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Vfs {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue