Skip to content

Commit c544f9a

Browse files
Merge #4940
4940: Add support for marking doctest items as distinct from normal code r=ltentrup a=Nashenas88 This adds `HighlightTag::Generic | HighlightModifier::Injected` as the default highlight for all elements within a doctest. Please feel free to suggest that a new tag be created or a different one used. ![Screenshot from 2020-06-23 09-18-13](https://user-images.githubusercontent.com/1673130/85408493-9752ce00-b532-11ea-94fe-197353ccc778.png) Fixes #4929 Fixes #4939 Co-authored-by: Paul Daniel Faria <[email protected]> Co-authored-by: Paul Daniel Faria <[email protected]>
2 parents 471d44e + 0d87eee commit c544f9a

12 files changed

+92
-39
lines changed

crates/ra_ide/src/snapshots/highlight_doctest.html

+17-15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }
@@ -33,7 +35,7 @@
3335
.control { font-style: italic; }
3436
</style>
3537
<pre><code><span class="comment documentation">/// ```</span>
36-
<span class="comment documentation">/// </span><span class="keyword">let</span> _ = <span class="string_literal">"early doctests should not go boom"</span>;
38+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> _ = </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="generic injected">;</span>
3739
<span class="comment documentation">/// ```</span>
3840
<span class="keyword">struct</span> <span class="struct declaration">Foo</span> {
3941
<span class="field declaration">bar</span>: <span class="builtin_type">bool</span>,
@@ -47,8 +49,8 @@
4749
<span class="comment documentation">/// # Examples</span>
4850
<span class="comment documentation">///</span>
4951
<span class="comment documentation">/// ```</span>
50-
<span class="comment documentation">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span>
51-
<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>();
52+
<span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute injected">#![</span><span class="function attribute injected">allow</span><span class="attribute injected">(unused_mut)]</span>
53+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="generic injected">: </span><span class="struct injected">Foo</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">();</span>
5254
<span class="comment documentation">/// ```</span>
5355
<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> {
5456
<span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> }
@@ -59,26 +61,26 @@
5961
<span class="comment documentation">/// # Examples</span>
6062
<span class="comment documentation">///</span>
6163
<span class="comment documentation">/// ```</span>
62-
<span class="comment documentation">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>;
64+
<span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="generic injected"> </span><span class="module injected">x</span><span class="generic injected">::</span><span class="module injected">y</span><span class="generic injected">;</span>
6365
<span class="comment documentation">///</span>
64-
<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>();
66+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foo</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">();</span>
6567
<span class="comment documentation">///</span>
66-
<span class="comment documentation">/// </span><span class="comment">// calls bar on foo</span>
67-
<span class="comment documentation">/// </span><span class="macro">assert!</span>(foo.bar());
68+
<span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span>
69+
<span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="generic injected">(foo.bar());</span>
6870
<span class="comment documentation">///</span>
69-
<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>;
71+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">bar</span><span class="generic injected"> = </span><span class="variable injected">foo</span><span class="generic injected">.</span><span class="field injected">bar</span><span class="generic injected"> || </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="constant injected">bar</span><span class="generic injected">;</span>
7072
<span class="comment documentation">///</span>
71-
<span class="comment documentation">/// </span><span class="comment">/* multi-line
72-
</span><span class="comment documentation">/// </span><span class="comment"> comment */</span>
73+
<span class="comment documentation">/// </span><span class="comment injected">/* multi-line
74+
</span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span>
7375
<span class="comment documentation">///</span>
74-
<span class="comment documentation">/// </span><span class="keyword">let</span> <span class="variable declaration">multi_line_string</span> = <span class="string_literal">"Foo
75-
</span><span class="comment documentation">/// </span><span class="string_literal"> bar
76-
</span><span class="comment documentation">/// </span><span class="string_literal"> "</span>;
76+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="generic injected"> = </span><span class="string_literal injected">"Foo
77+
</span><span class="comment documentation">/// </span><span class="string_literal injected"> bar
78+
</span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="generic injected">;</span>
7779
<span class="comment documentation">///</span>
7880
<span class="comment documentation">/// ```</span>
7981
<span class="comment documentation">///</span>
8082
<span class="comment documentation">/// ```rust,no_run</span>
81-
<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>();
83+
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foobar</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">().</span><span class="function injected">bar</span><span class="generic injected">();</span>
8284
<span class="comment documentation">/// ```</span>
8385
<span class="comment documentation">///</span>
8486
<span class="comment documentation">/// ```sh</span>
@@ -90,7 +92,7 @@
9092
}
9193

