aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_batch/src/lib.rs2
-rw-r--r--crates/ra_lsp_server/src/config.rs5
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs1
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs31
-rw-r--r--crates/ra_project_model/src/lib.rs14
-rw-r--r--editors/code/package.json15
-rw-r--r--editors/code/src/config.ts70
-rw-r--r--editors/code/src/server.ts1
8 files changed, 118 insertions, 21 deletions
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index 2c9645c00..7744ba85a 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
22 22
23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { 23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
24 let root = std::env::current_dir()?.join(root); 24 let root = std::env::current_dir()?.join(root);
25 let ws = ProjectWorkspace::discover(root.as_ref())?; 25 let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
26 let project_roots = ws.to_roots(); 26 let project_roots = ws.to_roots();
27 let (sender, receiver) = unbounded(); 27 let (sender, receiver) = unbounded();
28 let sender = Box::new(move |t| sender.send(t).unwrap()); 28 let sender = Box::new(move |t| sender.send(t).unwrap());
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs
index 8045f3d60..67942aa41 100644
--- a/crates/ra_lsp_server/src/config.rs
+++ b/crates/ra_lsp_server/src/config.rs
@@ -9,6 +9,7 @@
9 9
10use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
11 11
12use ra_project_model::CargoFeatures;
12use serde::{Deserialize, Deserializer}; 13use serde::{Deserialize, Deserializer};
13 14
14/// Client provided initialization options 15/// Client provided initialization options
@@ -37,6 +38,9 @@ pub struct ServerConfig {
37 38
38 /// Fine grained feature flags to disable specific features. 39 /// Fine grained feature flags to disable specific features.
39 pub feature_flags: FxHashMap<String, bool>, 40 pub feature_flags: FxHashMap<String, bool>,
41
42 /// Cargo feature configurations.
43 pub cargo_features: CargoFeatures,
40} 44}
41 45
42impl Default for ServerConfig { 46impl Default for ServerConfig {
@@ -49,6 +53,7 @@ impl Default for ServerConfig {
49 max_inlay_hint_length: None, 53 max_inlay_hint_length: None,
50 with_sysroot: true, 54 with_sysroot: true,
51 feature_flags: FxHashMap::default(), 55 feature_flags: FxHashMap::default(),
56 cargo_features: Default::default(),
52 } 57 }
53 } 58 }
54} 59}
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 158cac0be..965e7c53c 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -67,6 +67,7 @@ pub fn main_loop(
67 let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( 67 let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
68 ws_root.as_path(), 68 ws_root.as_path(),
69 config.with_sysroot, 69 config.with_sysroot,
70 &config.cargo_features,
70 ); 71 );
71 match workspace { 72 match workspace {
72 Ok(workspace) => loaded_workspaces.push(workspace), 73 Ok(workspace) => loaded_workspaces.push(workspace),
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 351997dcd..4a0437da3 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -6,6 +6,7 @@ use cargo_metadata::{CargoOpt, MetadataCommand};
6use ra_arena::{impl_arena_id, Arena, RawId}; 6use ra_arena::{impl_arena_id, Arena, RawId};
7use ra_db::Edition; 7use ra_db::Edition;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use serde::Deserialize;
9 10
10use crate::Result; 11use crate::Result;
11 12
@@ -23,6 +24,20 @@ pub struct CargoWorkspace {
23 pub(crate) workspace_root: PathBuf, 24 pub(crate) workspace_root: PathBuf,
24} 25}
25 26
27#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
28#[serde(rename_all = "camelCase", default)]
29pub struct CargoFeatures {
30 /// Do not activate the `default` feature.
31 pub no_default_features: bool,
32
33 /// Activate all available features
34 pub all_features: bool,
35
36 /// List of features to activate.
37 /// This will be ignored if `cargo_all_features` is true.
38 pub features: Vec<String>,
39}
40
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 41#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27pub struct Package(RawId); 42pub struct Package(RawId);
28impl_arena_id!(Package); 43impl_arena_id!(Package);
@@ -132,9 +147,21 @@ impl Target {
132} 147}
133 148
134impl CargoWorkspace { 149impl CargoWorkspace {
135 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { 150 pub fn from_cargo_metadata(
151 cargo_toml: &Path,
152 cargo_features: &CargoFeatures,
153 ) -> Result<CargoWorkspace> {
136 let mut meta = MetadataCommand::new(); 154 let mut meta = MetadataCommand::new();
137 meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures); 155 meta.manifest_path(cargo_toml);
156 if cargo_features.all_features {
157 meta.features(CargoOpt::AllFeatures);
158 } else if cargo_features.no_default_features {
159 // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
160 // https://github.com/oli-obk/cargo_metadata/issues/79
161 meta.features(CargoOpt::NoDefaultFeatures);
162 } else {
163 meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone()));
164 }
138 if let Some(parent) = cargo_toml.parent() { 165 if let Some(parent) = cargo_toml.parent() {
139 meta.current_dir(parent); 166 meta.current_dir(parent);
140 } 167 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 55ff4d6ef..d71b7031a 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -18,7 +18,7 @@ use rustc_hash::FxHashMap;
18use serde_json::from_reader; 18use serde_json::from_reader;
19 19
20pub use crate::{ 20pub use crate::{
21 cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, 21 cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind},
22 json_project::JsonProject, 22 json_project::JsonProject,
23 sysroot::Sysroot, 23 sysroot::Sysroot,
24}; 24};
@@ -60,11 +60,15 @@ impl PackageRoot {
60} 60}
61 61
62impl ProjectWorkspace { 62impl ProjectWorkspace {
63 pub fn discover(path: &Path) -> Result<ProjectWorkspace> { 63 pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> {
64 ProjectWorkspace::discover_with_sysroot(path, true) 64 ProjectWorkspace::discover_with_sysroot(path, true, cargo_features)
65 } 65 }
66 66
67 pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result<ProjectWorkspace> { 67 pub fn discover_with_sysroot(
68 path: &Path,
69 with_sysroot: bool,
70 cargo_features: &CargoFeatures,
71 ) -> Result<ProjectWorkspace> {
68 match find_rust_project_json(path) { 72 match find_rust_project_json(path) {
69 Some(json_path) => { 73 Some(json_path) => {
70 let file = File::open(json_path)?; 74 let file = File::open(json_path)?;
@@ -73,7 +77,7 @@ impl ProjectWorkspace {
73 } 77 }
74 None => { 78 None => {
75 let cargo_toml = find_cargo_toml(path)?; 79 let cargo_toml = find_cargo_toml(path)?;
76 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; 80 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?;
77 let sysroot = 81 let sysroot =
78 if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() }; 82 if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() };
79 Ok(ProjectWorkspace::Cargo { cargo, sysroot }) 83 Ok(ProjectWorkspace::Cargo { cargo, sysroot })
diff --git a/editors/code/package.json b/editors/code/package.json
index 7bc08ec31..8ed95fda7 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -278,6 +278,21 @@
278 "type": "number", 278 "type": "number",
279 "default": 20, 279 "default": 20,
280 "description": "Maximum length for inlay hints" 280 "description": "Maximum length for inlay hints"
281 },
282 "rust-analyzer.cargoFeatures.noDefaultFeatures": {
283 "type": "boolean",
284 "default": false,
285 "description": "Do not activate the `default` feature"
286 },
287 "rust-analyzer.cargoFeatures.allFeatures": {
288 "type": "boolean",
289 "default": false,
290 "description": "Activate all available features"
291 },
292 "rust-analyzer.cargoFeatures.features": {
293 "type": "array",
294 "default": [],
295 "description": "List of features to activate"
281 } 296 }
282 } 297 }
283 }, 298 },
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 2d3b6a54e..6d709f7a8 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -15,6 +15,12 @@ export interface CargoWatchOptions {
15 ignore: string[]; 15 ignore: string[];
16} 16}
17 17
18export interface CargoFeatures {
19 noDefaultFeatures: boolean;
20 allFeatures: boolean;
21 features: string[];
22}
23
18export class Config { 24export class Config {
19 public highlightingOn = true; 25 public highlightingOn = true;
20 public rainbowHighlightingOn = false; 26 public rainbowHighlightingOn = false;
@@ -35,8 +41,14 @@ export class Config {
35 command: '', 41 command: '',
36 ignore: [], 42 ignore: [],
37 }; 43 };
44 public cargoFeatures: CargoFeatures = {
45 noDefaultFeatures: false,
46 allFeatures: false,
47 features: [],
48 };
38 49
39 private prevEnhancedTyping: null | boolean = null; 50 private prevEnhancedTyping: null | boolean = null;
51 private prevCargoFeatures: null | CargoFeatures = null;
40 52
41 constructor() { 53 constructor() {
42 vscode.workspace.onDidChangeConfiguration(_ => 54 vscode.workspace.onDidChangeConfiguration(_ =>
@@ -47,6 +59,8 @@ export class Config {
47 59
48 public userConfigChanged() { 60 public userConfigChanged() {
49 const config = vscode.workspace.getConfiguration('rust-analyzer'); 61 const config = vscode.workspace.getConfiguration('rust-analyzer');
62 let requireReloadMessage = null;
63
50 if (config.has('highlightingOn')) { 64 if (config.has('highlightingOn')) {
51 this.highlightingOn = config.get('highlightingOn') as boolean; 65 this.highlightingOn = config.get('highlightingOn') as boolean;
52 } 66 }
@@ -74,19 +88,7 @@ export class Config {
74 } 88 }
75 89
76 if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { 90 if (this.prevEnhancedTyping !== this.enableEnhancedTyping) {
77 const reloadAction = 'Reload now'; 91 requireReloadMessage = 'Changing enhanced typing setting requires a reload';
78 vscode.window
79 .showInformationMessage(
80 'Changing enhanced typing setting requires a reload',
81 reloadAction,
82 )
83 .then(selectedAction => {
84 if (selectedAction === reloadAction) {
85 vscode.commands.executeCommand(
86 'workbench.action.reloadWindow',
87 );
88 }
89 });
90 this.prevEnhancedTyping = this.enableEnhancedTyping; 92 this.prevEnhancedTyping = this.enableEnhancedTyping;
91 } 93 }
92 94
@@ -153,5 +155,47 @@ export class Config {
153 if (config.has('withSysroot')) { 155 if (config.has('withSysroot')) {
154 this.withSysroot = config.get('withSysroot') || false; 156 this.withSysroot = config.get('withSysroot') || false;
155 } 157 }
158
159 if (config.has('cargoFeatures.noDefaultFeatures')) {
160 this.cargoFeatures.noDefaultFeatures = config.get(
161 'cargoFeatures.noDefaultFeatures',
162 false,
163 );
164 }
165 if (config.has('cargoFeatures.allFeatures')) {
166 this.cargoFeatures.allFeatures = config.get(
167 'cargoFeatures.allFeatures',
168 false,
169 );
170 }
171 if (config.has('cargoFeatures.features')) {
172 this.cargoFeatures.features = config.get(
173 'cargoFeatures.features',
174 [],
175 );
176 }
177
178 if (this.prevCargoFeatures !== null && (
179 this.cargoFeatures.allFeatures !== this.prevCargoFeatures.allFeatures ||
180 this.cargoFeatures.noDefaultFeatures !== this.prevCargoFeatures.noDefaultFeatures ||
181 this.cargoFeatures.features.length !== this.prevCargoFeatures.features.length ||
182 this.cargoFeatures.features.some((v, i) => v !== this.prevCargoFeatures!.features[i])
183 )) {
184 requireReloadMessage = 'Changing cargo features requires a reload';
185 }
186 this.prevCargoFeatures = { ...this.cargoFeatures };
187
188 if (requireReloadMessage !== null) {
189 const reloadAction = 'Reload now';
190 vscode.window
191 .showInformationMessage(requireReloadMessage, reloadAction)
192 .then(selectedAction => {
193 if (selectedAction === reloadAction) {
194 vscode.commands.executeCommand(
195 'workbench.action.reloadWindow',
196 );
197 }
198 });
199 }
156 } 200 }
157} 201}
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts
index 2fe45f1ed..5ace1d0fa 100644
--- a/editors/code/src/server.ts
+++ b/editors/code/src/server.ts
@@ -59,6 +59,7 @@ export class Server {
59 useClientWatching: Server.config.useClientWatching, 59 useClientWatching: Server.config.useClientWatching,
60 featureFlags: Server.config.featureFlags, 60 featureFlags: Server.config.featureFlags,
61 withSysroot: Server.config.withSysroot, 61 withSysroot: Server.config.withSysroot,
62 cargoFeatures: Server.config.cargoFeatures,
62 }, 63 },
63 traceOutputChannel, 64 traceOutputChannel,
64 }; 65 };