Skip to content

Commit c4b3db0

Browse files
committed
Syntactic highlighting of NAME_REF for injections
This commit adds a function that tries to determine the syntax highlighting class of NAME_REFs based on the usage. It is used for highlighting injections (such as highlighting of doctests) as the semantic logic will most of the time result in unresolved references. It also adds a color to unresolved references in HTML encoding.
1 parent f4f5117 commit c4b3db0

File tree

12 files changed

+102
-16
lines changed

12 files changed

+102
-16
lines changed

crates/ra_ide/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,12 +440,14 @@ impl Analysis {
440440

441441
/// Computes syntax highlighting for the given file
442442
pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
443-
self.with_db(|db| syntax_highlighting::highlight(db, file_id, None))
443+
self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false))
444444
}
445445

446446
/// Computes syntax highlighting for the given file range.
447447
pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> {
448-
self.with_db(|db| syntax_highlighting::highlight(db, frange.file_id, Some(frange.range)))
448+
self.with_db(|db| {
449+
syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false)
450+
})
449451
}
450452

451453
/// Computes syntax highlighting for the given file.

crates/ra_ide/src/prime_caches.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ use crate::{FileId, RootDatabase};
77

88
pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) {
99
for file in files {
10-
let _ = crate::syntax_highlighting::highlight(db, file, None);
10+
let _ = crate::syntax_highlighting::highlight(db, file, None, false);
1111
}
1212
}

crates/ra_ide/src/snapshots/highlight_doctest.html

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,45 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }
3132
.control { font-style: italic; }
3233
</style>
33-
<pre><code><span class="keyword">impl</span> <span class="unresolved_reference">Foo</span> {
34+
<pre><code><span class="keyword">struct</span> <span class="struct declaration">Foo</span> {
35+
<span class="field declaration">bar</span>: <span class="builtin_type">bool</span>,
36+
}
37+
38+
<span class="keyword">impl</span> <span class="struct">Foo</span> {
39+
<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+
3441
<span class="comment">/// Constructs a new `Foo`.</span>
3542
<span class="comment">///</span>
3643
<span class="comment">/// # Examples</span>
3744
<span class="comment">///</span>
3845
<span class="comment">/// ```</span>
3946
<span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span>
40-
<span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="unresolved_reference">Foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>();
47+
<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>();
4148
<span class="comment">/// ```</span>
42-
<span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -&gt; <span class="unresolved_reference">Foo</span> {
43-
<span class="unresolved_reference">Foo</span> { }
49+
<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="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> }
4451
}
4552

4653
<span class="comment">/// `bar` method on `Foo`.</span>
4754
<span class="comment">///</span>
4855
<span class="comment">/// # Examples</span>
4956
<span class="comment">///</span>
5057
<span class="comment">/// ```</span>
51-
<span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>();
58+
<span class="comment">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>;
59+
<span class="comment">///</span>
60+
<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>();
5261
<span class="comment">///</span>
5362
<span class="comment">/// </span><span class="comment">// calls bar on foo</span>
5463
<span class="comment">/// </span><span class="macro">assert!</span>(foo.bar());
5564
<span class="comment">///</span>
65+
<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">///</span>
5667
<span class="comment">/// </span><span class="comment">/* multi-line
5768
</span><span class="comment">/// </span><span class="comment"> comment */</span>
5869
<span class="comment">///</span>
@@ -63,7 +74,7 @@
6374
<span class="comment">/// ```</span>
6475
<span class="comment">///</span>
6576
<span class="comment">/// ```</span>
66-
<span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>().<span class="unresolved_reference">bar</span>();
77+
<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>();
6778
<span class="comment">/// ```</span>
6879
<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> {
6980
<span class="bool_literal">true</span>

crates/ra_ide/src/snapshots/highlight_injection.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }

crates/ra_ide/src/snapshots/highlight_strings.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }

crates/ra_ide/src/snapshots/highlight_unsafe.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }

crates/ra_ide/src/snapshots/highlighting.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }

