aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs4
-rw-r--r--crates/ra_hir_ty/src/tests.rs32
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs37
-rw-r--r--editors/code/src/client.ts2
-rw-r--r--editors/code/src/ctx.ts2
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.
32pub(crate) struct CfgExpander { 32pub(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]
394fn 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]
394fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() { 426fn 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 {
69pub struct ClientCapsConfig { 69pub 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
74impl Default for Config { 75impl 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};
21use ra_ide::{ 21use 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
264fn 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
254pub fn handle_workspace_symbol( 283pub fn handle_workspace_symbol(
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index f702829cd..cffdcf11a 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -4,7 +4,7 @@ import * as vscode from 'vscode';
4import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; 4import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed';
5import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; 5import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed';
6 6
7export async function createClient(serverPath: string, cwd: string): Promise<lc.LanguageClient> { 7export 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();