Skip to content

Commit 8e8aa7b

Browse files
committed
Auto merge of rust-lang#12358 - Veykril:hl-mac, r=Veykril
minor: Simplify syntax-highlighting macro checks
2 parents db9930b + 9f6d99c commit 8e8aa7b

File tree

1 file changed

+87
-93
lines changed

1 file changed

+87
-93
lines changed

crates/ide/src/syntax_highlighting.rs

+87-93
Original file line numberDiff line numberDiff line change
@@ -206,18 +206,19 @@ fn traverse(
206206
let is_unlinked = sema.to_module_def(file_id).is_none();
207207
let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
208208

209-
let mut current_macro_call: Option<ast::MacroCall> = None;
210-
let mut current_attr_call = None;
211-
let mut current_derive_call = None;
209+
let mut tt_level = 0;
210+
let mut attr_or_derive_item = None;
212211
let mut current_macro: Option<ast::Macro> = None;
213212
let mut macro_highlighter = MacroHighlighter::default();
214213
let mut inside_attribute = false;
215214

216215
// Walk all nodes, keeping track of whether we are inside a macro or not.
217216
// If in macro, expand it first and highlight the expanded code.
218217
for event in root.preorder_with_tokens() {
218+
use WalkEvent::{Enter, Leave};
219+
219220
let range = match &event {
220-
WalkEvent::Enter(it) | WalkEvent::Leave(it) => it.text_range(),
221+
Enter(it) | Leave(it) => it.text_range(),
221222
};
222223

223224
// Element outside of the viewport, no need to highlight
@@ -227,78 +228,84 @@ fn traverse(
227228

228229
// set macro and attribute highlighting states
229230
match event.clone() {
230-
WalkEvent::Enter(NodeOrToken::Node(node)) => match ast::Item::cast(node.clone()) {
231-
Some(ast::Item::MacroCall(mcall)) => {
232-
current_macro_call = Some(mcall);
233-
continue;
234-
}
235-
Some(ast::Item::MacroRules(mac)) => {
236-
macro_highlighter.init();
237-
current_macro = Some(mac.into());
238-
continue;
239-
}
240-
Some(ast::Item::MacroDef(mac)) => {
241-
macro_highlighter.init();
242-
current_macro = Some(mac.into());
243-
continue;
244-
}
245-
Some(item) => {
246-
if matches!(node.kind(), FN | CONST | STATIC) {
247-
bindings_shadow_count.clear();
231+
Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
232+
tt_level += 1;
233+
}
234+
Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
235+
tt_level -= 1;
236+
}
237+
Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
238+
inside_attribute = true
239+
}
240+
Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
241+
inside_attribute = false
242+
}
243+
244+
Enter(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
245+
match ast::Item::cast(node.clone()) {
246+
Some(ast::Item::MacroRules(mac)) => {
247+
macro_highlighter.init();
248+
current_macro = Some(mac.into());
249+
continue;
248250
}
251+
Some(ast::Item::MacroDef(mac)) => {
252+
macro_highlighter.init();
253+
current_macro = Some(mac.into());
254+
continue;
255+
}
256+
Some(item) => {
257+
if matches!(node.kind(), FN | CONST | STATIC) {
258+
bindings_shadow_count.clear();
259+
}
249260

250-
if sema.is_attr_macro_call(&item) {
251-
current_attr_call = Some(item);
252-
} else if current_attr_call.is_none() {
253-
let adt = match item {
254-
ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
255-
ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
256-
ast::Item::Union(it) => Some(ast::Adt::Union(it)),
257-
_ => None,
258-
};
259-
match adt {
260-
Some(adt) if sema.is_derive_annotated(&adt) => {
261-
current_derive_call = Some(ast::Item::from(adt));
261+
if attr_or_derive_item.is_none() {
262+
if sema.is_attr_macro_call(&item) {
263+
attr_or_derive_item = Some(item);
264+
} else {
265+
let adt = match item {
266+
ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
267+
ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
268+
ast::Item::Union(it) => Some(ast::Adt::Union(it)),
269+
_ => None,
270+
};
271+
match adt {
272+
Some(adt) if sema.is_derive_annotated(&adt) => {
273+
attr_or_derive_item = Some(ast::Item::from(adt));
274+
}
275+
_ => (),
276+
}
262277
}
263-
_ => (),
264278
}
265279
}
280+
_ => (),
266281
}
267-
None if ast::Attr::can_cast(node.kind()) => inside_attribute = true,
268-
_ => (),
269-
},
270-
WalkEvent::Leave(NodeOrToken::Node(node)) => match ast::Item::cast(node.clone()) {
271-
Some(ast::Item::MacroCall(mcall)) => {
272-
assert_eq!(current_macro_call, Some(mcall));
273-
current_macro_call = None;
274-
}
275-
Some(ast::Item::MacroRules(mac)) => {
276-
assert_eq!(current_macro, Some(mac.into()));
277-
current_macro = None;
278-
macro_highlighter = MacroHighlighter::default();
279-
}
280-
Some(ast::Item::MacroDef(mac)) => {
281-
assert_eq!(current_macro, Some(mac.into()));
282-
current_macro = None;
283-
macro_highlighter = MacroHighlighter::default();
284-
}
285-
Some(item) if current_attr_call.as_ref().map_or(false, |it| *it == item) => {
286-
current_attr_call = None;
287-
}
288-
Some(item) if current_derive_call.as_ref().map_or(false, |it| *it == item) => {
289-
current_derive_call = None;
282+
}
283+
Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
284+
match ast::Item::cast(node.clone()) {
285+
Some(ast::Item::MacroRules(mac)) => {
286+
assert_eq!(current_macro, Some(mac.into()));
287+
current_macro = None;
288+
macro_highlighter = MacroHighlighter::default();
289+
}
290+
Some(ast::Item::MacroDef(mac)) => {
291+
assert_eq!(current_macro, Some(mac.into()));
292+
current_macro = None;
293+
macro_highlighter = MacroHighlighter::default();
294+
}
295+
Some(item) if attr_or_derive_item.as_ref().map_or(false, |it| *it == item) => {
296+
attr_or_derive_item = None;
297+
}
298+
_ => (),
290299
}
291-
None if ast::Attr::can_cast(node.kind()) => inside_attribute = false,
292-
_ => (),
293-
},
300+
}
294301
_ => (),
295302
}
296303

297304
let element = match event {
298-
WalkEvent::Enter(NodeOrToken::Token(tok)) if tok.kind() == WHITESPACE => continue,
299-
WalkEvent::Enter(it) => it,
300-
WalkEvent::Leave(NodeOrToken::Token(_)) => continue,
301-
WalkEvent::Leave(NodeOrToken::Node(node)) => {
305+
Enter(NodeOrToken::Token(tok)) if tok.kind() == WHITESPACE => continue,
306+
Enter(it) => it,
307+
Leave(NodeOrToken::Token(_)) => continue,
308+
Leave(NodeOrToken::Node(node)) => {
302309
// Doc comment highlighting injection, we do this when leaving the node
303310
// so that we overwrite the highlighting of the doc comment itself.
304311
inject::doc_comment(hl, sema, InFile::new(file_id.into(), &node));
@@ -323,38 +330,25 @@ fn traverse(
323330

324331
// Descending tokens into macros is expensive even if no descending occurs, so make sure
325332
// that we actually are in a position where descending is possible.
326-
let in_macro = current_macro_call.is_some()
327-
|| current_derive_call.is_some()
328-
|| current_attr_call.is_some();
333+
let in_macro = tt_level > 0 || attr_or_derive_item.is_some();
329334
let descended_element = if in_macro {
330335
// Attempt to descend tokens into macro-calls.
331336
match element {
332337
NodeOrToken::Token(token) if token.kind() != COMMENT => {
333-
// For function-like macro calls and derive attributes, only attempt to descend if
334-
// we are inside their token-trees.
335-
let in_tt = current_attr_call.is_some()
336-
|| token.parent().as_ref().map(SyntaxNode::kind) == Some(TOKEN_TREE);
337-
338-
if in_tt {
339-
let token = sema.descend_into_macros_single(token);
340-
match token.parent().and_then(ast::NameLike::cast) {
341-
// Remap the token into the wrapping single token nodes
342-
// FIXME: if the node doesn't resolve, we also won't do token based highlighting!
343-
Some(parent) => match (token.kind(), parent.syntax().kind()) {
344-
(T![self] | T![ident], NAME | NAME_REF) => {
345-
NodeOrToken::Node(parent)
346-
}
347-
(T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
348-
NodeOrToken::Node(parent)
349-
}
350-
(INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
351-
(LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
352-
_ => NodeOrToken::Token(token),
353-
},
354-
None => NodeOrToken::Token(token),
355-
}
356-
} else {
357-
NodeOrToken::Token(token)
338+
let token = sema.descend_into_macros_single(token);
339+
match token.parent().and_then(ast::NameLike::cast) {
340+
// Remap the token into the wrapping single token nodes
341+
// FIXME: if the node doesn't resolve, we also won't do token based highlighting!
342+
Some(parent) => match (token.kind(), parent.syntax().kind()) {
343+
(T![self] | T![ident], NAME | NAME_REF) => NodeOrToken::Node(parent),
344+
(T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
345+
NodeOrToken::Node(parent)
346+
}
347+
(INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
348+
(LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
349+
_ => NodeOrToken::Token(token),
350+
},
351+
None => NodeOrToken::Token(token),
358352
}
359353
}
360354
e => e,

0 commit comments

Comments
 (0)