diff options
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 32 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 37 | ||||
-rw-r--r-- | editors/code/src/client.ts | 2 | ||||
-rw-r--r-- | editors/code/src/ctx.ts | 2 |
7 files changed, 78 insertions, 7 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 3b169440a..890cefcaf 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -27,7 +27,7 @@ use crate::{ | |||
27 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 27 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | /// A subser of Exander that only deals with cfg attributes. We only need it to | 30 | /// A subset of Exander that only deals with cfg attributes. We only need it to |
31 | /// avoid cyclic queries in crate def map during enum processing. | 31 | /// avoid cyclic queries in crate def map during enum processing. |
32 | pub(crate) struct CfgExpander { | 32 | pub(crate) struct CfgExpander { |
33 | cfg_options: CfgOptions, | 33 | cfg_options: CfgOptions, |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 0caedd8d8..571603854 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -141,6 +141,10 @@ impl ExprCollector<'_> { | |||
141 | 141 | ||
142 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 142 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
143 | let syntax_ptr = AstPtr::new(&expr); | 143 | let syntax_ptr = AstPtr::new(&expr); |
144 | let attrs = self.expander.parse_attrs(&expr); | ||
145 | if !self.expander.is_cfg_enabled(&attrs) { | ||
146 | return self.missing_expr(); | ||
147 | } | ||
144 | match expr { | 148 | match expr { |
145 | ast::Expr::IfExpr(e) => { | 149 | ast::Expr::IfExpr(e) => { |
146 | let then_branch = self.collect_block_opt(e.then_branch()); | 150 | let then_branch = self.collect_block_opt(e.then_branch()); |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index b6a96bb5c..588d81282 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -391,6 +391,38 @@ fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { | |||
391 | } | 391 | } |
392 | 392 | ||
393 | #[test] | 393 | #[test] |
394 | fn no_such_field_with_feature_flag_diagnostics_on_block_expr() { | ||
395 | let diagnostics = TestDB::with_files( | ||
396 | r#" | ||
397 | //- /lib.rs crate:foo cfg:feature=foo | ||
398 | struct S { | ||
399 | #[cfg(feature = "foo")] | ||
400 | foo: u32, | ||
401 | #[cfg(not(feature = "foo"))] | ||
402 | bar: u32, | ||
403 | } | ||
404 | |||
405 | impl S { | ||
406 | fn new(bar: u32) -> Self { | ||
407 | #[cfg(feature = "foo")] | ||
408 | { | ||
409 | Self { foo: bar } | ||
410 | } | ||
411 | #[cfg(not(feature = "foo"))] | ||
412 | { | ||
413 | Self { bar } | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | "#, | ||
418 | ) | ||
419 | .diagnostics() | ||
420 | .0; | ||
421 | |||
422 | assert_snapshot!(diagnostics, @r###""###); | ||
423 | } | ||
424 | |||
425 | #[test] | ||
394 | fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() { | 426 | fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() { |
395 | let diagnostics = TestDB::with_files( | 427 | let diagnostics = TestDB::with_files( |
396 | r#" | 428 | r#" |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 715eddadb..74a63e32a 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -69,6 +69,7 @@ pub enum RustfmtConfig { | |||
69 | pub struct ClientCapsConfig { | 69 | pub struct ClientCapsConfig { |
70 | pub location_link: bool, | 70 | pub location_link: bool, |
71 | pub line_folding_only: bool, | 71 | pub line_folding_only: bool, |
72 | pub hierarchical_symbols: bool, | ||
72 | } | 73 | } |
73 | 74 | ||
74 | impl Default for Config { | 75 | impl Default for Config { |
@@ -215,6 +216,11 @@ impl Config { | |||
215 | if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { | 216 | if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { |
216 | self.client_caps.line_folding_only = value | 217 | self.client_caps.line_folding_only = value |
217 | } | 218 | } |
219 | if let Some(value) = | ||
220 | caps.document_symbol.as_ref().and_then(|it| it.hierarchical_document_symbol_support) | ||
221 | { | ||
222 | self.client_caps.hierarchical_symbols = value | ||
223 | } | ||
218 | self.completion.allow_snippets(false); | 224 | self.completion.allow_snippets(false); |
219 | if let Some(completion) = &caps.completion { | 225 | if let Some(completion) = &caps.completion { |
220 | if let Some(completion_item) = &completion.completion_item { | 226 | if let Some(completion_item) = &completion.completion_item { |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index c2c1a23cd..e87e8db5d 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -16,7 +16,7 @@ use lsp_types::{ | |||
16 | Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, | 16 | Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, |
17 | Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, | 17 | Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, |
18 | SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, | 18 | SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, |
19 | TextEdit, WorkspaceEdit, | 19 | TextEdit, Url, WorkspaceEdit, |
20 | }; | 20 | }; |
21 | use ra_ide::{ | 21 | use ra_ide::{ |
22 | Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, | 22 | Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, |
@@ -219,6 +219,7 @@ pub fn handle_document_symbol( | |||
219 | let _p = profile("handle_document_symbol"); | 219 | let _p = profile("handle_document_symbol"); |
220 | let file_id = params.text_document.try_conv_with(&world)?; | 220 | let file_id = params.text_document.try_conv_with(&world)?; |
221 | let line_index = world.analysis().file_line_index(file_id)?; | 221 | let line_index = world.analysis().file_line_index(file_id)?; |
222 | let url = file_id.try_conv_with(&world)?; | ||
222 | 223 | ||
223 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); | 224 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); |
224 | 225 | ||
@@ -234,10 +235,10 @@ pub fn handle_document_symbol( | |||
234 | }; | 235 | }; |
235 | parents.push((doc_symbol, symbol.parent)); | 236 | parents.push((doc_symbol, symbol.parent)); |
236 | } | 237 | } |
237 | let mut res = Vec::new(); | 238 | let mut document_symbols = Vec::new(); |
238 | while let Some((node, parent)) = parents.pop() { | 239 | while let Some((node, parent)) = parents.pop() { |
239 | match parent { | 240 | match parent { |
240 | None => res.push(node), | 241 | None => document_symbols.push(node), |
241 | Some(i) => { | 242 | Some(i) => { |
242 | let children = &mut parents[i].0.children; | 243 | let children = &mut parents[i].0.children; |
243 | if children.is_none() { | 244 | if children.is_none() { |
@@ -248,7 +249,35 @@ pub fn handle_document_symbol( | |||
248 | } | 249 | } |
249 | } | 250 | } |
250 | 251 | ||
251 | Ok(Some(res.into())) | 252 | if world.config.client_caps.hierarchical_symbols { |
253 | Ok(Some(document_symbols.into())) | ||
254 | } else { | ||
255 | let mut symbol_information = Vec::<SymbolInformation>::new(); | ||
256 | for symbol in document_symbols { | ||
257 | flatten_document_symbol(&symbol, None, &url, &mut symbol_information); | ||
258 | } | ||
259 | |||
260 | Ok(Some(symbol_information.into())) | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn flatten_document_symbol( | ||
265 | symbol: &DocumentSymbol, | ||
266 | container_name: Option<String>, | ||
267 | url: &Url, | ||
268 | res: &mut Vec<SymbolInformation>, | ||
269 | ) { | ||
270 | res.push(SymbolInformation { | ||
271 | name: symbol.name.clone(), | ||
272 | kind: symbol.kind, | ||
273 | deprecated: symbol.deprecated, | ||
274 | location: Location::new(url.clone(), symbol.range), | ||
275 | container_name: container_name, | ||
276 | }); | ||
277 | |||
278 | for child in symbol.children.iter().flatten() { | ||
279 | flatten_document_symbol(child, Some(symbol.name.clone()), url, res); | ||
280 | } | ||
252 | } | 281 | } |
253 | 282 | ||
254 | pub fn handle_workspace_symbol( | 283 | pub fn handle_workspace_symbol( |
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 0ad4b63ae..97e794091 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts | |||
@@ -4,7 +4,7 @@ import * as vscode from 'vscode'; | |||
4 | import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; | 4 | import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; |
5 | import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; | 5 | import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; |
6 | 6 | ||
7 | export async function createClient(serverPath: string, cwd: string): Promise<lc.LanguageClient> { | 7 | export function createClient(serverPath: string, cwd: string): lc.LanguageClient { |
8 | // '.' Is the fallback if no folder is open | 8 | // '.' Is the fallback if no folder is open |
9 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). | 9 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). |
10 | // It might be a good idea to test if the uri points to a file. | 10 | // It might be a good idea to test if the uri points to a file. |
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index f7ed62d03..41df11991 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts | |||
@@ -21,7 +21,7 @@ export class Ctx { | |||
21 | serverPath: string, | 21 | serverPath: string, |
22 | cwd: string, | 22 | cwd: string, |
23 | ): Promise<Ctx> { | 23 | ): Promise<Ctx> { |
24 | const client = await createClient(serverPath, cwd); | 24 | const client = createClient(serverPath, cwd); |
25 | const res = new Ctx(config, extCtx, client, serverPath); | 25 | const res = new Ctx(config, extCtx, client, serverPath); |
26 | res.pushCleanup(client.start()); | 26 | res.pushCleanup(client.start()); |
27 | await client.onReady(); | 27 | await client.onReady(); |