9294
<span class="comment documentation">/// ```</span>
93-
<span class="comment documentation">/// </span><span class="macro">noop!</span>(<span class="numeric_literal">1</span>);
95+
<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="generic injected">(</span><span class="numeric_literal injected">1</span><span class="generic injected">);</span>
9496
<span class="comment documentation">/// ```</span>
9597
<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> {
9698
($expr:expr) =&gt; {

crates/ra_ide/src/snapshots/highlight_injection.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }

crates/ra_ide/src/snapshots/highlight_strings.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }

crates/ra_ide/src/snapshots/highlight_unsafe.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }

crates/ra_ide/src/snapshots/highlighting.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }

crates/ra_ide/src/snapshots/rainbow_highlighting.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
77
.comment { color: #7F9F7F; }
8+
.documentation { color: #629755; }
9+
.injected { opacity: 0.65 ; }
810
.struct, .enum { color: #7CB8BB; }
911
.enum_variant { color: #BDE0F3; }
1012
.string_literal { color: #CC9393; }

crates/ra_ide/src/syntax_highlighting.rs

+46-18
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ pub(crate) fn highlight(
236236
});
237237
}
238238
}
239-
stack.pop_and_inject(false);
239+
stack.pop_and_inject(None);
240240
}
241241
} else if let Some(string) =
242242
element_to_highlight.as_token().cloned().and_then(ast::RawString::cast)
@@ -324,16 +324,27 @@ impl HighlightedRangeStack {
324324
cloned
325325
}
326326

