implement feature flags

This commit is contained in:
Aleksey Kladov 2019-08-22 14:44:16 +03:00
parent 4dd5afb7fe
commit 69bbe79c50
11 changed files with 150 additions and 36 deletions

View file

@ -1,3 +1,5 @@
use rustc_hash::FxHashMap;
use serde::{Deserialize, Deserializer};
/// Client provided initialization options
@ -12,12 +14,6 @@ pub struct ServerConfig {
#[serde(deserialize_with = "nullable_bool_false")]
pub publish_decorations: bool,
/// Whether or not the workspace loaded notification should be sent
///
/// Defaults to `true`
#[serde(deserialize_with = "nullable_bool_true")]
pub show_workspace_loaded: bool,
pub exclude_globs: Vec<String>,
pub lru_capacity: Option<usize>,
@ -25,16 +21,19 @@ pub struct ServerConfig {
/// For internal usage to make integrated tests faster.
#[serde(deserialize_with = "nullable_bool_true")]
pub with_sysroot: bool,
/// Fine grained feature flags to disable specific features.
pub feature_flags: FxHashMap<String, bool>,
}
impl Default for ServerConfig {
fn default() -> ServerConfig {
ServerConfig {
publish_decorations: false,
show_workspace_loaded: true,
exclude_globs: Vec::new(),
lru_capacity: None,
with_sysroot: true,
feature_flags: FxHashMap::default(),
}
}
}

View file

@ -9,7 +9,7 @@ use gen_lsp_server::{
handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse,
};
use lsp_types::{ClientCapabilities, NumberOrString};
use ra_ide_api::{Canceled, FileId, LibraryData};
use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData};
use ra_prof::profile;
use ra_vfs::VfsTask;
use serde::{de::DeserializeOwned, Serialize};
@ -56,7 +56,7 @@ pub fn main_loop(
msg_receiver: &Receiver<RawMessage>,
msg_sender: &Sender<RawMessage>,
) -> Result<()> {
log::debug!("server_config: {:?}", config);
log::info!("server_config: {:#?}", config);
// FIXME: support dynamic workspace loading.
let workspaces = {
let ws_worker = workspace_loader(config.with_sysroot);
@ -83,6 +83,21 @@ pub fn main_loop(
.iter()
.map(|glob| ra_vfs_glob::Glob::new(glob))
.collect::<std::result::Result<Vec<_>, _>>()?;
let feature_flags = {
let mut ff = FeatureFlags::default();
for (flag, value) in config.feature_flags {
if let Err(_) = ff.set(flag.as_str(), value) {
log::error!("unknown feature flag: {:?}", flag);
show_message(
req::MessageType::Error,
format!("unknown feature flag: {:?}", flag),
msg_sender,
);
}
}
ff
};
log::info!("feature_flags: {:#?}", feature_flags);
let mut state = WorldState::new(
ws_roots,
workspaces,
@ -90,13 +105,13 @@ pub fn main_loop(
&globs,
Options {
publish_decorations: config.publish_decorations,
show_workspace_loaded: config.show_workspace_loaded,
supports_location_link: client_caps
.text_document
.and_then(|it| it.definition)
.and_then(|it| it.link_support)
.unwrap_or(false),
},
feature_flags,
);
let pool = ThreadPool::new(THREADPOOL_SIZE);
@ -276,7 +291,7 @@ fn main_loop_inner(
&& in_flight_libraries == 0
{
let n_packages: usize = state.workspaces.iter().map(|it| it.n_packages()).sum();
if state.options.show_workspace_loaded {
if state.feature_flags().get("notifications.workspace-loaded") {
let msg = format!("workspace loaded, {} rust packages", n_packages);
show_message(req::MessageType::Info, msg, msg_sender);
}
@ -587,17 +602,20 @@ fn update_file_notifications_on_threadpool(
subscriptions: Vec<FileId>,
) {
log::trace!("updating notifications for {:?}", subscriptions);
let publish_diagnostics = world.feature_flags().get("lsp.diagnostics");
pool.execute(move || {
for file_id in subscriptions {
match handlers::publish_diagnostics(&world, file_id) {
Err(e) => {
if !is_canceled(&e) {
log::error!("failed to compute diagnostics: {:?}", e);
if publish_diagnostics {
match handlers::publish_diagnostics(&world, file_id) {
Err(e) => {
if !is_canceled(&e) {
log::error!("failed to compute diagnostics: {:?}", e);
}
}
Ok(params) => {
let not = RawNotification::new::<req::PublishDiagnostics>(&params);
sender.send(Task::Notify(not)).unwrap();
}
}
Ok(params) => {
let not = RawNotification::new::<req::PublishDiagnostics>(&params);
sender.send(Task::Notify(not)).unwrap();
}
}
if publish_decorations {

View file

@ -7,7 +7,8 @@ use gen_lsp_server::ErrorCode;
use lsp_types::Url;
use parking_lot::RwLock;
use ra_ide_api::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
SourceRootId,
};
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot};
use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
@ -22,7 +23,6 @@ use crate::{
#[derive(Debug, Clone)]
pub struct Options {
pub publish_decorations: bool,
pub show_workspace_loaded: bool,
pub supports_location_link: bool,
}
@ -58,6 +58,7 @@ impl WorldState {
lru_capacity: Option<usize>,
exclude_globs: &[Glob],
options: Options,
feature_flags: FeatureFlags,
) -> WorldState {
let mut change = AnalysisChange::new();
@ -99,7 +100,7 @@ impl WorldState {
}
change.set_crate_graph(crate_graph);
let mut analysis_host = AnalysisHost::new(lru_capacity);
let mut analysis_host = AnalysisHost::new(lru_capacity, feature_flags);
analysis_host.apply_change(change);
WorldState {
options,
@ -184,6 +185,10 @@ impl WorldState {
pub fn complete_request(&mut self, request: CompletedRequest) {
self.latest_requests.write().record(request)
}
pub fn feature_flags(&self) -> &FeatureFlags {
self.analysis_host.feature_flags()
}
}
impl WorldSnapshot {
@ -246,4 +251,8 @@ impl WorldSnapshot {
let path = self.vfs.read().file2path(VfsFile(file_id.0));
self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path))
}
pub fn feature_flags(&self) -> &FeatureFlags {
self.analysis.feature_flags()
}
}