aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/paths/src/lib.rs5
-rw-r--r--crates/ra_hir_def/src/nameres.rs7
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs5
-rw-r--r--crates/ra_hir_ty/src/_match.rs77
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs23
-rw-r--r--crates/ra_ide/src/runnables.rs18
-rw-r--r--crates/ra_ide/src/snapshots/highlight_doctest.html76
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs9
-rw-r--r--crates/ra_ide/src/syntax_highlighting/injection.rs8
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs3
-rw-r--r--crates/rust-analyzer/src/global_state.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs10
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
-rw-r--r--crates/stdx/src/lib.rs1
-rw-r--r--crates/vfs/src/file_set.rs32
-rw-r--r--crates/vfs/src/lib.rs3
16 files changed, 175 insertions, 107 deletions
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index c7ce0c42f..190c50913 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -2,7 +2,7 @@
2//! relative paths. 2//! relative paths.
3use std::{ 3use std::{
4 convert::{TryFrom, TryInto}, 4 convert::{TryFrom, TryInto},
5 ops, 5 io, ops,
6 path::{Component, Path, PathBuf}, 6 path::{Component, Path, PathBuf},
7}; 7};
8 8
@@ -46,6 +46,9 @@ impl TryFrom<&str> for AbsPathBuf {
46} 46}
47 47
48impl AbsPathBuf { 48impl AbsPathBuf {
49 pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
50 path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
51 }
49 pub fn as_path(&self) -> &AbsPath { 52 pub fn as_path(&self) -> &AbsPath {
50 AbsPath::new_unchecked(self.0.as_path()) 53 AbsPath::new_unchecked(self.0.as_path())
51 } 54 }
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index b3e5f491a..b8560fdc9 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -119,13 +119,6 @@ impl Default for ModuleOrigin {
119} 119}
120 120
121impl ModuleOrigin { 121impl ModuleOrigin {
122 pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self {
123 match file {
124 None => ModuleOrigin::Inline { definition: declaration },
125 Some(definition) => ModuleOrigin::File { declaration, definition },
126 }
127 }
128
129 fn declaration(&self) -> Option<AstId<ast::Module>> { 122 fn declaration(&self) -> Option<AstId<ast::Module>> {
130 match self { 123 match self {
131 ModuleOrigin::File { declaration: module, .. } 124 ModuleOrigin::File { declaration: module, .. }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 976e5e585..77baa4c69 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -825,7 +825,10 @@ impl ModCollector<'_, '_> {
825 let modules = &mut self.def_collector.def_map.modules; 825 let modules = &mut self.def_collector.def_map.modules;
826 let res = modules.alloc(ModuleData::default()); 826 let res = modules.alloc(ModuleData::default());
827 modules[res].parent = Some(self.module_id); 827 modules[res].parent = Some(self.module_id);
828 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); 828 modules[res].origin = match definition {
829 None => ModuleOrigin::Inline { definition: declaration },
830 Some(definition) => ModuleOrigin::File { declaration, definition },
831 };
829 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { 832 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
830 modules[res].scope.define_legacy_macro(name, mac) 833 modules[res].scope.define_legacy_macro(name, mac)
831 } 834 }
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index 02a7a61f1..5495ce284 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -312,20 +312,16 @@ impl PatStack {
312 Self(v) 312 Self(v)
313 } 313 }
314 314
315 fn is_empty(&self) -> bool {
316 self.0.is_empty()
317 }
318
319 fn head(&self) -> PatIdOrWild {
320 self.0[0]
321 }
322
323 fn get_head(&self) -> Option<PatIdOrWild> { 315 fn get_head(&self) -> Option<PatIdOrWild> {
324 self.0.first().copied() 316 self.0.first().copied()
325 } 317 }
326 318
319 fn tail(&self) -> &[PatIdOrWild] {
320 self.0.get(1..).unwrap_or(&[])
321 }
322
327 fn to_tail(&self) -> PatStack { 323 fn to_tail(&self) -> PatStack {
328 Self::from_slice(&self.0[1..]) 324 Self::from_slice(self.tail())
329 } 325 }
330 326
331 fn replace_head_with<I, T>(&self, pats: I) -> PatStack 327 fn replace_head_with<I, T>(&self, pats: I) -> PatStack
@@ -347,7 +343,7 @@ impl PatStack {
347 /// 343 ///
348 /// See the module docs and the associated documentation in rustc for details. 344 /// See the module docs and the associated documentation in rustc for details.
349 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> { 345 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> {
350 if matches!(self.head().as_pat(cx), Pat::Wild) { 346 if matches!(self.get_head()?.as_pat(cx), Pat::Wild) {
351 Some(self.to_tail()) 347 Some(self.to_tail())
352 } else { 348 } else {
353 None 349 None
@@ -362,11 +358,12 @@ impl PatStack {
362 cx: &MatchCheckCtx, 358 cx: &MatchCheckCtx,
363 constructor: &Constructor, 359 constructor: &Constructor,
364 ) -> MatchCheckResult<Option<PatStack>> { 360 ) -> MatchCheckResult<Option<PatStack>> {
365 if self.is_empty() { 361 let head = match self.get_head() {
366 return Ok(None); 362 Some(head) => head,
367 } 363 None => return Ok(None),
364 };
368 365
369 let head_pat = self.head().as_pat(cx); 366 let head_pat = head.as_pat(cx);
370 let result = match (head_pat, constructor) { 367 let result = match (head_pat, constructor) {
371 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => { 368 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => {
372 if ellipsis.is_some() { 369 if ellipsis.is_some() {
@@ -394,7 +391,7 @@ impl PatStack {
394 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?), 391 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?),
395 (Pat::Path(_), Constructor::Enum(constructor)) => { 392 (Pat::Path(_), Constructor::Enum(constructor)) => {
396 // unit enum variants become `Pat::Path` 393 // unit enum variants become `Pat::Path`
397 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 394 let pat_id = head.as_id().expect("we know this isn't a wild");
398 if !enum_variant_matches(cx, pat_id, *constructor) { 395 if !enum_variant_matches(cx, pat_id, *constructor) {
399 None 396 None
400 } else { 397 } else {
@@ -405,7 +402,7 @@ impl PatStack {
405 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. }, 402 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. },
406 Constructor::Enum(enum_constructor), 403 Constructor::Enum(enum_constructor),
407 ) => { 404 ) => {
408 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 405 let pat_id = head.as_id().expect("we know this isn't a wild");
409 if !enum_variant_matches(cx, pat_id, *enum_constructor) { 406 if !enum_variant_matches(cx, pat_id, *enum_constructor) {
410 None 407 None
411 } else { 408 } else {
@@ -445,7 +442,7 @@ impl PatStack {
445 } 442 }
446 } 443 }
447 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => { 444 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => {
448 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 445 let pat_id = head.as_id().expect("we know this isn't a wild");
449 if !enum_variant_matches(cx, pat_id, *e) { 446 if !enum_variant_matches(cx, pat_id, *e) {
450 None 447 None
451 } else { 448 } else {
@@ -491,7 +488,7 @@ impl PatStack {
491 ) -> MatchCheckResult<PatStack> { 488 ) -> MatchCheckResult<PatStack> {
492 assert_eq!( 489 assert_eq!(
493 Pat::Wild, 490 Pat::Wild,
494 self.head().as_pat(cx), 491 self.get_head().expect("expand_wildcard called on empty PatStack").as_pat(cx),
495 "expand_wildcard must only be called on PatStack with wild at head", 492 "expand_wildcard must only be called on PatStack with wild at head",
496 ); 493 );
497 494
@@ -509,7 +506,6 @@ impl PatStack {
509 } 506 }
510} 507}
511 508
512#[derive(Debug)]
513/// A collection of PatStack. 509/// A collection of PatStack.
514/// 510///
515/// This type is modeled from the struct of the same name in `rustc`. 511/// This type is modeled from the struct of the same name in `rustc`.
@@ -623,13 +619,16 @@ pub(crate) fn is_useful(
623 _ => (), 619 _ => (),
624 } 620 }
625 621
626 if v.is_empty() { 622 let head = match v.get_head() {
627 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful }; 623 Some(head) => head,
624 None => {
625 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
628 626
629 return Ok(result); 627 return Ok(result);
630 } 628 }
629 };
631 630
632 if let Pat::Or(pat_ids) = v.head().as_pat(cx) { 631 if let Pat::Or(pat_ids) = head.as_pat(cx) {
633 let mut found_unimplemented = false; 632 let mut found_unimplemented = false;
634 let any_useful = pat_ids.iter().any(|&pat_id| { 633 let any_useful = pat_ids.iter().any(|&pat_id| {
635 let v = PatStack::from_pattern(pat_id); 634 let v = PatStack::from_pattern(pat_id);
@@ -653,7 +652,7 @@ pub(crate) fn is_useful(
653 }; 652 };
654 } 653 }
655 654
656 if let Some(constructor) = pat_constructor(cx, v.head())? { 655 if let Some(constructor) = pat_constructor(cx, head)? {
657 let matrix = matrix.specialize_constructor(&cx, &constructor)?; 656 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
658 let v = v 657 let v = v
659 .specialize_constructor(&cx, &constructor)? 658 .specialize_constructor(&cx, &constructor)?
@@ -854,10 +853,10 @@ mod tests {
854 } 853 }
855 854
856 pub(super) fn check_no_diagnostic(ra_fixture: &str) { 855 pub(super) fn check_no_diagnostic(ra_fixture: &str) {
857 let diagnostic_count = 856 let (s, diagnostic_count) =
858 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1; 857 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>();
859 858
860 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); 859 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s);
861 } 860 }
862 861
863 #[test] 862 #[test]
@@ -2014,6 +2013,28 @@ mod tests {
2014 ", 2013 ",
2015 ); 2014 );
2016 } 2015 }
2016
2017 #[test]
2018 fn or_pattern_panic_2() {
2019 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
2020 // so this acts as a regression test for that.
2021 check_diagnostic(
2022 r"
2023 pub enum Category {
2024 Infinity,
2025 Zero,
2026 }
2027
2028 fn panic(a: Category, b: Category) {
2029 match (a, b) {
2030 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {}
2031
2032 (Category::Infinity | Category::Zero, _) => {}
2033 }
2034 }
2035 ",
2036 );
2037 }
2017} 2038}
2018 2039
2019#[cfg(test)] 2040#[cfg(test)]
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index c7bb1e69f..0b52b01ab 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -135,8 +135,8 @@ impl NavigationTarget {
135 db: &RootDatabase, 135 db: &RootDatabase,
136 node: InFile<&dyn ast::NameOwner>, 136 node: InFile<&dyn ast::NameOwner>,
137 ) -> NavigationTarget { 137 ) -> NavigationTarget {
138 //FIXME: use `_` instead of empty string 138 let name =
139 let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); 139 node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
140 let focus_range = 140 let focus_range =
141 node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range); 141 node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range);
142 let frange = original_range(db, node.map(|it| it.syntax())); 142 let frange = original_range(db, node.map(|it| it.syntax()));
@@ -150,6 +150,25 @@ impl NavigationTarget {
150 ) 150 )
151 } 151 }
152 152
153 /// Allows `NavigationTarget` to be created from a `DocCommentsOwner` and a `NameOwner`
154 pub(crate) fn from_doc_commented(
155 db: &RootDatabase,
156 named: InFile<&dyn ast::NameOwner>,
157 node: InFile<&dyn ast::DocCommentsOwner>,
158 ) -> NavigationTarget {
159 let name =
160 named.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
161 let frange = original_range(db, node.map(|it| it.syntax()));
162
163 NavigationTarget::from_syntax(
164 frange.file_id,
165 name,
166 None,
167 frange.range,
168 node.value.syntax().kind(),
169 )
170 }
171
153 fn from_syntax( 172 fn from_syntax(
154 file_id: FileId, 173 file_id: FileId,
155 name: SmolStr, 174 name: SmolStr,
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index fc57dc33d..8105ef373 100644
--- a/crates/ra_ide/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
@@ -171,7 +171,15 @@ fn runnable_fn(
171 let cfg_exprs = 171 let cfg_exprs =
172 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); 172 attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
173 173
174 let nav = NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def)); 174 let nav = if let RunnableKind::DocTest { .. } = kind {
175 NavigationTarget::from_doc_commented(
176 sema.db,
177 InFile::new(file_id.into(), &fn_def),
178 InFile::new(file_id.into(), &fn_def),
179 )
180 } else {
181 NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def))
182 };
175 Some(Runnable { nav, kind, cfg_exprs }) 183 Some(Runnable { nav, kind, cfg_exprs })
176} 184}
177 185
@@ -419,9 +427,7 @@ mod tests {
419 full_range: 22..64, 427 full_range: 22..64,
420 name: "foo", 428 name: "foo",
421 kind: FN_DEF, 429 kind: FN_DEF,
422 focus_range: Some( 430 focus_range: None,
423 56..59,
424 ),
425 container_name: None, 431 container_name: None,
426 description: None, 432 description: None,
427 docs: None, 433 docs: None,
@@ -486,9 +492,7 @@ mod tests {
486 full_range: 51..105, 492 full_range: 51..105,
487 name: "foo", 493 name: "foo",
488 kind: FN_DEF, 494 kind: FN_DEF,
489 focus_range: Some( 495 focus_range: None,
490 97..100,
491 ),
492 container_name: None, 496 container_name: None,
493 description: None, 497 description: None,
494 docs: None, 498 docs: None,
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html
index f92a0aba5..f61c0daa5 100644
--- a/crates/ra_ide/src/snapshots/highlight_doctest.html
+++ b/crates/ra_ide/src/snapshots/highlight_doctest.html
@@ -39,48 +39,48 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
39<span class="keyword">impl</span> <span class="struct">Foo</span> { 39<span class="keyword">impl</span> <span class="struct">Foo</span> {
40 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span>: <span class="builtin_type">bool</span> = <span class="bool_literal">true</span>; 40 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span>: <span class="builtin_type">bool</span> = <span class="bool_literal">true</span>;
41 41
42 <span class="comment">/// Constructs a new `Foo`.</span> 42 <span class="comment documentation">/// Constructs a new `Foo`.</span>
43 <span class="comment">///</span> 43 <span class="comment documentation">///</span>
44 <span class="comment">/// # Examples</span> 44 <span class="comment documentation">/// # Examples</span>
45 <span class="comment">///</span> 45 <span class="comment documentation">///</span>
46 <span class="comment">/// ```</span> 46 <span class="comment documentation">/// ```</span>
47 <span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span> 47 <span class="comment documentation">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span>
48 <span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="struct">Foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); 48 <span class="comment documentation">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="struct">Foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>();
49 <span class="comment">/// ```</span> 49 <span class="comment documentation">/// ```</span>
50 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -&gt; <span class="struct">Foo</span> { 50 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -&gt; <span class="struct">Foo</span> {
51 <span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> } 51 <span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> }
52 } 52 }
53 53
54 <span class="comment">/// `bar` method on `Foo`.</span> 54 <span class="comment documentation">/// `bar` method on `Foo`.</span>
55 <span class="comment">///</span> 55 <span class="comment documentation">///</span>
56 <span class="comment">/// # Examples</span> 56 <span class="comment documentation">/// # Examples</span>
57 <span class="comment">///</span> 57 <span class="comment documentation">///</span>
58 <span class="comment">/// ```</span> 58 <span class="comment documentation">/// ```</span>
59 <span class="comment">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>; 59 <span class="comment documentation">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>;
60 <span class="comment">///</span> 60 <span class="comment documentation">///</span>
61 <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); 61 <span class="comment documentation">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>();
62 <span class="comment">///</span> 62 <span class="comment documentation">///</span>
63 <span class="comment">/// </span><span class="comment">// calls bar on foo</span> 63 <span class="comment documentation">/// </span><span class="comment">// calls bar on foo</span>
64 <span class="comment">/// </span><span class="macro">assert!</span>(foo.bar()); 64 <span class="comment documentation">/// </span><span class="macro">assert!</span>(foo.bar());
65 <span class="comment">///</span> 65 <span class="comment documentation">///</span>
66 <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">bar</span> = <span class="variable">foo</span>.<span class="field">bar</span> || <span class="struct">Foo</span>::<span class="constant">bar</span>; 66 <span class="comment documentation">/// </span><span class="keyword">let</span> <span class="variable declaration">bar</span> = <span class="variable">foo</span>.<span class="field">bar</span> || <span class="struct">Foo</span>::<span class="constant">bar</span>;
67 <span class="comment">///</span> 67 <span class="comment documentation">///</span>
68 <span class="comment">/// </span><span class="comment">/* multi-line 68 <span class="comment documentation">/// </span><span class="comment">/* multi-line
69 </span><span class="comment">/// </span><span class="comment"> comment */</span> 69 </span><span class="comment documentation">/// </span><span class="comment"> comment */</span>
70 <span class="comment">///</span> 70 <span class="comment documentation">///</span>
71 <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">multi_line_string</span> = <span class="string_literal">"Foo 71 <span class="comment documentation">/// </span><span class="keyword">let</span> <span class="variable declaration">multi_line_string</span> = <span class="string_literal">"Foo
72 </span><span class="comment">/// </span><span class="string_literal"> bar 72 </span><span class="comment documentation">/// </span><span class="string_literal"> bar
73 </span><span class="comment">/// </span><span class="string_literal"> "</span>; 73 </span><span class="comment documentation">/// </span><span class="string_literal"> "</span>;
74 <span class="comment">///</span> 74 <span class="comment documentation">///</span>
75 <span class="comment">/// ```</span> 75 <span class="comment documentation">/// ```</span>
76 <span class="comment">///</span> 76 <span class="comment documentation">///</span>
77 <span class="comment">/// ```rust,no_run</span> 77 <span class="comment documentation">/// ```rust,no_run</span>
78 <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>(); 78 <span class="comment documentation">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>();
79 <span class="comment">/// ```</span> 79 <span class="comment documentation">/// ```</span>
80 <span class="comment">///</span> 80 <span class="comment documentation">///</span>
81 <span class="comment">/// ```sh</span> 81 <span class="comment documentation">/// ```sh</span>
82 <span class="comment">/// echo 1</span> 82 <span class="comment documentation">/// echo 1</span>
83 <span class="comment">/// ```</span> 83 <span class="comment documentation">/// ```</span>
84 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">bool</span> { 84 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">bool</span> {
85 <span class="bool_literal">true</span> 85 <span class="bool_literal">true</span>
86 } 86 }
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 854b6cc6d..f8f790e59 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -489,7 +489,14 @@ fn highlight_element(
489 } 489 }
490 490
491 // Simple token-based highlighting 491 // Simple token-based highlighting
492 COMMENT => HighlightTag::Comment.into(), 492 COMMENT => {
493 let comment = element.into_token().and_then(ast::Comment::cast)?;
494 let h = HighlightTag::Comment;
495 match comment.kind().doc {
496 Some(_) => h | HighlightModifier::Documentation,
497 None => h.into(),
498 }
499 }
493 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::StringLiteral.into(), 500 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::StringLiteral.into(),
494 ATTR => HighlightTag::Attribute.into(), 501 ATTR => HighlightTag::Attribute.into(),
495 INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(), 502 INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(),
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs
index 929a5cc5c..415f24a6d 100644
--- a/crates/ra_ide/src/syntax_highlighting/injection.rs
+++ b/crates/ra_ide/src/syntax_highlighting/injection.rs
@@ -7,7 +7,10 @@ use hir::Semantics;
7use ra_syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; 7use ra_syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize};
8use stdx::SepBy; 8use stdx::SepBy;
9 9
10use crate::{call_info::ActiveParameter, Analysis, HighlightTag, HighlightedRange, RootDatabase}; 10use crate::{
11 call_info::ActiveParameter, Analysis, HighlightModifier, HighlightTag, HighlightedRange,
12 RootDatabase,
13};
11 14
12use super::HighlightedRangeStack; 15use super::HighlightedRangeStack;
13 16
@@ -118,7 +121,7 @@ pub(super) fn extract_doc_comments(
118 range.start(), 121 range.start(),
119 range.start() + TextSize::try_from(pos).unwrap(), 122 range.start() + TextSize::try_from(pos).unwrap(),
120 ), 123 ),
121 highlight: HighlightTag::Comment.into(), 124 highlight: HighlightTag::Comment | HighlightModifier::Documentation,
122 binding_hash: None, 125 binding_hash: None,
123 }); 126 });
124 line_start += range.len() - TextSize::try_from(pos).unwrap(); 127 line_start += range.len() - TextSize::try_from(pos).unwrap();
@@ -164,6 +167,7 @@ pub(super) fn highlight_doc_comment(
164 h.range.start() + start_offset, 167 h.range.start() + start_offset,
165 h.range.end() + end_offset.unwrap_or(start_offset), 168 h.range.end() + end_offset.unwrap_or(start_offset),
166 ); 169 );
170
167 stack.add(h); 171 stack.add(h);
168 } 172 }
169 } 173 }
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index 400d22fb6..93bbb4b4d 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -56,6 +56,7 @@ pub enum HighlightModifier {
56 /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is 56 /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is
57 /// not. 57 /// not.
58 Definition, 58 Definition,
59 Documentation,
59 Mutable, 60 Mutable,
60 Unsafe, 61 Unsafe,
61} 62}
@@ -108,6 +109,7 @@ impl HighlightModifier {
108 HighlightModifier::Attribute, 109 HighlightModifier::Attribute,
109 HighlightModifier::ControlFlow, 110 HighlightModifier::ControlFlow,
110 HighlightModifier::Definition, 111 HighlightModifier::Definition,
112 HighlightModifier::Documentation,
111 HighlightModifier::Mutable, 113 HighlightModifier::Mutable,
112 HighlightModifier::Unsafe, 114 HighlightModifier::Unsafe,
113 ]; 115 ];
@@ -117,6 +119,7 @@ impl HighlightModifier {
117 HighlightModifier::Attribute => "attribute", 119 HighlightModifier::Attribute => "attribute",
118 HighlightModifier::ControlFlow => "control", 120 HighlightModifier::ControlFlow => "control",
119 HighlightModifier::Definition => "declaration", 121 HighlightModifier::Definition => "declaration",
122 HighlightModifier::Documentation => "documentation",
120 HighlightModifier::Mutable => "mutable", 123 HighlightModifier::Mutable => "mutable",
121 HighlightModifier::Unsafe => "unsafe", 124 HighlightModifier::Unsafe => "unsafe",
122 } 125 }
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index ca95d776a..1527c9947 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -18,7 +18,7 @@ use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsTask, Watch};
18use stdx::format_to; 18use stdx::format_to;
19 19
20use crate::{ 20use crate::{
21 config::Config, 21 config::{Config, FilesWatcher},
22 diagnostics::{CheckFixes, DiagnosticCollection}, 22 diagnostics::{CheckFixes, DiagnosticCollection},
23 main_loop::pending_requests::{CompletedRequest, LatestRequests}, 23 main_loop::pending_requests::{CompletedRequest, LatestRequests},
24 to_proto::url_from_abs_path, 24 to_proto::url_from_abs_path,
@@ -76,7 +76,6 @@ impl GlobalState {
76 workspaces: Vec<ProjectWorkspace>, 76 workspaces: Vec<ProjectWorkspace>,
77 lru_capacity: Option<usize>, 77 lru_capacity: Option<usize>,
78 exclude_globs: &[Glob], 78 exclude_globs: &[Glob],
79 watch: Watch,
80 config: Config, 79 config: Config,
81 ) -> GlobalState { 80 ) -> GlobalState {
82 let mut change = AnalysisChange::new(); 81 let mut change = AnalysisChange::new();
@@ -111,6 +110,7 @@ impl GlobalState {
111 110
112 let (task_sender, task_receiver) = unbounded(); 111 let (task_sender, task_receiver) = unbounded();
113 let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); 112 let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
113 let watch = Watch(matches!(config.files.watcher, FilesWatcher::Notify));
114 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); 114 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
115 115
116 let mut extern_source_roots = FxHashMap::default(); 116 let mut extern_source_roots = FxHashMap::default();
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 08b0a5a16..f0aaaa21e 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -27,7 +27,7 @@ use ra_flycheck::{CheckTask, Status};
27use ra_ide::{Canceled, FileId, LineIndex}; 27use ra_ide::{Canceled, FileId, LineIndex};
28use ra_prof::profile; 28use ra_prof::profile;
29use ra_project_model::{PackageRoot, ProjectWorkspace}; 29use ra_project_model::{PackageRoot, ProjectWorkspace};
30use ra_vfs::{VfsTask, Watch}; 30use ra_vfs::VfsTask;
31use rustc_hash::FxHashSet; 31use rustc_hash::FxHashSet;
32use serde::{de::DeserializeOwned, Serialize}; 32use serde::{de::DeserializeOwned, Serialize};
33use threadpool::ThreadPool; 33use threadpool::ThreadPool;
@@ -160,13 +160,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
160 connection.sender.send(request.into()).unwrap(); 160 connection.sender.send(request.into()).unwrap();
161 } 161 }
162 162
163 GlobalState::new( 163 GlobalState::new(workspaces, config.lru_capacity, &globs, config)
164 workspaces,
165 config.lru_capacity,
166 &globs,
167 Watch(matches!(config.files.watcher, FilesWatcher::Notify)),
168 config,
169 )
170 }; 164 };
171 165
172 loop_state.roots_total = global_state.vfs.read().n_roots(); 166 loop_state.roots_total = global_state.vfs.read().n_roots();
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 055c97455..ec153097e 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -331,6 +331,7 @@ fn semantic_token_type_and_modifiers(
331 let modifier = match modifier { 331 let modifier = match modifier {
332 HighlightModifier::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER, 332 HighlightModifier::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER,
333 HighlightModifier::Definition => lsp_types::SemanticTokenModifier::DECLARATION, 333 HighlightModifier::Definition => lsp_types::SemanticTokenModifier::DECLARATION,
334 HighlightModifier::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION,
334 HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW, 335 HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW,
335 HighlightModifier::Mutable => semantic_tokens::MUTABLE, 336 HighlightModifier::Mutable => semantic_tokens::MUTABLE,
336 HighlightModifier::Unsafe => semantic_tokens::UNSAFE, 337 HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index c0356344c..f2ff0e435 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,5 +1,4 @@
1//! Missing batteries for standard libraries. 1//! Missing batteries for standard libraries.
2
3use std::{cell::Cell, fmt, time::Instant}; 2use std::{cell::Cell, fmt, time::Instant};
4 3
5#[inline(always)] 4#[inline(always)]
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 7dc721f7e..724606a3d 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -2,7 +2,7 @@
2//! 2//!
3//! Files which do not belong to any explicitly configured `FileSet` belong to 3//! Files which do not belong to any explicitly configured `FileSet` belong to
4//! the default `FileSet`. 4//! the default `FileSet`.
5use std::{cmp, fmt, iter}; 5use std::{fmt, iter};
6 6
7use paths::AbsPathBuf; 7use paths::AbsPathBuf;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
@@ -44,6 +44,12 @@ pub struct FileSetConfig {
44 roots: Vec<(AbsPathBuf, usize)>, 44 roots: Vec<(AbsPathBuf, usize)>,
45} 45}
46 46
47impl Default for FileSetConfig {
48 fn default() -> Self {
49 FileSetConfig::builder().build()
50 }
51}
52
47impl FileSetConfig { 53impl FileSetConfig {
48 pub fn builder() -> FileSetConfigBuilder { 54 pub fn builder() -> FileSetConfigBuilder {
49 FileSetConfigBuilder::default() 55 FileSetConfigBuilder::default()
@@ -60,14 +66,19 @@ impl FileSetConfig {
60 self.n_file_sets 66 self.n_file_sets
61 } 67 }
62 fn classify(&self, path: &VfsPath) -> usize { 68 fn classify(&self, path: &VfsPath) -> usize {
63 for (root, idx) in self.roots.iter() { 69 let path = match path.as_path() {
64 if let Some(path) = path.as_path() { 70 Some(it) => it,
65 if path.starts_with(root) { 71 None => return self.len() - 1,
66 return *idx; 72 };
67 } 73 let idx = match self.roots.binary_search_by(|(p, _)| p.as_path().cmp(path)) {
68 } 74 Ok(it) => it,
75 Err(it) => it.saturating_sub(1),
76 };
77 if path.starts_with(&self.roots[idx].0) {
78 self.roots[idx].1
79 } else {
80 self.len() - 1
69 } 81 }
70 self.len() - 1
71 } 82 }
72} 83}
73 84
@@ -82,6 +93,9 @@ impl Default for FileSetConfigBuilder {
82} 93}
83 94
84impl FileSetConfigBuilder { 95impl FileSetConfigBuilder {
96 pub fn len(&self) -> usize {
97 self.roots.len()
98 }
85 pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) { 99 pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) {
86 self.roots.push(roots) 100 self.roots.push(roots)
87 } 101 }
@@ -93,7 +107,7 @@ impl FileSetConfigBuilder {
93 .enumerate() 107 .enumerate()
94 .flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i))) 108 .flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i)))
95 .collect(); 109 .collect();
96 roots.sort_by_key(|(path, _)| cmp::Reverse(path.to_string_lossy().len())); 110 roots.sort();
97 FileSetConfig { n_file_sets, roots } 111 FileSetConfig { n_file_sets, roots }
98 } 112 }
99} 113}
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index 75ce61cf9..055219b0c 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -79,6 +79,9 @@ pub enum ChangeKind {
79} 79}
80 80
81impl Vfs { 81impl Vfs {
82 pub fn len(&self) -> usize {
83 self.data.len()
84 }
82 pub fn file_id(&self, path: &VfsPath) -> Option<FileId> { 85 pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
83 self.interner.get(path).filter(|&it| self.get(it).is_some()) 86 self.interner.get(path).filter(|&it| self.get(it).is_some())
84 } 87 }