mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 20:29:11 +00:00
fix(lsp): regression where certain diagnostics were showing for disabled files (#13530)
This commit is contained in:
parent
5cf23176dc
commit
a2e4fa471b
1 changed files with 187 additions and 94 deletions
|
@ -4,6 +4,7 @@ use super::analysis;
|
||||||
use super::client::Client;
|
use super::client::Client;
|
||||||
use super::config::ConfigSnapshot;
|
use super::config::ConfigSnapshot;
|
||||||
use super::documents;
|
use super::documents;
|
||||||
|
use super::documents::Document;
|
||||||
use super::documents::Documents;
|
use super::documents::Documents;
|
||||||
use super::language_server;
|
use super::language_server;
|
||||||
use super::performance::Performance;
|
use super::performance::Performance;
|
||||||
|
@ -211,14 +212,14 @@ impl DiagnosticsServer {
|
||||||
|
|
||||||
let mark =
|
let mark =
|
||||||
performance.mark("update_diagnostics_ts", None::<()>);
|
performance.mark("update_diagnostics_ts", None::<()>);
|
||||||
let diagnostics =
|
let diagnostics = generate_ts_diagnostics(
|
||||||
generate_ts_diagnostics(snapshot.clone(), &ts_server)
|
snapshot.clone(),
|
||||||
|
&config,
|
||||||
|
&ts_server,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!(
|
error!("Error generating TypeScript diagnostics: {}", err);
|
||||||
"Error generating TypeScript diagnostics: {}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -257,8 +258,8 @@ impl DiagnosticsServer {
|
||||||
let mark =
|
let mark =
|
||||||
performance.mark("update_diagnostics_deps", None::<()>);
|
performance.mark("update_diagnostics_deps", None::<()>);
|
||||||
let diagnostics = generate_deps_diagnostics(
|
let diagnostics = generate_deps_diagnostics(
|
||||||
snapshot.clone(),
|
&snapshot,
|
||||||
config.clone(),
|
&config,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -439,13 +440,33 @@ async fn generate_lint_diagnostics(
|
||||||
}
|
}
|
||||||
|
|
||||||
let version = document.maybe_lsp_version();
|
let version = document.maybe_lsp_version();
|
||||||
let is_allowed = match &maybe_lint_config {
|
diagnostics_vec.push((
|
||||||
Some(lint_config) => {
|
document.specifier().clone(),
|
||||||
lint_config.files.matches_specifier(document.specifier())
|
version,
|
||||||
|
generate_document_lint_diagnostics(
|
||||||
|
config,
|
||||||
|
&maybe_lint_config,
|
||||||
|
&document,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diagnostics_vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_document_lint_diagnostics(
|
||||||
|
config: &ConfigSnapshot,
|
||||||
|
maybe_lint_config: &Option<LintConfig>,
|
||||||
|
document: &Document,
|
||||||
|
) -> Vec<lsp::Diagnostic> {
|
||||||
|
if !config.specifier_enabled(document.specifier()) {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
if let Some(lint_config) = &maybe_lint_config {
|
||||||
|
if !lint_config.files.matches_specifier(document.specifier()) {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
let diagnostics = if is_allowed {
|
|
||||||
match document.maybe_parsed_source() {
|
match document.maybe_parsed_source() {
|
||||||
Some(Ok(parsed_source)) => {
|
Some(Ok(parsed_source)) => {
|
||||||
if let Ok(references) = analysis::get_lint_references(
|
if let Ok(references) = analysis::get_lint_references(
|
||||||
|
@ -466,21 +487,11 @@ async fn generate_lint_diagnostics(
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Vec::new()
|
|
||||||
};
|
|
||||||
diagnostics_vec.push((
|
|
||||||
document.specifier().clone(),
|
|
||||||
version,
|
|
||||||
diagnostics,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diagnostics_vec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn generate_ts_diagnostics(
|
async fn generate_ts_diagnostics(
|
||||||
snapshot: Arc<language_server::StateSnapshot>,
|
snapshot: Arc<language_server::StateSnapshot>,
|
||||||
|
config: &ConfigSnapshot,
|
||||||
ts_server: &tsc::TsServer,
|
ts_server: &tsc::TsServer,
|
||||||
) -> Result<DiagnosticVec, AnyError> {
|
) -> Result<DiagnosticVec, AnyError> {
|
||||||
let mut diagnostics_vec = Vec::new();
|
let mut diagnostics_vec = Vec::new();
|
||||||
|
@ -490,23 +501,41 @@ async fn generate_ts_diagnostics(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|d| d.specifier().clone())
|
.map(|d| d.specifier().clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if !specifiers.is_empty() {
|
let (enabled_specifiers, disabled_specifiers) = specifiers
|
||||||
let req = tsc::RequestMethod::GetDiagnostics(specifiers);
|
.iter()
|
||||||
let ts_diagnostics_map: TsDiagnosticsMap =
|
.cloned()
|
||||||
ts_server.request(snapshot.clone(), req).await?;
|
.partition::<Vec<_>, _>(|s| config.specifier_enabled(s));
|
||||||
for (specifier_str, ts_diagnostics) in ts_diagnostics_map {
|
let ts_diagnostics_map: TsDiagnosticsMap = if !enabled_specifiers.is_empty() {
|
||||||
|
let req = tsc::RequestMethod::GetDiagnostics(enabled_specifiers);
|
||||||
|
ts_server.request(snapshot.clone(), req).await?
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
};
|
||||||
|
for (specifier_str, ts_json_diagnostics) in ts_diagnostics_map {
|
||||||
let specifier = resolve_url(&specifier_str)?;
|
let specifier = resolve_url(&specifier_str)?;
|
||||||
let version = snapshot
|
let version = snapshot
|
||||||
.documents
|
.documents
|
||||||
.get(&specifier)
|
.get(&specifier)
|
||||||
.map(|d| d.maybe_lsp_version())
|
.map(|d| d.maybe_lsp_version())
|
||||||
.flatten();
|
.flatten();
|
||||||
diagnostics_vec.push((
|
// check if the specifier is enabled again just in case TS returns us
|
||||||
specifier,
|
// diagnostics for a disabled specifier
|
||||||
version,
|
let ts_diagnostics = if config.specifier_enabled(&specifier) {
|
||||||
ts_json_to_diagnostics(ts_diagnostics),
|
ts_json_to_diagnostics(ts_json_diagnostics)
|
||||||
));
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
diagnostics_vec.push((specifier, version, ts_diagnostics));
|
||||||
}
|
}
|
||||||
|
// add an empty diagnostic publish for disabled specifiers in order
|
||||||
|
// to clear those diagnostics if they exist
|
||||||
|
for specifier in disabled_specifiers {
|
||||||
|
let version = snapshot
|
||||||
|
.documents
|
||||||
|
.get(&specifier)
|
||||||
|
.map(|d| d.maybe_lsp_version())
|
||||||
|
.flatten();
|
||||||
|
diagnostics_vec.push((specifier, version, Vec::new()));
|
||||||
}
|
}
|
||||||
Ok(diagnostics_vec)
|
Ok(diagnostics_vec)
|
||||||
}
|
}
|
||||||
|
@ -619,8 +648,8 @@ fn diagnose_dependency(
|
||||||
/// Generate diagnostics for dependencies of a module, attempting to resolve
|
/// Generate diagnostics for dependencies of a module, attempting to resolve
|
||||||
/// dependencies on the local file system or in the DENO_DIR cache.
|
/// dependencies on the local file system or in the DENO_DIR cache.
|
||||||
async fn generate_deps_diagnostics(
|
async fn generate_deps_diagnostics(
|
||||||
snapshot: Arc<language_server::StateSnapshot>,
|
snapshot: &language_server::StateSnapshot,
|
||||||
config: Arc<ConfigSnapshot>,
|
config: &ConfigSnapshot,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
) -> DiagnosticVec {
|
) -> DiagnosticVec {
|
||||||
let mut diagnostics_vec = Vec::new();
|
let mut diagnostics_vec = Vec::new();
|
||||||
|
@ -629,10 +658,8 @@ async fn generate_deps_diagnostics(
|
||||||
if token.is_cancelled() {
|
if token.is_cancelled() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if !config.specifier_enabled(document.specifier()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
if config.specifier_enabled(document.specifier()) {
|
||||||
for (_, dependency) in document.dependencies() {
|
for (_, dependency) in document.dependencies() {
|
||||||
diagnose_dependency(
|
diagnose_dependency(
|
||||||
&mut diagnostics,
|
&mut diagnostics,
|
||||||
|
@ -649,6 +676,7 @@ async fn generate_deps_diagnostics(
|
||||||
dependency.maybe_assert_type.as_deref(),
|
dependency.maybe_assert_type.as_deref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
diagnostics_vec.push((
|
diagnostics_vec.push((
|
||||||
document.specifier().clone(),
|
document.specifier().clone(),
|
||||||
document.maybe_lsp_version(),
|
document.maybe_lsp_version(),
|
||||||
|
@ -664,6 +692,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::lsp::config::ConfigSnapshot;
|
use crate::lsp::config::ConfigSnapshot;
|
||||||
use crate::lsp::config::Settings;
|
use crate::lsp::config::Settings;
|
||||||
|
use crate::lsp::config::SpecifierSettings;
|
||||||
use crate::lsp::config::WorkspaceSettings;
|
use crate::lsp::config::WorkspaceSettings;
|
||||||
use crate::lsp::documents::LanguageId;
|
use crate::lsp::documents::LanguageId;
|
||||||
use crate::lsp::language_server::StateSnapshot;
|
use crate::lsp::language_server::StateSnapshot;
|
||||||
|
@ -708,31 +737,95 @@ mod tests {
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
sources: &[(&str, &str, i32, LanguageId)],
|
sources: &[(&str, &str, i32, LanguageId)],
|
||||||
) -> (StateSnapshot, PathBuf, ConfigSnapshot) {
|
) -> (StateSnapshot, PathBuf) {
|
||||||
let temp_dir = TempDir::new().expect("could not create temp dir");
|
let temp_dir = TempDir::new().expect("could not create temp dir");
|
||||||
let location = temp_dir.path().join("deps");
|
let location = temp_dir.path().join("deps");
|
||||||
let state_snapshot = mock_state_snapshot(sources, &location);
|
let state_snapshot = mock_state_snapshot(sources, &location);
|
||||||
let config = mock_config();
|
(state_snapshot, location)
|
||||||
(state_snapshot, location, config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_generate_lint_diagnostics() {
|
async fn test_enabled_then_disabled_specifier() {
|
||||||
let (snapshot, _, config) = setup(&[(
|
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
|
||||||
|
let (snapshot, _) = setup(&[(
|
||||||
"file:///a.ts",
|
"file:///a.ts",
|
||||||
r#"import * as b from "./b.ts";
|
r#"import * as b from "./b.ts";
|
||||||
|
let a: any = "a";
|
||||||
let a = "a";
|
let c: number = "a";
|
||||||
console.log(a);
|
|
||||||
"#,
|
"#,
|
||||||
1,
|
1,
|
||||||
LanguageId::TypeScript,
|
LanguageId::TypeScript,
|
||||||
)]);
|
)]);
|
||||||
let diagnostics =
|
let snapshot = Arc::new(snapshot);
|
||||||
generate_lint_diagnostics(&snapshot, &config, None, Default::default())
|
let ts_server = TsServer::new(Default::default());
|
||||||
|
|
||||||
|
// test enabled
|
||||||
|
{
|
||||||
|
let enabled_config = mock_config();
|
||||||
|
let diagnostics = generate_lint_diagnostics(
|
||||||
|
&snapshot,
|
||||||
|
&enabled_config,
|
||||||
|
None,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(diagnostics.len(), 1);
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 6);
|
||||||
let (_, _, diagnostics) = &diagnostics[0];
|
let diagnostics =
|
||||||
assert_eq!(diagnostics.len(), 2);
|
generate_ts_diagnostics(snapshot.clone(), &enabled_config, &ts_server)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 4);
|
||||||
|
let diagnostics = generate_deps_diagnostics(
|
||||||
|
&snapshot,
|
||||||
|
&enabled_config,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now test disabled specifier
|
||||||
|
{
|
||||||
|
let mut disabled_config = mock_config();
|
||||||
|
disabled_config.settings.specifiers.insert(
|
||||||
|
specifier.clone(),
|
||||||
|
(
|
||||||
|
specifier.clone(),
|
||||||
|
SpecifierSettings {
|
||||||
|
enable: false,
|
||||||
|
code_lens: Default::default(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let diagnostics = generate_lint_diagnostics(
|
||||||
|
&snapshot,
|
||||||
|
&disabled_config,
|
||||||
|
None,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0);
|
||||||
|
let diagnostics =
|
||||||
|
generate_ts_diagnostics(snapshot.clone(), &disabled_config, &ts_server)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0);
|
||||||
|
let diagnostics = generate_deps_diagnostics(
|
||||||
|
&snapshot,
|
||||||
|
&disabled_config,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_diagnostics_for_single(
|
||||||
|
diagnostic_vec: DiagnosticVec,
|
||||||
|
) -> Vec<lsp::Diagnostic> {
|
||||||
|
assert_eq!(diagnostic_vec.len(), 1);
|
||||||
|
let (_, _, diagnostics) = diagnostic_vec.into_iter().next().unwrap();
|
||||||
|
diagnostics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue