3551: Move FeatureFlags r=matklad a=matklad



bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-03-10 17:56:44 +00:00 committed by GitHub
commit e5df8c4028
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 88 additions and 68 deletions

View file

@ -33,6 +33,23 @@ pub use crate::completion::completion_item::{
CompletionItem, CompletionItemKind, InsertTextFormat, CompletionItem, CompletionItemKind, InsertTextFormat,
}; };
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionOptions {
pub enable_postfix_completions: bool,
pub add_call_parenthesis: bool,
pub add_call_argument_snippets: bool,
}
impl Default for CompletionOptions {
fn default() -> Self {
CompletionOptions {
enable_postfix_completions: true,
add_call_parenthesis: true,
add_call_argument_snippets: true,
}
}
}
/// Main entry point for completion. We run completion as a two-phase process. /// Main entry point for completion. We run completion as a two-phase process.
/// ///
/// First, we look at the position and collect a so-called `CompletionContext. /// First, we look at the position and collect a so-called `CompletionContext.
@ -55,8 +72,12 @@ pub use crate::completion::completion_item::{
/// `foo` *should* be present among the completion variants. Filtering by /// `foo` *should* be present among the completion variants. Filtering by
/// identifier prefix/fuzzy match should be done higher in the stack, together /// identifier prefix/fuzzy match should be done higher in the stack, together
/// with ordering of completions (currently this is done by the client). /// with ordering of completions (currently this is done by the client).
pub(crate) fn completions(db: &RootDatabase, position: FilePosition) -> Option<Completions> { pub(crate) fn completions(
let ctx = CompletionContext::new(db, position)?; db: &RootDatabase,
position: FilePosition,
opts: &CompletionOptions,
) -> Option<Completions> {
let ctx = CompletionContext::new(db, position, opts)?;
let mut acc = Completions::default(); let mut acc = Completions::default();

View file

@ -12,7 +12,7 @@ use crate::{
}; };
pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.db.feature_flags.get("completion.enable-postfix") { if !ctx.options.enable_postfix_completions {
return; return;
} }

View file

@ -11,7 +11,7 @@ use ra_syntax::{
}; };
use ra_text_edit::AtomTextEdit; use ra_text_edit::AtomTextEdit;
use crate::FilePosition; use crate::{completion::CompletionOptions, FilePosition};
/// `CompletionContext` is created early during completion to figure out, where /// `CompletionContext` is created early during completion to figure out, where
/// exactly is the cursor, syntax-wise. /// exactly is the cursor, syntax-wise.
@ -19,6 +19,7 @@ use crate::FilePosition;
pub(crate) struct CompletionContext<'a> { pub(crate) struct CompletionContext<'a> {
pub(super) sema: Semantics<'a, RootDatabase>, pub(super) sema: Semantics<'a, RootDatabase>,
pub(super) db: &'a RootDatabase, pub(super) db: &'a RootDatabase,
pub(super) options: &'a CompletionOptions,
pub(super) offset: TextUnit, pub(super) offset: TextUnit,
/// The token before the cursor, in the original file. /// The token before the cursor, in the original file.
pub(super) original_token: SyntaxToken, pub(super) original_token: SyntaxToken,
@ -57,6 +58,7 @@ impl<'a> CompletionContext<'a> {
pub(super) fn new( pub(super) fn new(
db: &'a RootDatabase, db: &'a RootDatabase,
position: FilePosition, position: FilePosition,
options: &'a CompletionOptions,
) -> Option<CompletionContext<'a>> { ) -> Option<CompletionContext<'a>> {
let sema = Semantics::new(db); let sema = Semantics::new(db);
@ -80,6 +82,7 @@ impl<'a> CompletionContext<'a> {
let mut ctx = CompletionContext { let mut ctx = CompletionContext {
sema, sema,
db, db,
options,
original_token, original_token,
token, token,
offset: position.offset, offset: position.offset,

View file

@ -321,14 +321,18 @@ impl Into<Vec<CompletionItem>> for Completions {
#[cfg(test)] #[cfg(test)]
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
use crate::completion::completions; use crate::{
use crate::mock_analysis::{analysis_and_position, single_file_with_position}; completion::{completions, CompletionOptions},
mock_analysis::{analysis_and_position, single_file_with_position},
};
let (analysis, position) = if code.contains("//-") { let (analysis, position) = if code.contains("//-") {
analysis_and_position(code) analysis_and_position(code)
} else { } else {
single_file_with_position(code) single_file_with_position(code)
}; };
let completions = completions(&analysis.db, position).unwrap(); let options = CompletionOptions::default();
let completions = completions(&analysis.db, position, &options).unwrap();
let completion_items: Vec<CompletionItem> = completions.into(); let completion_items: Vec<CompletionItem> = completions.into();
let mut kind_completions: Vec<CompletionItem> = let mut kind_completions: Vec<CompletionItem> =
completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();

View file

@ -104,10 +104,7 @@ impl Completions {
}; };
// Add `<>` for generic types // Add `<>` for generic types
if ctx.is_path_type if ctx.is_path_type && !ctx.has_type_args && ctx.options.add_call_parenthesis {
&& !ctx.has_type_args
&& ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
{
let has_non_default_type_params = match resolution { let has_non_default_type_params = match resolution {
ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db),
ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db),
@ -212,21 +209,14 @@ impl Completions {
.detail(function_signature.to_string()); .detail(function_signature.to_string());
// If not an import, add parenthesis automatically. // If not an import, add parenthesis automatically.
if ctx.use_item_syntax.is_none() if ctx.use_item_syntax.is_none() && !ctx.is_call && ctx.options.add_call_parenthesis {
&& !ctx.is_call
&& ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
{
tested_by!(inserts_parens_for_function_calls); tested_by!(inserts_parens_for_function_calls);
let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 { let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
(format!("{}()$0", name), format!("{}()", name)) (format!("{}()$0", name), format!("{}()", name))
} else { } else {
builder = builder.trigger_call_info(); builder = builder.trigger_call_info();
let snippet = if ctx let snippet = if ctx.options.add_call_argument_snippets {
.db
.feature_flags
.get("completion.insertion.add-argument-snippets")
{
let to_skip = if has_self_param { 1 } else { 0 }; let to_skip = if has_self_param { 1 } else { 0 };
let function_params_snippet = join( let function_params_snippet = join(
function_signature.parameter_names.iter().skip(to_skip).enumerate().map( function_signature.parameter_names.iter().skip(to_skip).enumerate().map(

View file

@ -62,7 +62,7 @@ use crate::display::ToNav;
pub use crate::{ pub use crate::{
assists::{Assist, AssistId}, assists::{Assist, AssistId},
call_hierarchy::CallItem, call_hierarchy::CallItem,
completion::{CompletionItem, CompletionItemKind, InsertTextFormat}, completion::{CompletionItem, CompletionItemKind, CompletionOptions, InsertTextFormat},
diagnostics::Severity, diagnostics::Severity,
display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
expand_macro::ExpandedMacro, expand_macro::ExpandedMacro,
@ -84,7 +84,6 @@ pub use ra_db::{
}; };
pub use ra_ide_db::{ pub use ra_ide_db::{
change::{AnalysisChange, LibraryData}, change::{AnalysisChange, LibraryData},
feature_flags::FeatureFlags,
line_index::{LineCol, LineIndex}, line_index::{LineCol, LineIndex},
line_index_utils::translate_offset_with_edit, line_index_utils::translate_offset_with_edit,
search::SearchScope, search::SearchScope,
@ -131,13 +130,13 @@ pub struct AnalysisHost {
impl Default for AnalysisHost { impl Default for AnalysisHost {
fn default() -> AnalysisHost { fn default() -> AnalysisHost {
AnalysisHost::new(None, FeatureFlags::default()) AnalysisHost::new(None)
} }
} }
impl AnalysisHost { impl AnalysisHost {
pub fn new(lru_capcity: Option<usize>, feature_flags: FeatureFlags) -> AnalysisHost { pub fn new(lru_capacity: Option<usize>) -> AnalysisHost {
AnalysisHost { db: RootDatabase::new(lru_capcity, feature_flags) } AnalysisHost { db: RootDatabase::new(lru_capacity) }
} }
/// Returns a snapshot of the current state, which you can query for /// Returns a snapshot of the current state, which you can query for
/// semantic information. /// semantic information.
@ -145,10 +144,6 @@ impl AnalysisHost {
Analysis { db: self.db.snapshot() } Analysis { db: self.db.snapshot() }
} }
pub fn feature_flags(&self) -> &FeatureFlags {
&self.db.feature_flags
}
/// Applies changes to the current state of the world. If there are /// Applies changes to the current state of the world. If there are
/// outstanding snapshots, they will be canceled. /// outstanding snapshots, they will be canceled.
pub fn apply_change(&mut self, change: AnalysisChange) { pub fn apply_change(&mut self, change: AnalysisChange) {
@ -224,11 +219,6 @@ impl Analysis {
(host.analysis(), file_id) (host.analysis(), file_id)
} }
/// Features for Analysis.
pub fn feature_flags(&self) -> &FeatureFlags {
&self.db.feature_flags
}
/// Debug info about the current state of the analysis. /// Debug info about the current state of the analysis.
pub fn status(&self) -> Cancelable<String> { pub fn status(&self) -> Cancelable<String> {
self.with_db(|db| status::status(&*db)) self.with_db(|db| status::status(&*db))
@ -450,8 +440,12 @@ impl Analysis {
} }
/// Computes completions at the given position. /// Computes completions at the given position.
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { pub fn completions(
self.with_db(|db| completion::completions(db, position).map(Into::into)) &self,
position: FilePosition,
options: &CompletionOptions,
) -> Cancelable<Option<Vec<CompletionItem>>> {
self.with_db(|db| completion::completions(db, position, options).map(Into::into))
} }
/// Computes assists (aka code actions aka intentions) for the given /// Computes assists (aka code actions aka intentions) for the given

View file

@ -5,7 +5,6 @@
pub mod marks; pub mod marks;
pub mod line_index; pub mod line_index;
pub mod line_index_utils; pub mod line_index_utils;
pub mod feature_flags;
pub mod symbol_index; pub mod symbol_index;
pub mod change; pub mod change;
pub mod defs; pub mod defs;
@ -22,7 +21,7 @@ use ra_db::{
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::{feature_flags::FeatureFlags, line_index::LineIndex, symbol_index::SymbolsDatabase}; use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
#[salsa::database( #[salsa::database(
ra_db::SourceDatabaseStorage, ra_db::SourceDatabaseStorage,
@ -37,7 +36,6 @@ use crate::{feature_flags::FeatureFlags, line_index::LineIndex, symbol_index::Sy
#[derive(Debug)] #[derive(Debug)]
pub struct RootDatabase { pub struct RootDatabase {
runtime: salsa::Runtime<RootDatabase>, runtime: salsa::Runtime<RootDatabase>,
pub feature_flags: Arc<FeatureFlags>,
pub(crate) debug_data: Arc<DebugData>, pub(crate) debug_data: Arc<DebugData>,
pub last_gc: crate::wasm_shims::Instant, pub last_gc: crate::wasm_shims::Instant,
pub last_gc_check: crate::wasm_shims::Instant, pub last_gc_check: crate::wasm_shims::Instant,
@ -82,17 +80,16 @@ impl salsa::Database for RootDatabase {
impl Default for RootDatabase { impl Default for RootDatabase {
fn default() -> RootDatabase { fn default() -> RootDatabase {
RootDatabase::new(None, FeatureFlags::default()) RootDatabase::new(None)
} }
} }
impl RootDatabase { impl RootDatabase {
pub fn new(lru_capacity: Option<usize>, feature_flags: FeatureFlags) -> RootDatabase { pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
let mut db = RootDatabase { let mut db = RootDatabase {
runtime: salsa::Runtime::default(), runtime: salsa::Runtime::default(),
last_gc: crate::wasm_shims::Instant::now(), last_gc: crate::wasm_shims::Instant::now(),
last_gc_check: crate::wasm_shims::Instant::now(), last_gc_check: crate::wasm_shims::Instant::now(),
feature_flags: Arc::new(feature_flags),
debug_data: Default::default(), debug_data: Default::default(),
}; };
db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
@ -112,7 +109,6 @@ impl salsa::ParallelDatabase for RootDatabase {
runtime: self.runtime.snapshot(self), runtime: self.runtime.snapshot(self),
last_gc: self.last_gc, last_gc: self.last_gc,
last_gc_check: self.last_gc_check, last_gc_check: self.last_gc_check,
feature_flags: Arc::clone(&self.feature_flags),
debug_data: Arc::clone(&self.debug_data), debug_data: Arc::clone(&self.debug_data),
}) })
} }

View file

@ -12,7 +12,7 @@ use ra_db::{
salsa::{Database, Durability}, salsa::{Database, Durability},
FileId, SourceDatabaseExt, FileId, SourceDatabaseExt,
}; };
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CompletionOptions, FilePosition, LineCol};
use crate::cli::{load_cargo::load_cargo, Verbosity}; use crate::cli::{load_cargo::load_cargo, Verbosity};
@ -94,17 +94,19 @@ pub fn analysis_bench(verbosity: Verbosity, path: &Path, what: BenchWhat) -> Res
.analysis() .analysis()
.file_line_index(file_id)? .file_line_index(file_id)?
.offset(LineCol { line: pos.line - 1, col_utf16: pos.column }); .offset(LineCol { line: pos.line - 1, col_utf16: pos.column });
let file_postion = FilePosition { file_id, offset }; let file_position = FilePosition { file_id, offset };
if is_completion { if is_completion {
let res = let options = CompletionOptions::default();
do_work(&mut host, file_id, |analysis| analysis.completions(file_postion)); let res = do_work(&mut host, file_id, |analysis| {
analysis.completions(file_position, &options)
});
if verbosity.is_verbose() { if verbosity.is_verbose() {
println!("\n{:#?}", res); println!("\n{:#?}", res);
} }
} else { } else {
let res = let res =
do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_postion)); do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_position));
if verbosity.is_verbose() { if verbosity.is_verbose() {
println!("\n{:#?}", res); println!("\n{:#?}", res);
} }

View file

@ -6,7 +6,7 @@ use std::path::Path;
use anyhow::Result; use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver}; use crossbeam_channel::{unbounded, Receiver};
use ra_db::{CrateGraph, FileId, SourceRootId}; use ra_db::{CrateGraph, FileId, SourceRootId};
use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags}; use ra_ide::{AnalysisChange, AnalysisHost};
use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -82,7 +82,7 @@ pub(crate) fn load(
receiver: Receiver<VfsTask>, receiver: Receiver<VfsTask>,
) -> AnalysisHost { ) -> AnalysisHost {
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default()); let mut host = AnalysisHost::new(lru_cap);
let mut analysis_change = AnalysisChange::new(); let mut analysis_change = AnalysisChange::new();
analysis_change.set_crate_graph(crate_graph); analysis_change.set_crate_graph(crate_graph);

View file

@ -2,6 +2,10 @@
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
// FIXME: looks like a much better design is to pass options to each call,
// rather than to have a global ambient feature flags -- that way, the clients
// can issue two successive calls with different options.
/// Feature flags hold fine-grained toggles for all *user-visible* features of /// Feature flags hold fine-grained toggles for all *user-visible* features of
/// rust-analyzer. /// rust-analyzer.
/// ///

View file

@ -37,6 +37,7 @@ mod config;
mod world; mod world;
mod diagnostics; mod diagnostics;
mod semantic_tokens; mod semantic_tokens;
mod feature_flags;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;

View file

@ -18,7 +18,7 @@ use crossbeam_channel::{select, unbounded, RecvError, Sender};
use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
use lsp_types::{ClientCapabilities, NumberOrString}; use lsp_types::{ClientCapabilities, NumberOrString};
use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckTask}; use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckTask};
use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; use ra_ide::{Canceled, FileId, LibraryData, SourceRootId};
use ra_prof::profile; use ra_prof::profile;
use ra_vfs::{VfsFile, VfsTask, Watch}; use ra_vfs::{VfsFile, VfsTask, Watch};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
@ -28,6 +28,7 @@ use threadpool::ThreadPool;
use crate::{ use crate::{
diagnostics::DiagnosticTask, diagnostics::DiagnosticTask,
feature_flags::FeatureFlags,
main_loop::{ main_loop::{
pending_requests::{PendingRequest, PendingRequests}, pending_requests::{PendingRequest, PendingRequests},
subscriptions::Subscriptions, subscriptions::Subscriptions,
@ -423,7 +424,7 @@ fn loop_turn(
{ {
loop_state.workspace_loaded = true; loop_state.workspace_loaded = true;
let n_packages: usize = world_state.workspaces.iter().map(|it| it.n_packages()).sum(); let n_packages: usize = world_state.workspaces.iter().map(|it| it.n_packages()).sum();
if world_state.feature_flags().get("notifications.workspace-loaded") { if world_state.feature_flags.get("notifications.workspace-loaded") {
let msg = format!("workspace loaded, {} rust packages", n_packages); let msg = format!("workspace loaded, {} rust packages", n_packages);
show_message(req::MessageType::Info, msg, &connection.sender); show_message(req::MessageType::Info, msg, &connection.sender);
} }
@ -839,7 +840,7 @@ fn update_file_notifications_on_threadpool(
subscriptions: Vec<FileId>, subscriptions: Vec<FileId>,
) { ) {
log::trace!("updating notifications for {:?}", subscriptions); log::trace!("updating notifications for {:?}", subscriptions);
let publish_diagnostics = world.feature_flags().get("lsp.diagnostics"); let publish_diagnostics = world.feature_flags.get("lsp.diagnostics");
pool.execute(move || { pool.execute(move || {
for file_id in subscriptions { for file_id in subscriptions {
if publish_diagnostics { if publish_diagnostics {

View file

@ -20,8 +20,8 @@ use lsp_types::{
TextEdit, WorkspaceEdit, TextEdit, WorkspaceEdit,
}; };
use ra_ide::{ use ra_ide::{
Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, Assist, AssistId, CompletionOptions, FileId, FilePosition, FileRange, Query, RangeInfo,
SearchScope, Runnable, RunnableKind, SearchScope,
}; };
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit};
@ -424,7 +424,15 @@ pub fn handle_completion(
return Ok(None); return Ok(None);
} }
let items = match world.analysis().completions(position)? { let options = CompletionOptions {
enable_postfix_completions: world.feature_flags.get("completion.enable-postfix"),
add_call_parenthesis: world.feature_flags.get("completion.insertion.add-call-parenthesis"),
add_call_argument_snippets: world
.feature_flags
.get("completion.insertion.add-argument-snippets"),
};
let items = match world.analysis().completions(position, &options)? {
None => return Ok(None), None => return Ok(None),
Some(items) => items, Some(items) => items,
}; };
@ -461,7 +469,7 @@ pub fn handle_signature_help(
let _p = profile("handle_signature_help"); let _p = profile("handle_signature_help");
let position = params.try_conv_with(&world)?; let position = params.try_conv_with(&world)?;
if let Some(call_info) = world.analysis().call_info(position)? { if let Some(call_info) = world.analysis().call_info(position)? {
let concise = !world.analysis().feature_flags().get("call-info.full"); let concise = !world.feature_flags.get("call-info.full");
let mut active_parameter = call_info.active_parameter.map(|it| it as i64); let mut active_parameter = call_info.active_parameter.map(|it| it as i64);
if concise && call_info.signature.has_self_param { if concise && call_info.signature.has_self_param {
active_parameter = active_parameter.map(|it| it.saturating_sub(1)); active_parameter = active_parameter.map(|it| it.saturating_sub(1));

View file

@ -13,8 +13,7 @@ use lsp_types::Url;
use parking_lot::RwLock; use parking_lot::RwLock;
use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckWatcher}; use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckWatcher};
use ra_ide::{ use ra_ide::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData, Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
SourceRootId,
}; };
use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace};
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
@ -22,6 +21,7 @@ use relative_path::RelativePathBuf;
use crate::{ use crate::{
diagnostics::{CheckFixes, DiagnosticCollection}, diagnostics::{CheckFixes, DiagnosticCollection},
feature_flags::FeatureFlags,
main_loop::pending_requests::{CompletedRequest, LatestRequests}, main_loop::pending_requests::{CompletedRequest, LatestRequests},
vfs_glob::{Glob, RustPackageFilterBuilder}, vfs_glob::{Glob, RustPackageFilterBuilder},
LspError, Result, LspError, Result,
@ -45,6 +45,7 @@ pub struct Options {
#[derive(Debug)] #[derive(Debug)]
pub struct WorldState { pub struct WorldState {
pub options: Options, pub options: Options,
pub feature_flags: Arc<FeatureFlags>,
//FIXME: this belongs to `LoopState` rather than to `WorldState` //FIXME: this belongs to `LoopState` rather than to `WorldState`
pub roots_to_scan: usize, pub roots_to_scan: usize,
pub roots: Vec<PathBuf>, pub roots: Vec<PathBuf>,
@ -60,6 +61,7 @@ pub struct WorldState {
/// An immutable snapshot of the world's state at a point in time. /// An immutable snapshot of the world's state at a point in time.
pub struct WorldSnapshot { pub struct WorldSnapshot {
pub options: Options, pub options: Options,
pub feature_flags: Arc<FeatureFlags>,
pub workspaces: Arc<Vec<ProjectWorkspace>>, pub workspaces: Arc<Vec<ProjectWorkspace>>,
pub analysis: Analysis, pub analysis: Analysis,
pub latest_requests: Arc<RwLock<LatestRequests>>, pub latest_requests: Arc<RwLock<LatestRequests>>,
@ -146,10 +148,11 @@ impl WorldState {
CheckWatcher::dummy() CheckWatcher::dummy()
}); });
let mut analysis_host = AnalysisHost::new(lru_capacity, feature_flags); let mut analysis_host = AnalysisHost::new(lru_capacity);
analysis_host.apply_change(change); analysis_host.apply_change(change);
WorldState { WorldState {
options, options,
feature_flags: Arc::new(feature_flags),
roots_to_scan, roots_to_scan,
roots: folder_roots, roots: folder_roots,
workspaces: Arc::new(workspaces), workspaces: Arc::new(workspaces),
@ -216,6 +219,7 @@ impl WorldState {
pub fn snapshot(&self) -> WorldSnapshot { pub fn snapshot(&self) -> WorldSnapshot {
WorldSnapshot { WorldSnapshot {
options: self.options.clone(), options: self.options.clone(),
feature_flags: Arc::clone(&self.feature_flags),
workspaces: Arc::clone(&self.workspaces), workspaces: Arc::clone(&self.workspaces),
analysis: self.analysis_host.analysis(), analysis: self.analysis_host.analysis(),
vfs: Arc::clone(&self.vfs), vfs: Arc::clone(&self.vfs),
@ -235,10 +239,6 @@ impl WorldState {
pub fn complete_request(&mut self, request: CompletedRequest) { pub fn complete_request(&mut self, request: CompletedRequest) {
self.latest_requests.write().record(request) self.latest_requests.write().record(request)
} }
pub fn feature_flags(&self) -> &FeatureFlags {
self.analysis_host.feature_flags()
}
} }
impl WorldSnapshot { impl WorldSnapshot {
@ -306,8 +306,4 @@ impl WorldSnapshot {
let path = self.vfs.read().file2path(VfsFile(file_id.0)); let path = self.vfs.read().file2path(VfsFile(file_id.0));
self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path))
} }
pub fn feature_flags(&self) -> &FeatureFlags {
self.analysis.feature_flags()
}
} }