crates/ra_ide/src/snapshots/rainbow_highlighting.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
.variable { color: #DCDCCC; }
2626
.format_specifier { color: #CC696B; }
2727
.mutable { text-decoration: underline; }
28+
.unresolved_reference { color: #FC5555; }
2829

2930
.keyword { color: #F0DFAF; font-weight: bold; }
3031
.keyword.unsafe { color: #BC8383; font-weight: bold; }

crates/ra_ide/src/syntax_highlighting.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub(crate) fn highlight(
4444
db: &RootDatabase,
4545
file_id: FileId,
4646
range_to_highlight: Option<TextRange>,
47+
syntactic_name_ref_highlighting: bool,
4748
) -> Vec<HighlightedRange> {
4849
let _p = profile("highlight");
4950
let sema = Semantics::new(db);
@@ -104,6 +105,7 @@ pub(crate) fn highlight(
104105
if let Some((highlight, binding_hash)) = highlight_element(
105106
&sema,
106107
&mut bindings_shadow_count,
108+
syntactic_name_ref_highlighting,
107109
name.syntax().clone().into(),
108110
) {
109111
stack.add(HighlightedRange {
@@ -200,9 +202,12 @@ pub(crate) fn highlight(
200202

201203
let is_format_string = format_string.as_ref() == Some(&element_to_highlight);
202204

203-
if let Some((highlight, binding_hash)) =
204-
highlight_element(&sema, &mut bindings_shadow_count, element_to_highlight.clone())
205-
{
205+
if let Some((highlight, binding_hash)) = highlight_element(
206+
&sema,
207+
&mut bindings_shadow_count,
208+
syntactic_name_ref_highlighting,
209+
element_to_highlight.clone(),
210+
) {
206211
stack.add(HighlightedRange { range, highlight, binding_hash });
207212
if let Some(string) =
208213
element_to_highlight.as_token().cloned().and_then(ast::String::cast)
@@ -410,6 +415,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
410415
fn highlight_element(
411416
sema: &Semantics<RootDatabase>,
412417
bindings_shadow_count: &mut FxHashMap<Name, u32>,
418+
syntactic_name_ref_highlighting: bool,
413419
element: SyntaxElement,
414420
) -> Option<(Highlight, Option<u64>)> {
415421
let db = sema.db;
@@ -463,6 +469,7 @@ fn highlight_element(
463469
}
464470
NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
465471
},
472+
None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref),
466473
None => HighlightTag::UnresolvedReference.into(),
467474
}
468475
}
@@ -614,3 +621,53 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
614621

615622
tag.into()
616623
}
624+
625+
fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
626+
let default = HighlightTag::UnresolvedReference;
627+
628+
let parent = match name.syntax().parent() {
629+
Some(it) => it,
630+
_ => return default.into(),
631+
};
632+
633+
let tag = match parent.kind() {
634+
METHOD_CALL_EXPR => HighlightTag::Function,
635+
FIELD_EXPR => HighlightTag::Field,
636+
PATH_SEGMENT => {
637+
let path = match parent.parent().and_then(ast::Path::cast) {
638+
Some(it) => it,
639+
_ => return default.into(),
640+
};
641+
let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) {
642+
Some(it) => it,
643+
_ => {
644+
// within path, decide whether it is module or adt by checking for uppercase name
645+
return if name.text().chars().next().unwrap_or_default().is_uppercase() {
646+
HighlightTag::Struct
647+
} else {
648+
HighlightTag::Module
649+
}
650+
.into();
651+
}
652+
};
653+
let parent = match expr.syntax().parent() {
654+
Some(it) => it,
655+
None => return default.into(),
656+
};
657+
658+
match parent.kind() {
659+
CALL_EXPR => HighlightTag::Function,
660+
_ => {
661+
if name.text().chars().next().unwrap_or_default().is_uppercase() {
662+
HighlightTag::Struct
663+
} else {
664+
HighlightTag::Constant
665+
}
666+
}
667+
}
668+
}
669+
_ => default,
670+
};
671+
672+
tag.into()
673+
}

crates/ra_ide/src/syntax_highlighting/html.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
1919
)
2020
}
2121

22-
let ranges = highlight(db, file_id, None);
22+
let ranges = highlight(db, file_id, None, false);
2323
let text = parse.tree().syntax().to_string();
2424
let mut prev_pos = TextSize::from(0);
2525
let mut buf = String::new();
@@ -84,6 +84,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
8484
.variable { color: #DCDCCC; }
8585
.format_specifier { color: #CC696B; }
8686
.mutable { text-decoration: underline; }
87+
.unresolved_reference { color: #FC5555; }
8788
8889
.keyword { color: #F0DFAF; font-weight: bold; }
8990
.keyword.unsafe { color: #BC8383; font-weight: bold; }

0 commit comments

Comments
 (0)