mirror of
https://github.com/denoland/deno.git
synced 2025-01-22 06:09:25 -05:00
refactor(lsp): unify config file data into ConfigTree (#23032)
This commit is contained in:
parent
d6452b3946
commit
3b61104e2a
10 changed files with 1090 additions and 967 deletions
|
@ -260,6 +260,12 @@ pub struct FmtOptions {
|
||||||
pub files: FilePatterns,
|
pub files: FilePatterns,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for FmtOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new_with_base(PathBuf::from("/"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FmtOptions {
|
impl FmtOptions {
|
||||||
pub fn new_with_base(base: PathBuf) -> Self {
|
pub fn new_with_base(base: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -394,6 +400,12 @@ pub struct LintOptions {
|
||||||
pub fix: bool,
|
pub fix: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for LintOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new_with_base(PathBuf::from("/"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LintOptions {
|
impl LintOptions {
|
||||||
pub fn new_with_base(base: PathBuf) -> Self {
|
pub fn new_with_base(base: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -43,6 +43,7 @@ use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
use tower_lsp::lsp_types::Position;
|
use tower_lsp::lsp_types::Position;
|
||||||
use tower_lsp::lsp_types::Range;
|
use tower_lsp::lsp_types::Range;
|
||||||
|
@ -216,7 +217,7 @@ fn code_as_string(code: &Option<lsp::NumberOrString>) -> String {
|
||||||
/// Rewrites imports in quick fixes and code changes to be Deno specific.
|
/// Rewrites imports in quick fixes and code changes to be Deno specific.
|
||||||
pub struct TsResponseImportMapper<'a> {
|
pub struct TsResponseImportMapper<'a> {
|
||||||
documents: &'a Documents,
|
documents: &'a Documents,
|
||||||
maybe_import_map: Option<&'a ImportMap>,
|
maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
node_resolver: Option<&'a CliNodeResolver>,
|
node_resolver: Option<&'a CliNodeResolver>,
|
||||||
npm_resolver: Option<&'a dyn CliNpmResolver>,
|
npm_resolver: Option<&'a dyn CliNpmResolver>,
|
||||||
}
|
}
|
||||||
|
@ -224,7 +225,7 @@ pub struct TsResponseImportMapper<'a> {
|
||||||
impl<'a> TsResponseImportMapper<'a> {
|
impl<'a> TsResponseImportMapper<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
documents: &'a Documents,
|
documents: &'a Documents,
|
||||||
maybe_import_map: Option<&'a ImportMap>,
|
maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
node_resolver: Option<&'a CliNodeResolver>,
|
node_resolver: Option<&'a CliNodeResolver>,
|
||||||
npm_resolver: Option<&'a dyn CliNpmResolver>,
|
npm_resolver: Option<&'a dyn CliNpmResolver>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -269,7 +270,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
let sub_path = (export != ".").then_some(export);
|
let sub_path = (export != ".").then_some(export);
|
||||||
let mut req = None;
|
let mut req = None;
|
||||||
req = req.or_else(|| {
|
req = req.or_else(|| {
|
||||||
let import_map = self.maybe_import_map?;
|
let import_map = self.maybe_import_map.as_ref()?;
|
||||||
for entry in import_map.entries_for_referrer(referrer) {
|
for entry in import_map.entries_for_referrer(referrer) {
|
||||||
let Some(value) = entry.raw_value else {
|
let Some(value) = entry.raw_value else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -296,7 +297,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
JsrPackageNvReference::new(nv_ref).to_string()
|
JsrPackageNvReference::new(nv_ref).to_string()
|
||||||
};
|
};
|
||||||
let specifier = ModuleSpecifier::parse(&spec_str).ok()?;
|
let specifier = ModuleSpecifier::parse(&spec_str).ok()?;
|
||||||
if let Some(import_map) = self.maybe_import_map {
|
if let Some(import_map) = &self.maybe_import_map {
|
||||||
if let Some(result) = import_map.lookup(&specifier, referrer) {
|
if let Some(result) = import_map.lookup(&specifier, referrer) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
|
@ -315,7 +316,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
// check if any pkg reqs match what is found in an import map
|
// check if any pkg reqs match what is found in an import map
|
||||||
if !pkg_reqs.is_empty() {
|
if !pkg_reqs.is_empty() {
|
||||||
let sub_path = self.resolve_package_path(specifier);
|
let sub_path = self.resolve_package_path(specifier);
|
||||||
if let Some(import_map) = self.maybe_import_map {
|
if let Some(import_map) = &self.maybe_import_map {
|
||||||
let pkg_reqs = pkg_reqs.iter().collect::<HashSet<_>>();
|
let pkg_reqs = pkg_reqs.iter().collect::<HashSet<_>>();
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
for entry in import_map.entries_for_referrer(referrer) {
|
for entry in import_map.entries_for_referrer(referrer) {
|
||||||
|
@ -357,7 +358,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the import map has this specifier
|
// check if the import map has this specifier
|
||||||
if let Some(import_map) = self.maybe_import_map {
|
if let Some(import_map) = &self.maybe_import_map {
|
||||||
if let Some(result) = import_map.lookup(specifier, referrer) {
|
if let Some(result) = import_map.lookup(specifier, referrer) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
|
@ -942,7 +943,7 @@ impl CodeActionCollection {
|
||||||
let action = fix_ts_import_action(
|
let action = fix_ts_import_action(
|
||||||
specifier,
|
specifier,
|
||||||
action,
|
action,
|
||||||
&language_server.get_ts_response_import_mapper(),
|
&language_server.get_ts_response_import_mapper(specifier),
|
||||||
)?;
|
)?;
|
||||||
let edit = ts_changes_to_edit(&action.changes, language_server)?;
|
let edit = ts_changes_to_edit(&action.changes, language_server)?;
|
||||||
let code_action = lsp::CodeAction {
|
let code_action = lsp::CodeAction {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,6 @@ use crate::graph_util::enhanced_resolution_error_message;
|
||||||
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
||||||
use crate::resolver::SloppyImportsResolution;
|
use crate::resolver::SloppyImportsResolution;
|
||||||
use crate::resolver::SloppyImportsResolver;
|
use crate::resolver::SloppyImportsResolver;
|
||||||
use crate::tools::lint::get_configured_rules;
|
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -46,6 +45,7 @@ use deno_runtime::tokio_util::create_basic_runtime;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use import_map::ImportMap;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -62,10 +62,10 @@ use tower_lsp::lsp_types as lsp;
|
||||||
pub struct DiagnosticServerUpdateMessage {
|
pub struct DiagnosticServerUpdateMessage {
|
||||||
pub snapshot: Arc<StateSnapshot>,
|
pub snapshot: Arc<StateSnapshot>,
|
||||||
pub config: Arc<ConfigSnapshot>,
|
pub config: Arc<ConfigSnapshot>,
|
||||||
pub lint_options: LintOptions,
|
|
||||||
pub url_map: LspUrlMap,
|
pub url_map: LspUrlMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct DiagnosticRecord {
|
struct DiagnosticRecord {
|
||||||
pub specifier: ModuleSpecifier,
|
pub specifier: ModuleSpecifier,
|
||||||
pub versioned: VersionedDiagnostics,
|
pub versioned: VersionedDiagnostics,
|
||||||
|
@ -461,7 +461,6 @@ impl DiagnosticsServer {
|
||||||
DiagnosticServerUpdateMessage {
|
DiagnosticServerUpdateMessage {
|
||||||
snapshot,
|
snapshot,
|
||||||
config,
|
config,
|
||||||
lint_options,
|
|
||||||
url_map,
|
url_map,
|
||||||
},
|
},
|
||||||
batch_index,
|
batch_index,
|
||||||
|
@ -612,14 +611,7 @@ impl DiagnosticsServer {
|
||||||
let mark = performance.mark("lsp.update_diagnostics_lint");
|
let mark = performance.mark("lsp.update_diagnostics_lint");
|
||||||
let diagnostics = spawn_blocking({
|
let diagnostics = spawn_blocking({
|
||||||
let token = token.clone();
|
let token = token.clone();
|
||||||
move || {
|
move || generate_lint_diagnostics(&snapshot, &config, token)
|
||||||
generate_lint_diagnostics(
|
|
||||||
&snapshot,
|
|
||||||
&config,
|
|
||||||
&lint_options,
|
|
||||||
token,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -791,17 +783,12 @@ fn ts_json_to_diagnostics(
|
||||||
fn generate_lint_diagnostics(
|
fn generate_lint_diagnostics(
|
||||||
snapshot: &language_server::StateSnapshot,
|
snapshot: &language_server::StateSnapshot,
|
||||||
config: &ConfigSnapshot,
|
config: &ConfigSnapshot,
|
||||||
lint_options: &LintOptions,
|
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
) -> DiagnosticVec {
|
) -> DiagnosticVec {
|
||||||
let documents = snapshot
|
let documents = snapshot
|
||||||
.documents
|
.documents
|
||||||
.documents(DocumentsFilter::OpenDiagnosable);
|
.documents(DocumentsFilter::OpenDiagnosable);
|
||||||
let lint_rules = get_configured_rules(
|
let config_data_by_scope = config.tree.data_by_scope();
|
||||||
lint_options.rules.clone(),
|
|
||||||
config.config_file.as_ref(),
|
|
||||||
)
|
|
||||||
.rules;
|
|
||||||
let mut diagnostics_vec = Vec::new();
|
let mut diagnostics_vec = Vec::new();
|
||||||
for document in documents {
|
for document in documents {
|
||||||
let settings =
|
let settings =
|
||||||
|
@ -820,14 +807,20 @@ fn generate_lint_diagnostics(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let version = document.maybe_lsp_version();
|
let version = document.maybe_lsp_version();
|
||||||
|
let (lint_options, lint_rules) = config
|
||||||
|
.tree
|
||||||
|
.scope_for_specifier(document.specifier())
|
||||||
|
.and_then(|s| config_data_by_scope.get(&s))
|
||||||
|
.map(|d| (d.lint_options.clone(), d.lint_rules.clone()))
|
||||||
|
.unwrap_or_default();
|
||||||
diagnostics_vec.push(DiagnosticRecord {
|
diagnostics_vec.push(DiagnosticRecord {
|
||||||
specifier: document.specifier().clone(),
|
specifier: document.specifier().clone(),
|
||||||
versioned: VersionedDiagnostics {
|
versioned: VersionedDiagnostics {
|
||||||
version,
|
version,
|
||||||
diagnostics: generate_document_lint_diagnostics(
|
diagnostics: generate_document_lint_diagnostics(
|
||||||
config,
|
config,
|
||||||
lint_options,
|
&lint_options,
|
||||||
lint_rules.clone(),
|
lint_rules.rules.clone(),
|
||||||
&document,
|
&document,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -1304,6 +1297,7 @@ fn diagnose_resolution(
|
||||||
resolution: &Resolution,
|
resolution: &Resolution,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
maybe_assert_type: Option<&str>,
|
maybe_assert_type: Option<&str>,
|
||||||
|
import_map: Option<&ImportMap>,
|
||||||
) -> Vec<DenoDiagnostic> {
|
) -> Vec<DenoDiagnostic> {
|
||||||
fn check_redirect_diagnostic(
|
fn check_redirect_diagnostic(
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -1392,7 +1386,7 @@ fn diagnose_resolution(
|
||||||
.push(DenoDiagnostic::InvalidNodeSpecifier(specifier.clone()));
|
.push(DenoDiagnostic::InvalidNodeSpecifier(specifier.clone()));
|
||||||
} else if module_name == dependency_key {
|
} else if module_name == dependency_key {
|
||||||
let mut is_mapped = false;
|
let mut is_mapped = false;
|
||||||
if let Some(import_map) = &snapshot.maybe_import_map {
|
if let Some(import_map) = import_map {
|
||||||
if let Resolution::Ok(resolved) = &resolution {
|
if let Resolution::Ok(resolved) = &resolution {
|
||||||
if import_map.resolve(module_name, &resolved.specifier).is_ok() {
|
if import_map.resolve(module_name, &resolved.specifier).is_ok() {
|
||||||
is_mapped = true;
|
is_mapped = true;
|
||||||
|
@ -1455,7 +1449,8 @@ fn diagnose_dependency(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(import_map) = &snapshot.maybe_import_map {
|
let import_map = snapshot.config.tree.import_map_for_specifier(referrer);
|
||||||
|
if let Some(import_map) = &import_map {
|
||||||
if let Resolution::Ok(resolved) = &dependency.maybe_code {
|
if let Resolution::Ok(resolved) = &dependency.maybe_code {
|
||||||
if let Some(to) = import_map.lookup(&resolved.specifier, referrer) {
|
if let Some(to) = import_map.lookup(&resolved.specifier, referrer) {
|
||||||
if dependency_key != to {
|
if dependency_key != to {
|
||||||
|
@ -1504,6 +1499,7 @@ fn diagnose_dependency(
|
||||||
},
|
},
|
||||||
dependency.is_dynamic,
|
dependency.is_dynamic,
|
||||||
dependency.maybe_attribute_type.as_deref(),
|
dependency.maybe_attribute_type.as_deref(),
|
||||||
|
import_map.as_deref(),
|
||||||
)
|
)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|diag| {
|
.flat_map(|diag| {
|
||||||
|
@ -1526,6 +1522,7 @@ fn diagnose_dependency(
|
||||||
&dependency.maybe_type,
|
&dependency.maybe_type,
|
||||||
dependency.is_dynamic,
|
dependency.is_dynamic,
|
||||||
dependency.maybe_attribute_type.as_deref(),
|
dependency.maybe_attribute_type.as_deref(),
|
||||||
|
import_map.as_deref(),
|
||||||
)
|
)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|diag| diag.to_lsp_diagnostic(&range)),
|
.map(|diag| diag.to_lsp_diagnostic(&range)),
|
||||||
|
@ -1580,20 +1577,21 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::cache::GlobalHttpCache;
|
use crate::cache::GlobalHttpCache;
|
||||||
use crate::cache::RealDenoCacheEnv;
|
use crate::cache::RealDenoCacheEnv;
|
||||||
|
use crate::lsp::config::Config;
|
||||||
use crate::lsp::config::ConfigSnapshot;
|
use crate::lsp::config::ConfigSnapshot;
|
||||||
use crate::lsp::config::Settings;
|
use crate::lsp::config::Settings;
|
||||||
use crate::lsp::config::WorkspaceSettings;
|
use crate::lsp::config::WorkspaceSettings;
|
||||||
use crate::lsp::documents::Documents;
|
use crate::lsp::documents::Documents;
|
||||||
use crate::lsp::documents::LanguageId;
|
use crate::lsp::documents::LanguageId;
|
||||||
use crate::lsp::language_server::StateSnapshot;
|
use crate::lsp::language_server::StateSnapshot;
|
||||||
use deno_config::glob::FilePatterns;
|
use deno_config::ConfigFile;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
fn mock_state_snapshot(
|
async fn mock_state_snapshot(
|
||||||
fixtures: &[(&str, &str, i32, LanguageId)],
|
fixtures: &[(&str, &str, i32, LanguageId)],
|
||||||
location: &Path,
|
location: &Path,
|
||||||
maybe_import_map: Option<(&str, &str)>,
|
maybe_import_map: Option<(&str, &str)>,
|
||||||
|
@ -1613,22 +1611,19 @@ mod tests {
|
||||||
(*source).into(),
|
(*source).into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let maybe_import_map = maybe_import_map.map(|(base, json_string)| {
|
let config = Config::new_with_roots([resolve_url("file:///").unwrap()]);
|
||||||
let base_url = ModuleSpecifier::parse(base).unwrap();
|
if let Some((base_url, json_string)) = maybe_import_map {
|
||||||
let result = import_map::parse_from_json(&base_url, json_string).unwrap();
|
let base_url = resolve_url(base_url).unwrap();
|
||||||
if !result.diagnostics.is_empty() {
|
let config_file = ConfigFile::new(json_string, base_url).unwrap();
|
||||||
panic!("unexpected import map diagnostics");
|
config.tree.inject_config_file(config_file).await;
|
||||||
}
|
}
|
||||||
Arc::new(result.import_map)
|
|
||||||
});
|
|
||||||
StateSnapshot {
|
StateSnapshot {
|
||||||
documents,
|
documents,
|
||||||
maybe_import_map,
|
|
||||||
assets: Default::default(),
|
assets: Default::default(),
|
||||||
cache_metadata: cache::CacheMetadata::new(Arc::new(
|
cache_metadata: cache::CacheMetadata::new(Arc::new(
|
||||||
GlobalHttpCache::new(location.to_path_buf(), RealDenoCacheEnv),
|
GlobalHttpCache::new(location.to_path_buf(), RealDenoCacheEnv),
|
||||||
)),
|
)),
|
||||||
config: Default::default(),
|
config: config.snapshot(),
|
||||||
npm: None,
|
npm: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1655,14 +1650,14 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
async fn setup(
|
||||||
temp_dir: &TempDir,
|
temp_dir: &TempDir,
|
||||||
sources: &[(&str, &str, i32, LanguageId)],
|
sources: &[(&str, &str, i32, LanguageId)],
|
||||||
maybe_import_map: Option<(&str, &str)>,
|
maybe_import_map: Option<(&str, &str)>,
|
||||||
) -> (StateSnapshot, PathBuf) {
|
) -> (StateSnapshot, PathBuf) {
|
||||||
let location = temp_dir.path().join("deps").to_path_buf();
|
let location = temp_dir.path().join("deps").to_path_buf();
|
||||||
let state_snapshot =
|
let state_snapshot =
|
||||||
mock_state_snapshot(sources, &location, maybe_import_map);
|
mock_state_snapshot(sources, &location, maybe_import_map).await;
|
||||||
(state_snapshot, location)
|
(state_snapshot, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1681,18 +1676,14 @@ let c: number = "a";
|
||||||
LanguageId::TypeScript,
|
LanguageId::TypeScript,
|
||||||
)],
|
)],
|
||||||
None,
|
None,
|
||||||
);
|
)
|
||||||
|
.await;
|
||||||
let snapshot = Arc::new(snapshot);
|
let snapshot = Arc::new(snapshot);
|
||||||
let cache =
|
let cache =
|
||||||
Arc::new(GlobalHttpCache::new(cache_location, RealDenoCacheEnv));
|
Arc::new(GlobalHttpCache::new(cache_location, RealDenoCacheEnv));
|
||||||
let ts_server = TsServer::new(Default::default(), cache);
|
let ts_server =
|
||||||
|
TsServer::new(Default::default(), cache, Default::default());
|
||||||
ts_server.start(None);
|
ts_server.start(None);
|
||||||
let lint_options = LintOptions {
|
|
||||||
rules: Default::default(),
|
|
||||||
files: FilePatterns::new_with_base(temp_dir.path().to_path_buf()),
|
|
||||||
reporter_kind: Default::default(),
|
|
||||||
fix: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// test enabled
|
// test enabled
|
||||||
{
|
{
|
||||||
|
@ -1700,7 +1691,6 @@ let c: number = "a";
|
||||||
let diagnostics = generate_lint_diagnostics(
|
let diagnostics = generate_lint_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&enabled_config,
|
&enabled_config,
|
||||||
&lint_options,
|
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 6);
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 6);
|
||||||
|
@ -1712,7 +1702,7 @@ let c: number = "a";
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 5);
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 4);
|
||||||
let diagnostics = generate_deno_diagnostics(
|
let diagnostics = generate_deno_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&enabled_config,
|
&enabled_config,
|
||||||
|
@ -1732,7 +1722,6 @@ let c: number = "a";
|
||||||
let diagnostics = generate_lint_diagnostics(
|
let diagnostics = generate_lint_diagnostics(
|
||||||
&snapshot,
|
&snapshot,
|
||||||
&disabled_config,
|
&disabled_config,
|
||||||
&lint_options,
|
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0);
|
assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0);
|
||||||
|
@ -1793,7 +1782,8 @@ let c: number = "a";
|
||||||
}
|
}
|
||||||
}"#,
|
}"#,
|
||||||
)),
|
)),
|
||||||
);
|
)
|
||||||
|
.await;
|
||||||
let config = mock_config();
|
let config = mock_config();
|
||||||
let token = CancellationToken::new();
|
let token = CancellationToken::new();
|
||||||
let actual = generate_deno_diagnostics(&snapshot, &config, token);
|
let actual = generate_deno_diagnostics(&snapshot, &config, token);
|
||||||
|
@ -1919,7 +1909,8 @@ let c: number = "a";
|
||||||
LanguageId::TypeScript,
|
LanguageId::TypeScript,
|
||||||
)],
|
)],
|
||||||
None,
|
None,
|
||||||
);
|
)
|
||||||
|
.await;
|
||||||
let config = mock_config();
|
let config = mock_config();
|
||||||
let token = CancellationToken::new();
|
let token = CancellationToken::new();
|
||||||
let actual = generate_deno_diagnostics(&snapshot, &config, token);
|
let actual = generate_deno_diagnostics(&snapshot, &config, token);
|
||||||
|
|
|
@ -37,7 +37,6 @@ use deno_lockfile::Lockfile;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -817,15 +816,6 @@ impl FileSystemDocuments {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UpdateDocumentConfigOptions<'a> {
|
|
||||||
pub config: &'a Config,
|
|
||||||
pub maybe_import_map: Option<Arc<import_map::ImportMap>>,
|
|
||||||
pub maybe_package_json: Option<&'a PackageJson>,
|
|
||||||
pub node_resolver: Option<Arc<CliNodeResolver>>,
|
|
||||||
pub npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
|
||||||
pub workspace_files: &'a BTreeSet<ModuleSpecifier>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specify the documents to include on a `documents.documents(...)` call.
|
/// Specify the documents to include on a `documents.documents(...)` call.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum DocumentsFilter {
|
pub enum DocumentsFilter {
|
||||||
|
@ -1309,26 +1299,34 @@ impl Documents {
|
||||||
Arc::new(JsrCacheResolver::new(self.cache.clone(), lockfile));
|
Arc::new(JsrCacheResolver::new(self.cache.clone(), lockfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_config(&mut self, options: UpdateDocumentConfigOptions) {
|
pub fn update_config(
|
||||||
let maybe_config_file = options.config.maybe_config_file();
|
&mut self,
|
||||||
let maybe_package_json_deps =
|
config: &Config,
|
||||||
options.maybe_package_json.map(|package_json| {
|
node_resolver: Option<Arc<CliNodeResolver>>,
|
||||||
package_json::get_local_package_json_version_reqs(package_json)
|
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
||||||
});
|
workspace_files: &BTreeSet<ModuleSpecifier>,
|
||||||
let maybe_jsx_config = maybe_config_file
|
) {
|
||||||
.and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten());
|
let config_data = config.tree.root_data();
|
||||||
let deps_provider =
|
let config_file =
|
||||||
Arc::new(PackageJsonDepsProvider::new(maybe_package_json_deps));
|
config_data.as_ref().and_then(|d| d.config_file.as_deref());
|
||||||
self.resolver = Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
|
self.resolver = Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
|
||||||
node_resolver: options.node_resolver,
|
node_resolver,
|
||||||
npm_resolver: options.npm_resolver,
|
npm_resolver,
|
||||||
package_json_deps_provider: deps_provider,
|
package_json_deps_provider: Arc::new(PackageJsonDepsProvider::new(
|
||||||
maybe_jsx_import_source_config: maybe_jsx_config,
|
config_data
|
||||||
maybe_import_map: options.maybe_import_map,
|
.as_ref()
|
||||||
maybe_vendor_dir: maybe_config_file
|
.and_then(|d| d.package_json.as_ref())
|
||||||
.and_then(|c| c.vendor_dir_path())
|
.map(|package_json| {
|
||||||
.as_ref(),
|
package_json::get_local_package_json_version_reqs(package_json)
|
||||||
bare_node_builtins_enabled: maybe_config_file
|
}),
|
||||||
|
)),
|
||||||
|
maybe_jsx_import_source_config: config_file
|
||||||
|
.and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten()),
|
||||||
|
maybe_import_map: config_data.as_ref().and_then(|d| d.import_map.clone()),
|
||||||
|
maybe_vendor_dir: config_data
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|d| d.vendor_dir.as_ref()),
|
||||||
|
bare_node_builtins_enabled: config_file
|
||||||
.map(|config| config.has_unstable("bare-node-builtins"))
|
.map(|config| config.has_unstable("bare-node-builtins"))
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
// Don't set this for the LSP because instead we'll use the OpenDocumentsLoader
|
// Don't set this for the LSP because instead we'll use the OpenDocumentsLoader
|
||||||
|
@ -1338,16 +1336,14 @@ impl Documents {
|
||||||
}));
|
}));
|
||||||
self.jsr_resolver = Arc::new(JsrCacheResolver::new(
|
self.jsr_resolver = Arc::new(JsrCacheResolver::new(
|
||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
options.config.maybe_lockfile().cloned(),
|
config.tree.root_lockfile(),
|
||||||
));
|
));
|
||||||
self.redirect_resolver =
|
self.redirect_resolver =
|
||||||
Arc::new(RedirectResolver::new(self.cache.clone()));
|
Arc::new(RedirectResolver::new(self.cache.clone()));
|
||||||
let resolver = self.resolver.as_graph_resolver();
|
let resolver = self.resolver.as_graph_resolver();
|
||||||
let npm_resolver = self.resolver.as_graph_npm_resolver();
|
let npm_resolver = self.resolver.as_graph_npm_resolver();
|
||||||
self.imports = Arc::new(
|
self.imports = Arc::new(
|
||||||
if let Some(Ok(imports)) =
|
if let Some(Ok(imports)) = config_file.map(|cf| cf.to_maybe_imports()) {
|
||||||
maybe_config_file.map(|cf| cf.to_maybe_imports())
|
|
||||||
{
|
|
||||||
imports
|
imports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(referrer, imports)| {
|
.map(|(referrer, imports)| {
|
||||||
|
@ -1364,7 +1360,7 @@ impl Documents {
|
||||||
IndexMap::new()
|
IndexMap::new()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.unstable_sloppy_imports = maybe_config_file
|
self.unstable_sloppy_imports = config_file
|
||||||
.map(|c| c.has_unstable("sloppy-imports"))
|
.map(|c| c.has_unstable("sloppy-imports"))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
{
|
{
|
||||||
|
@ -1376,7 +1372,7 @@ impl Documents {
|
||||||
// anymore after updating resolvers.
|
// anymore after updating resolvers.
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if !options.config.specifier_enabled(specifier) {
|
if !config.specifier_enabled(specifier) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
path.is_file()
|
path.is_file()
|
||||||
|
@ -1384,7 +1380,7 @@ impl Documents {
|
||||||
let mut open_docs = std::mem::take(&mut self.open_docs);
|
let mut open_docs = std::mem::take(&mut self.open_docs);
|
||||||
for docs in [&mut open_docs, &mut fs_docs.docs] {
|
for docs in [&mut open_docs, &mut fs_docs.docs] {
|
||||||
for doc in docs.values_mut() {
|
for doc in docs.values_mut() {
|
||||||
if !options.config.specifier_enabled(doc.specifier()) {
|
if !config.specifier_enabled(doc.specifier()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(new_doc) =
|
if let Some(new_doc) =
|
||||||
|
@ -1395,8 +1391,8 @@ impl Documents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.open_docs = open_docs;
|
self.open_docs = open_docs;
|
||||||
for specifier in options.workspace_files {
|
for specifier in workspace_files {
|
||||||
if !options.config.specifier_enabled(specifier) {
|
if !config.specifier_enabled(specifier) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !self.open_docs.contains_key(specifier)
|
if !self.open_docs.contains_key(specifier)
|
||||||
|
@ -1738,8 +1734,9 @@ mod tests {
|
||||||
use crate::cache::RealDenoCacheEnv;
|
use crate::cache::RealDenoCacheEnv;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use deno_config::ConfigFile;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use import_map::ImportMap;
|
use deno_core::serde_json::json;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use test_util::PathRef;
|
use test_util::PathRef;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
@ -1842,8 +1839,8 @@ console.log(b, "hello deno");
|
||||||
assert_eq!(documents.documents(DocumentsFilter::All).len(), 1);
|
assert_eq!(documents.documents(DocumentsFilter::All).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn test_documents_refresh_dependencies_config_change() {
|
async fn test_documents_refresh_dependencies_config_change() {
|
||||||
// it should never happen that a user of this API causes this to happen,
|
// it should never happen that a user of this API causes this to happen,
|
||||||
// but we'll guard against it anyway
|
// but we'll guard against it anyway
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
|
@ -1878,23 +1875,23 @@ console.log(b, "hello deno");
|
||||||
|
|
||||||
// set the initial import map and point to file 2
|
// set the initial import map and point to file 2
|
||||||
{
|
{
|
||||||
let mut import_map = ImportMap::new(
|
config
|
||||||
ModuleSpecifier::from_file_path(documents_path.join("import_map.json"))
|
.tree
|
||||||
|
.inject_config_file(
|
||||||
|
ConfigFile::new(
|
||||||
|
&json!({
|
||||||
|
"imports": {
|
||||||
|
"test": "./file2.ts",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
config.root_uri().unwrap().join("deno.json").unwrap(),
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
)
|
||||||
import_map
|
.await;
|
||||||
.imports_mut()
|
|
||||||
.append("test".to_string(), "./file2.ts".to_string())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
documents.update_config(UpdateDocumentConfigOptions {
|
documents.update_config(&config, None, None, &workspace_files);
|
||||||
config: &config,
|
|
||||||
maybe_import_map: Some(Arc::new(import_map)),
|
|
||||||
maybe_package_json: None,
|
|
||||||
node_resolver: None,
|
|
||||||
npm_resolver: None,
|
|
||||||
workspace_files: &workspace_files,
|
|
||||||
});
|
|
||||||
|
|
||||||
// open the document
|
// open the document
|
||||||
let document = documents.open(
|
let document = documents.open(
|
||||||
|
@ -1918,23 +1915,23 @@ console.log(b, "hello deno");
|
||||||
|
|
||||||
// now point at file 3
|
// now point at file 3
|
||||||
{
|
{
|
||||||
let mut import_map = ImportMap::new(
|
config
|
||||||
ModuleSpecifier::from_file_path(documents_path.join("import_map.json"))
|
.tree
|
||||||
|
.inject_config_file(
|
||||||
|
ConfigFile::new(
|
||||||
|
&json!({
|
||||||
|
"imports": {
|
||||||
|
"test": "./file3.ts",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
config.root_uri().unwrap().join("deno.json").unwrap(),
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
)
|
||||||
import_map
|
.await;
|
||||||
.imports_mut()
|
|
||||||
.append("test".to_string(), "./file3.ts".to_string())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
documents.update_config(UpdateDocumentConfigOptions {
|
documents.update_config(&config, None, None, &workspace_files);
|
||||||
config: &config,
|
|
||||||
maybe_import_map: Some(Arc::new(import_map)),
|
|
||||||
maybe_package_json: None,
|
|
||||||
node_resolver: None,
|
|
||||||
npm_resolver: None,
|
|
||||||
workspace_files: &workspace_files,
|
|
||||||
});
|
|
||||||
|
|
||||||
// check the document's dependencies
|
// check the document's dependencies
|
||||||
let document = documents.get(&file1_specifier).unwrap();
|
let document = documents.get(&file1_specifier).unwrap();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
121
cli/lsp/tsc.rs
121
cli/lsp/tsc.rs
|
@ -3,6 +3,7 @@
|
||||||
use super::analysis::CodeActionData;
|
use super::analysis::CodeActionData;
|
||||||
use super::code_lens;
|
use super::code_lens;
|
||||||
use super::config;
|
use super::config;
|
||||||
|
use super::config::ConfigTree;
|
||||||
use super::documents::AssetOrDocument;
|
use super::documents::AssetOrDocument;
|
||||||
use super::documents::DocumentsFilter;
|
use super::documents::DocumentsFilter;
|
||||||
use super::language_server;
|
use super::language_server;
|
||||||
|
@ -22,7 +23,6 @@ use super::urls::INVALID_SPECIFIER;
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
use crate::args::FmtOptionsConfig;
|
use crate::args::FmtOptionsConfig;
|
||||||
use crate::args::TsConfig;
|
|
||||||
use crate::cache::HttpCache;
|
use crate::cache::HttpCache;
|
||||||
use crate::lsp::cache::CacheMetadata;
|
use crate::lsp::cache::CacheMetadata;
|
||||||
use crate::lsp::documents::Documents;
|
use crate::lsp::documents::Documents;
|
||||||
|
@ -221,6 +221,7 @@ pub struct TsServer {
|
||||||
sender: mpsc::UnboundedSender<Request>,
|
sender: mpsc::UnboundedSender<Request>,
|
||||||
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
|
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
specifier_map: Arc<TscSpecifierMap>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
inspector_server: Mutex<Option<Arc<InspectorServer>>>,
|
inspector_server: Mutex<Option<Arc<InspectorServer>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +239,11 @@ impl std::fmt::Debug for TsServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TsServer {
|
impl TsServer {
|
||||||
pub fn new(performance: Arc<Performance>, cache: Arc<dyn HttpCache>) -> Self {
|
pub fn new(
|
||||||
|
performance: Arc<Performance>,
|
||||||
|
cache: Arc<dyn HttpCache>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
|
) -> Self {
|
||||||
let (tx, request_rx) = mpsc::unbounded_channel::<Request>();
|
let (tx, request_rx) = mpsc::unbounded_channel::<Request>();
|
||||||
Self {
|
Self {
|
||||||
performance,
|
performance,
|
||||||
|
@ -246,6 +251,7 @@ impl TsServer {
|
||||||
sender: tx,
|
sender: tx,
|
||||||
receiver: Mutex::new(Some(request_rx)),
|
receiver: Mutex::new(Some(request_rx)),
|
||||||
specifier_map: Arc::new(TscSpecifierMap::new()),
|
specifier_map: Arc::new(TscSpecifierMap::new()),
|
||||||
|
config_tree,
|
||||||
inspector_server: Mutex::new(None),
|
inspector_server: Mutex::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,6 +274,7 @@ impl TsServer {
|
||||||
let performance = self.performance.clone();
|
let performance = self.performance.clone();
|
||||||
let cache = self.cache.clone();
|
let cache = self.cache.clone();
|
||||||
let specifier_map = self.specifier_map.clone();
|
let specifier_map = self.specifier_map.clone();
|
||||||
|
let config_tree = self.config_tree.clone();
|
||||||
let _join_handle = thread::spawn(move || {
|
let _join_handle = thread::spawn(move || {
|
||||||
run_tsc_thread(
|
run_tsc_thread(
|
||||||
receiver,
|
receiver,
|
||||||
|
@ -275,6 +282,7 @@ impl TsServer {
|
||||||
cache.clone(),
|
cache.clone(),
|
||||||
specifier_map.clone(),
|
specifier_map.clone(),
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
|
config_tree,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -343,18 +351,6 @@ impl TsServer {
|
||||||
self.request(snapshot, req).await
|
self.request(snapshot, req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn configure(
|
|
||||||
&self,
|
|
||||||
snapshot: Arc<StateSnapshot>,
|
|
||||||
tsconfig: TsConfig,
|
|
||||||
) -> Result<bool, AnyError> {
|
|
||||||
let req = TscRequest {
|
|
||||||
method: "$configure",
|
|
||||||
args: json!([tsconfig]),
|
|
||||||
};
|
|
||||||
self.request(snapshot, req).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_supported_code_fixes(
|
pub async fn get_supported_code_fixes(
|
||||||
&self,
|
&self,
|
||||||
snapshot: Arc<StateSnapshot>,
|
snapshot: Arc<StateSnapshot>,
|
||||||
|
@ -3482,7 +3478,7 @@ impl CompletionEntry {
|
||||||
{
|
{
|
||||||
if let Ok(import_specifier) = resolve_url(&import_data.file_name) {
|
if let Ok(import_specifier) = resolve_url(&import_data.file_name) {
|
||||||
if let Some(new_module_specifier) = language_server
|
if let Some(new_module_specifier) = language_server
|
||||||
.get_ts_response_import_mapper()
|
.get_ts_response_import_mapper(specifier)
|
||||||
.check_specifier(&import_specifier, specifier)
|
.check_specifier(&import_specifier, specifier)
|
||||||
.or_else(|| relative_specifier(specifier, &import_specifier))
|
.or_else(|| relative_specifier(specifier, &import_specifier))
|
||||||
{
|
{
|
||||||
|
@ -3849,6 +3845,7 @@ struct State {
|
||||||
response: Option<Response>,
|
response: Option<Response>,
|
||||||
state_snapshot: Arc<StateSnapshot>,
|
state_snapshot: Arc<StateSnapshot>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
specifier_map: Arc<TscSpecifierMap>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3856,6 +3853,7 @@ impl State {
|
||||||
fn new(
|
fn new(
|
||||||
state_snapshot: Arc<StateSnapshot>,
|
state_snapshot: Arc<StateSnapshot>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
specifier_map: Arc<TscSpecifierMap>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -3864,6 +3862,7 @@ impl State {
|
||||||
response: None,
|
response: None,
|
||||||
state_snapshot,
|
state_snapshot,
|
||||||
specifier_map,
|
specifier_map,
|
||||||
|
config_tree,
|
||||||
token: Default::default(),
|
token: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4077,10 +4076,20 @@ fn op_script_version(
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[serde]
|
||||||
|
fn op_ts_config(state: &mut OpState) -> serde_json::Value {
|
||||||
|
let state = state.borrow_mut::<State>();
|
||||||
|
let mark = state.performance.mark("tsc.op.op_ts_config");
|
||||||
|
let r = json!(state.config_tree.root_ts_config());
|
||||||
|
state.performance.measure(mark);
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
fn op_project_version(state: &mut OpState) -> String {
|
fn op_project_version(state: &mut OpState) -> String {
|
||||||
let state = state.borrow_mut::<State>();
|
let state: &mut State = state.borrow_mut::<State>();
|
||||||
let mark = state.performance.mark("tsc.op.op_project_version");
|
let mark = state.performance.mark("tsc.op.op_project_version");
|
||||||
let r = state.state_snapshot.documents.project_version();
|
let r = state.state_snapshot.documents.project_version();
|
||||||
state.performance.measure(mark);
|
state.performance.measure(mark);
|
||||||
|
@ -4093,13 +4102,19 @@ fn run_tsc_thread(
|
||||||
cache: Arc<dyn HttpCache>,
|
cache: Arc<dyn HttpCache>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
specifier_map: Arc<TscSpecifierMap>,
|
||||||
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
) {
|
) {
|
||||||
let has_inspector_server = maybe_inspector_server.is_some();
|
let has_inspector_server = maybe_inspector_server.is_some();
|
||||||
// Create and setup a JsRuntime based on a snapshot. It is expected that the
|
// Create and setup a JsRuntime based on a snapshot. It is expected that the
|
||||||
// supplied snapshot is an isolate that contains the TypeScript language
|
// supplied snapshot is an isolate that contains the TypeScript language
|
||||||
// server.
|
// server.
|
||||||
let mut tsc_runtime = JsRuntime::new(RuntimeOptions {
|
let mut tsc_runtime = JsRuntime::new(RuntimeOptions {
|
||||||
extensions: vec![deno_tsc::init_ops(performance, cache, specifier_map)],
|
extensions: vec![deno_tsc::init_ops(
|
||||||
|
performance,
|
||||||
|
cache,
|
||||||
|
specifier_map,
|
||||||
|
config_tree,
|
||||||
|
)],
|
||||||
startup_snapshot: Some(tsc::compiler_snapshot()),
|
startup_snapshot: Some(tsc::compiler_snapshot()),
|
||||||
inspector: maybe_inspector_server.is_some(),
|
inspector: maybe_inspector_server.is_some(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -4166,12 +4181,14 @@ deno_core::extension!(deno_tsc,
|
||||||
op_respond,
|
op_respond,
|
||||||
op_script_names,
|
op_script_names,
|
||||||
op_script_version,
|
op_script_version,
|
||||||
|
op_ts_config,
|
||||||
op_project_version,
|
op_project_version,
|
||||||
],
|
],
|
||||||
options = {
|
options = {
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
cache: Arc<dyn HttpCache>,
|
cache: Arc<dyn HttpCache>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
specifier_map: Arc<TscSpecifierMap>,
|
||||||
|
config_tree: Arc<ConfigTree>,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
state.put(State::new(
|
state.put(State::new(
|
||||||
|
@ -4180,10 +4197,10 @@ deno_core::extension!(deno_tsc,
|
||||||
cache_metadata: CacheMetadata::new(options.cache.clone()),
|
cache_metadata: CacheMetadata::new(options.cache.clone()),
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
documents: Documents::new(options.cache.clone()),
|
documents: Documents::new(options.cache.clone()),
|
||||||
maybe_import_map: None,
|
|
||||||
npm: None,
|
npm: None,
|
||||||
}),
|
}),
|
||||||
options.specifier_map,
|
options.specifier_map,
|
||||||
|
options.config_tree,
|
||||||
options.performance,
|
options.performance,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
@ -4344,9 +4361,10 @@ pub struct UserPreferences {
|
||||||
impl UserPreferences {
|
impl UserPreferences {
|
||||||
pub fn from_config_for_specifier(
|
pub fn from_config_for_specifier(
|
||||||
config: &config::Config,
|
config: &config::Config,
|
||||||
fmt_config: &FmtOptionsConfig,
|
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let fmt_options = config.tree.fmt_options_for_specifier(specifier);
|
||||||
|
let fmt_config = &fmt_options.options;
|
||||||
let base_preferences = Self {
|
let base_preferences = Self {
|
||||||
allow_incomplete_completions: Some(true),
|
allow_incomplete_completions: Some(true),
|
||||||
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
||||||
|
@ -4450,7 +4468,8 @@ impl UserPreferences {
|
||||||
language_settings.preferences.use_aliases_for_renames,
|
language_settings.preferences.use_aliases_for_renames,
|
||||||
),
|
),
|
||||||
// Only use workspace settings for quote style if there's no `deno.json`.
|
// Only use workspace settings for quote style if there's no `deno.json`.
|
||||||
quote_preference: if config.has_config_file() {
|
quote_preference: if config.tree.has_config_file_for_specifier(specifier)
|
||||||
|
{
|
||||||
base_preferences.quote_preference
|
base_preferences.quote_preference
|
||||||
} else {
|
} else {
|
||||||
Some(language_settings.preferences.quote_style)
|
Some(language_settings.preferences.quote_style)
|
||||||
|
@ -4630,7 +4649,6 @@ mod tests {
|
||||||
assets: Default::default(),
|
assets: Default::default(),
|
||||||
cache_metadata: CacheMetadata::new(cache),
|
cache_metadata: CacheMetadata::new(cache),
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
maybe_import_map: None,
|
|
||||||
npm: None,
|
npm: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4645,13 +4663,21 @@ mod tests {
|
||||||
Arc::new(GlobalHttpCache::new(location.clone(), RealDenoCacheEnv));
|
Arc::new(GlobalHttpCache::new(location.clone(), RealDenoCacheEnv));
|
||||||
let snapshot = Arc::new(mock_state_snapshot(sources, &location));
|
let snapshot = Arc::new(mock_state_snapshot(sources, &location));
|
||||||
let performance = Arc::new(Performance::default());
|
let performance = Arc::new(Performance::default());
|
||||||
let ts_server = TsServer::new(performance, cache.clone());
|
let config_tree = Arc::new(ConfigTree::default());
|
||||||
|
config_tree
|
||||||
|
.inject_config_file(
|
||||||
|
deno_config::ConfigFile::new(
|
||||||
|
&json!({
|
||||||
|
"compilerOptions": config,
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
resolve_url("file:///deno.json").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let ts_server = TsServer::new(performance, cache.clone(), config_tree);
|
||||||
ts_server.start(None);
|
ts_server.start(None);
|
||||||
let ts_config = TsConfig::new(config);
|
|
||||||
assert!(ts_server
|
|
||||||
.configure(snapshot.clone(), ts_config,)
|
|
||||||
.await
|
|
||||||
.unwrap());
|
|
||||||
(ts_server, snapshot, cache)
|
(ts_server, snapshot, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4670,43 +4696,6 @@ mod tests {
|
||||||
assert_eq!(actual, r"test [`a link`](http://deno.land/x/mod.ts) test");
|
assert_eq!(actual, r"test [`a link`](http://deno.land/x/mod.ts) test");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_project_configure() {
|
|
||||||
let temp_dir = TempDir::new();
|
|
||||||
setup(
|
|
||||||
&temp_dir,
|
|
||||||
json!({
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"noEmit": true,
|
|
||||||
}),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_project_reconfigure() {
|
|
||||||
let temp_dir = TempDir::new();
|
|
||||||
let (ts_server, snapshot, _) = setup(
|
|
||||||
&temp_dir,
|
|
||||||
json!({
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"noEmit": true,
|
|
||||||
}),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
let ts_config = TsConfig::new(json!({
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"noEmit": true,
|
|
||||||
"lib": ["deno.ns", "deno.worker"]
|
|
||||||
}));
|
|
||||||
assert!(ts_server.configure(snapshot, ts_config).await.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_diagnostics() {
|
async fn test_get_diagnostics() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
|
@ -4716,6 +4705,7 @@ mod tests {
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
"lib": [],
|
||||||
}),
|
}),
|
||||||
&[(
|
&[(
|
||||||
"file:///a.ts",
|
"file:///a.ts",
|
||||||
|
@ -5468,11 +5458,10 @@ mod tests {
|
||||||
.inlay_hints
|
.inlay_hints
|
||||||
.variable_types
|
.variable_types
|
||||||
.suppress_when_type_matches_name = true;
|
.suppress_when_type_matches_name = true;
|
||||||
let mut config = config::Config::new();
|
let mut config = config::Config::default();
|
||||||
config.set_workspace_settings(settings, vec![]);
|
config.set_workspace_settings(settings, vec![]);
|
||||||
let user_preferences = UserPreferences::from_config_for_specifier(
|
let user_preferences = UserPreferences::from_config_for_specifier(
|
||||||
&config,
|
&config,
|
||||||
&Default::default(),
|
|
||||||
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -857,6 +857,12 @@ pub struct ConfiguredRules {
|
||||||
pub no_slow_types: bool,
|
pub no_slow_types: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ConfiguredRules {
|
||||||
|
fn default() -> Self {
|
||||||
|
get_configured_rules(Default::default(), None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConfiguredRules {
|
impl ConfiguredRules {
|
||||||
fn incremental_cache_state(&self) -> Vec<&str> {
|
fn incremental_cache_state(&self) -> Vec<&str> {
|
||||||
// use a hash of the rule names in order to bust the cache
|
// use a hash of the rule names in order to bust the cache
|
||||||
|
|
|
@ -503,9 +503,6 @@ delete Object.prototype.__proto__;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {ts.CompilerOptions} */
|
|
||||||
let compilationSettings = {};
|
|
||||||
|
|
||||||
/** @type {ts.LanguageService} */
|
/** @type {ts.LanguageService} */
|
||||||
let languageService;
|
let languageService;
|
||||||
|
|
||||||
|
@ -720,7 +717,17 @@ delete Object.prototype.__proto__;
|
||||||
if (logDebug) {
|
if (logDebug) {
|
||||||
debug("host.getCompilationSettings()");
|
debug("host.getCompilationSettings()");
|
||||||
}
|
}
|
||||||
return compilationSettings;
|
const tsConfig = normalizeConfig(ops.op_ts_config());
|
||||||
|
const { options, errors } = ts
|
||||||
|
.convertCompilerOptionsFromJson(tsConfig, "");
|
||||||
|
Object.assign(options, {
|
||||||
|
allowNonTsExtensions: true,
|
||||||
|
allowImportingTsExtensions: true,
|
||||||
|
});
|
||||||
|
if (errors.length > 0 && logDebug) {
|
||||||
|
debug(ts.formatDiagnostics(errors, host));
|
||||||
|
}
|
||||||
|
return options;
|
||||||
},
|
},
|
||||||
getScriptFileNames() {
|
getScriptFileNames() {
|
||||||
if (logDebug) {
|
if (logDebug) {
|
||||||
|
@ -1010,21 +1017,6 @@ delete Object.prototype.__proto__;
|
||||||
serverRestart();
|
serverRestart();
|
||||||
return respond(id, true);
|
return respond(id, true);
|
||||||
}
|
}
|
||||||
case "$configure": {
|
|
||||||
const config = normalizeConfig(args[0]);
|
|
||||||
const { options, errors } = ts
|
|
||||||
.convertCompilerOptionsFromJson(config, "");
|
|
||||||
Object.assign(options, {
|
|
||||||
allowNonTsExtensions: true,
|
|
||||||
allowImportingTsExtensions: true,
|
|
||||||
});
|
|
||||||
if (errors.length > 0 && logDebug) {
|
|
||||||
debug(ts.formatDiagnostics(errors, host));
|
|
||||||
}
|
|
||||||
compilationSettings = options;
|
|
||||||
moduleSpecifierCache.clear();
|
|
||||||
return respond(id, true);
|
|
||||||
}
|
|
||||||
case "$getSupportedCodeFixes": {
|
case "$getSupportedCodeFixes": {
|
||||||
return respond(
|
return respond(
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -145,32 +145,6 @@ fn lsp_tsconfig_types_config_sub_dir() {
|
||||||
client.shutdown();
|
client.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn lsp_tsconfig_bad_config_path() {
|
|
||||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
|
||||||
let mut client = context.new_lsp_command().build();
|
|
||||||
client.initialize(|builder| {
|
|
||||||
builder
|
|
||||||
.set_config("bad_tsconfig.json")
|
|
||||||
.set_maybe_root_uri(None);
|
|
||||||
});
|
|
||||||
let (method, maybe_params) = client.read_notification();
|
|
||||||
assert_eq!(method, "window/showMessage");
|
|
||||||
assert_eq!(maybe_params, Some(lsp::ShowMessageParams {
|
|
||||||
typ: lsp::MessageType::WARNING,
|
|
||||||
message: "The path to the configuration file (\"bad_tsconfig.json\") is not resolvable.".to_string()
|
|
||||||
}));
|
|
||||||
let diagnostics = client.did_open(json!({
|
|
||||||
"textDocument": {
|
|
||||||
"uri": "file:///a/file.ts",
|
|
||||||
"languageId": "typescript",
|
|
||||||
"version": 1,
|
|
||||||
"text": "console.log(Deno.args);\n"
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
assert_eq!(diagnostics.all().len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_triple_slash_types() {
|
fn lsp_triple_slash_types() {
|
||||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||||
|
@ -223,7 +197,7 @@ fn lsp_import_map() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
assert_eq!(diagnostics.all().len(), 0);
|
assert_eq!(json!(diagnostics.all()), json!([]));
|
||||||
|
|
||||||
let res = client.write_request(
|
let res = client.write_request(
|
||||||
"textDocument/hover",
|
"textDocument/hover",
|
||||||
|
@ -497,7 +471,7 @@ fn lsp_import_map_embedded_in_config_file_after_initialize() {
|
||||||
}]
|
}]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
assert_eq!(client.read_diagnostics().all().len(), 0);
|
assert_eq!(json!(client.read_diagnostics().all()), json!([]));
|
||||||
|
|
||||||
let res = client.write_request(
|
let res = client.write_request(
|
||||||
"textDocument/hover",
|
"textDocument/hover",
|
||||||
|
@ -546,7 +520,7 @@ fn lsp_import_map_config_file_auto_discovered() {
|
||||||
}]
|
}]
|
||||||
}));
|
}));
|
||||||
client.wait_until_stderr_line(|line| {
|
client.wait_until_stderr_line(|line| {
|
||||||
line.contains("Auto-resolved configuration file:")
|
line.contains(" Resolved Deno configuration file:")
|
||||||
});
|
});
|
||||||
|
|
||||||
let uri = temp_dir.uri().join("a.ts").unwrap();
|
let uri = temp_dir.uri().join("a.ts").unwrap();
|
||||||
|
@ -607,7 +581,7 @@ fn lsp_import_map_config_file_auto_discovered() {
|
||||||
}]
|
}]
|
||||||
}));
|
}));
|
||||||
client.wait_until_stderr_line(|line| {
|
client.wait_until_stderr_line(|line| {
|
||||||
line.contains("Auto-resolved configuration file:")
|
line.contains(" Resolved Deno configuration file:")
|
||||||
});
|
});
|
||||||
let res = client.write_request(
|
let res = client.write_request(
|
||||||
"textDocument/hover",
|
"textDocument/hover",
|
||||||
|
@ -675,7 +649,7 @@ fn lsp_import_map_config_file_auto_discovered_symlink() {
|
||||||
|
|
||||||
// this will discover the deno.json in the root
|
// this will discover the deno.json in the root
|
||||||
let search_line = format!(
|
let search_line = format!(
|
||||||
"Auto-resolved configuration file: \"{}\"",
|
" Resolved Deno configuration file: \"{}\"",
|
||||||
temp_dir.uri().join("deno.json").unwrap().as_str()
|
temp_dir.uri().join("deno.json").unwrap().as_str()
|
||||||
);
|
);
|
||||||
client.wait_until_stderr_line(|line| line.contains(&search_line));
|
client.wait_until_stderr_line(|line| line.contains(&search_line));
|
||||||
|
@ -8946,10 +8920,7 @@ fn lsp_performance() {
|
||||||
"lsp.update_diagnostics_deps",
|
"lsp.update_diagnostics_deps",
|
||||||
"lsp.update_diagnostics_lint",
|
"lsp.update_diagnostics_lint",
|
||||||
"lsp.update_diagnostics_ts",
|
"lsp.update_diagnostics_ts",
|
||||||
"lsp.update_import_map",
|
|
||||||
"lsp.update_registries",
|
"lsp.update_registries",
|
||||||
"lsp.update_tsconfig",
|
|
||||||
"tsc.host.$configure",
|
|
||||||
"tsc.host.$getAssets",
|
"tsc.host.$getAssets",
|
||||||
"tsc.host.$getDiagnostics",
|
"tsc.host.$getDiagnostics",
|
||||||
"tsc.host.$getSupportedCodeFixes",
|
"tsc.host.$getSupportedCodeFixes",
|
||||||
|
@ -8959,7 +8930,7 @@ fn lsp_performance() {
|
||||||
"tsc.op.op_project_version",
|
"tsc.op.op_project_version",
|
||||||
"tsc.op.op_script_names",
|
"tsc.op.op_script_names",
|
||||||
"tsc.op.op_script_version",
|
"tsc.op.op_script_version",
|
||||||
"tsc.request.$configure",
|
"tsc.op.op_ts_config",
|
||||||
"tsc.request.$getAssets",
|
"tsc.request.$getAssets",
|
||||||
"tsc.request.$getSupportedCodeFixes",
|
"tsc.request.$getSupportedCodeFixes",
|
||||||
"tsc.request.getQuickInfoAtPosition",
|
"tsc.request.getQuickInfoAtPosition",
|
||||||
|
|
Loading…
Add table
Reference in a new issue