327+
/// Remove the `HighlightRange` of `parent` that's currently covered by `child`.
328+
fn intersect_partial(parent: &mut HighlightedRange, child: &HighlightedRange) {
329+
assert!(
330+
parent.range.start() <= child.range.start()
331+
&& parent.range.end() >= child.range.start()
332+
&& child.range.end() > parent.range.end()
333+
);
334+
335+
parent.range = TextRange::new(parent.range.start(), child.range.start());
336+
}
337+
327338
/// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`)
328339
/// can only modify the last range currently on the stack.
329340
/// Can be used to do injections that span multiple ranges, like the
330341
/// doctest injection below.
331-
/// If `delete` is set to true, the parent range is deleted instead of
332-
/// intersected.
342+
/// If `overwrite_parent` is non-optional, the highlighting of the parent range
343+
/// is overwritten with the argument.
333344
///
334345
/// Note that `pop` can be simulated by `pop_and_inject(false)` but the
335346
/// latter is computationally more expensive.
336-
fn pop_and_inject(&mut self, delete: bool) {
347+
fn pop_and_inject(&mut self, overwrite_parent: Option<Highlight>) {
337348
let mut children = self.stack.pop().unwrap();
338349
let prev = self.stack.last_mut().unwrap();
339350
children.sort_by_key(|range| range.range.start());
@@ -343,26 +354,45 @@ impl HighlightedRangeStack {
343354
if let Some(idx) =
344355
prev.iter().position(|parent| parent.range.contains_range(child.range))
345356
{
357+
if let Some(tag) = overwrite_parent {
358+
prev[idx].highlight = tag;
359+
}
360+
346361
let cloned = Self::intersect(&mut prev[idx], &child);
347-
let insert_idx = if delete || prev[idx].range.is_empty() {
362+
let insert_idx = if prev[idx].range.is_empty() {
348363
prev.remove(idx);
349364
idx
350365
} else {
351366
idx + 1
352367
};
353368
prev.insert(insert_idx, child);
354-
if !delete && !cloned.range.is_empty() {
369+
if !cloned.range.is_empty() {
355370
prev.insert(insert_idx + 1, cloned);
356371
}
357-
} else if let Some(_idx) =
358-
prev.iter().position(|parent| parent.range.contains(child.range.start()))
359-
{
360-
unreachable!("child range should be completely contained in parent range");
361372
} else {
362-
let idx = prev
363-
.binary_search_by_key(&child.range.start(), |range| range.range.start())
364-
.unwrap_or_else(|x| x);
365-
prev.insert(idx, child);
373+
let maybe_idx =
374+
prev.iter().position(|parent| parent.range.contains(child.range.start()));
375+
match (overwrite_parent, maybe_idx) {
376+
(Some(_), Some(idx)) => {
377+
Self::intersect_partial(&mut prev[idx], &child);
378+
let insert_idx = if prev[idx].range.is_empty() {
379+
prev.remove(idx);
380+
idx
381+
} else {
382+
idx + 1
383+
};
384+
prev.insert(insert_idx, child);
385+
}
386+
(_, None) => {
387+
let idx = prev
388+
.binary_search_by_key(&child.range.start(), |range| range.range.start())
389+
.unwrap_or_else(|x| x);
390+
prev.insert(idx, child);
391+
}
392+
_ => {
393+
unreachable!("child range should be completely contained in parent range");
394+
}
395+
}
366396
}
367397
}
368398
}
@@ -516,11 +546,9 @@ fn highlight_element(
516546
let ty = sema.type_of_expr(&expr)?;
517547
if !ty.is_raw_ptr() {
518548
return None;
549+
} else {
550+
HighlightTag::Operator | HighlightModifier::Unsafe
519551
}
520-
521-
let mut h = Highlight::new(HighlightTag::Operator);
522-
h |= HighlightModifier::Unsafe;
523-
h
524552
}
525553
T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
526554
Highlight::new(HighlightTag::Macro)

crates/ra_ide/src/syntax_highlighting/html.rs

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
6464
6565
.lifetime { color: #DFAF8F; font-style: italic; }
6666
.comment { color: #7F9F7F; }
67+
.documentation { color: #629755; }
68+
.injected { opacity: 0.65 ; }
6769
.struct, .enum { color: #7CB8BB; }
6870
.enum_variant { color: #BDE0F3; }
6971
.string_literal { color: #CC9393; }

crates/ra_ide/src/syntax_highlighting/injection.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use ra_syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize};
88
use stdx::SepBy;
99

1010
use crate::{
11-
call_info::ActiveParameter, Analysis, HighlightModifier, HighlightTag, HighlightedRange,
12-
RootDatabase,
11+
call_info::ActiveParameter, Analysis, Highlight, HighlightModifier, HighlightTag,
12+
HighlightedRange, RootDatabase,
1313
};
1414

1515
use super::HighlightedRangeStack;
@@ -172,6 +172,7 @@ pub(super) fn highlight_doc_comment(
172172
h.range.end() + end_offset.unwrap_or(start_offset) - h.range.start(),
173173
);
174174

175+
h.highlight |= HighlightModifier::Injected;
175176
stack.add(h);
176177
}
177178
}
@@ -181,6 +182,7 @@ pub(super) fn highlight_doc_comment(
181182
for comment in new_comments {
182183
stack.add(comment);
183184
}
184-
stack.pop_and_inject(false);
185-
stack.pop_and_inject(true);
185+
stack.pop_and_inject(None);
186+
stack
187+
.pop_and_inject(Some(Highlight::from(HighlightTag::Generic) | HighlightModifier::Injected));
186188
}

crates/ra_ide/src/syntax_highlighting/tags.rs

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum HighlightTag {
2727
Field,
2828
FormatSpecifier,
2929
Function,
30+
Generic,
3031
Keyword,
3132
Lifetime,
3233
Macro,
@@ -57,6 +58,7 @@ pub enum HighlightModifier {
5758
/// not.
5859
Definition,
5960
Documentation,
61+
Injected,
6062
Mutable,
6163
Unsafe,
6264
}
@@ -77,6 +79,7 @@ impl HighlightTag {
7779
HighlightTag::Field => "field",
7880
HighlightTag::FormatSpecifier => "format_specifier",
7981
HighlightTag::Function => "function",
82+
HighlightTag::Generic => "generic",
8083
HighlightTag::Keyword => "keyword",
8184
HighlightTag::Lifetime => "lifetime",
8285
HighlightTag::Macro => "macro",
@@ -110,6 +113,7 @@ impl HighlightModifier {
110113
HighlightModifier::ControlFlow,
111114
HighlightModifier::Definition,
112115
HighlightModifier::Documentation,
116+
HighlightModifier::Injected,
113117
HighlightModifier::Mutable,
114118
HighlightModifier::Unsafe,
115119
];
@@ -120,6 +124,7 @@ impl HighlightModifier {
120124
HighlightModifier::ControlFlow => "control",
121125
HighlightModifier::Definition => "declaration",
122126
HighlightModifier::Documentation => "documentation",
127+
HighlightModifier::Injected => "injected",
123128
HighlightModifier::Mutable => "mutable",
124129
HighlightModifier::Unsafe => "unsafe",
125130
}

crates/rust-analyzer/src/semantic_tokens.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ define_semantic_token_types![
3939
(BOOLEAN, "boolean"),
4040
(BUILTIN_TYPE, "builtinType"),
4141
(ENUM_MEMBER, "enumMember"),
42+
(ESCAPE_SEQUENCE, "escapeSequence"),
43+
(FORMAT_SPECIFIER, "formatSpecifier"),
44+
(GENERIC, "generic"),
4245
(LIFETIME, "lifetime"),
4346
(SELF_KEYWORD, "selfKeyword"),
4447
(TYPE_ALIAS, "typeAlias"),
4548
(UNION, "union"),
4649
(UNRESOLVED_REFERENCE, "unresolvedReference"),
47-
(FORMAT_SPECIFIER, "formatSpecifier"),
48-
(ESCAPE_SEQUENCE, "escapeSequence"),
4950
];
5051

5152
macro_rules! define_semantic_token_modifiers {
@@ -68,6 +69,7 @@ macro_rules! define_semantic_token_modifiers {
6869
define_semantic_token_modifiers![
6970
(CONSTANT, "constant"),
7071
(CONTROL_FLOW, "controlFlow"),
72+
(INJECTED, "injected"),
7173
(MUTABLE, "mutable"),
7274
(UNSAFE, "unsafe"),
7375
(ATTRIBUTE_MODIFIER, "attribute"),

crates/rust-analyzer/src/to_proto.rs

+2
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ fn semantic_token_type_and_modifiers(
295295
HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE,
296296
HighlightTag::Field => lsp_types::SemanticTokenType::PROPERTY,
297297
HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION,
298+
HighlightTag::Generic => semantic_tokens::GENERIC,
298299
HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE,
299300
HighlightTag::Constant => {
300301
mods |= semantic_tokens::CONSTANT;
@@ -331,6 +332,7 @@ fn semantic_token_type_and_modifiers(
331332
HighlightModifier::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER,
332333
HighlightModifier::Definition => lsp_types::SemanticTokenModifier::DECLARATION,
333334
HighlightModifier::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION,
335+
HighlightModifier::Injected => semantic_tokens::INJECTED,
334336
HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW,
335337
HighlightModifier::Mutable => semantic_tokens::MUTABLE,
336338
HighlightModifier::Unsafe => semantic_tokens::UNSAFE,

0 commit comments

Comments
 (0)