mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +00:00
highlight mutable variables differently
This commit is contained in:
parent
a15a278308
commit
4abe03879b
7 changed files with 110 additions and 51 deletions
|
@ -68,6 +68,7 @@ pub use self::{
|
||||||
source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
|
source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
|
||||||
source_id::{AstIdMap, ErasedFileAstId},
|
source_id::{AstIdMap, ErasedFileAstId},
|
||||||
ty::{display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor},
|
ty::{display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor},
|
||||||
|
type_ref::Mutability,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::code_model::{
|
pub use self::code_model::{
|
||||||
|
|
|
@ -12,6 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
|
||||||
.attribute { color: #BFEBBF; }
|
.attribute { color: #BFEBBF; }
|
||||||
.literal { color: #DFAF8F; }
|
.literal { color: #DFAF8F; }
|
||||||
.macro { color: #DFAF8F; }
|
.macro { color: #DFAF8F; }
|
||||||
|
.variable\.mut { color: #DFAF8F; }
|
||||||
|
|
||||||
.keyword { color: #F0DFAF; }
|
.keyword { color: #F0DFAF; }
|
||||||
.keyword\.unsafe { color: #F0DFAF; font-weight: bold; }
|
.keyword\.unsafe { color: #F0DFAF; font-weight: bold; }
|
||||||
|
@ -32,9 +33,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
|
||||||
<span class="keyword">fn</span> <span class="function">main</span>() {
|
<span class="keyword">fn</span> <span class="function">main</span>() {
|
||||||
<span class="macro">println</span><span class="macro">!</span>(<span class="string">"Hello, {}!"</span>, <span class="literal">92</span>);
|
<span class="macro">println</span><span class="macro">!</span>(<span class="string">"Hello, {}!"</span>, <span class="literal">92</span>);
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable" data-binding-hash="9636295041291189729" style="color: hsl(51,57%,74%);">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>();
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>();
|
||||||
<span class="keyword.control">if</span> <span class="keyword">true</span> {
|
<span class="keyword.control">if</span> <span class="keyword">true</span> {
|
||||||
<span class="variable" data-binding-hash="8496027264380925433" style="color: hsl(18,48%,55%);">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal">0</span>, <span class="field">y</span>: <span class="literal">1</span> });
|
<span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal">0</span>, <span class="field">y</span>: <span class="literal">1</span> });
|
||||||
}
|
}
|
||||||
<span class="keyword.unsafe">unsafe</span> { <span class="variable" data-binding-hash="8496027264380925433" style="color: hsl(18,48%,55%);">vec</span>.<span class="text">set_len</span>(<span class="literal">0</span>); }
|
<span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal">0</span>); }
|
||||||
|
|
||||||
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">x</span> = <span class="literal">42</span>;
|
||||||
|
<span class="keyword">let</span> <span class="variable.mut">y</span> = &<span class="keyword">mut</span> <span class="variable.mut">x</span>;
|
||||||
|
<span class="keyword">let</span> <span class="variable">z</span> = &<span class="variable.mut">y</span>;
|
||||||
|
|
||||||
|
<span class="variable.mut">y</span>;
|
||||||
}</code></pre>
|
}</code></pre>
|
|
@ -12,6 +12,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
|
||||||
.attribute { color: #BFEBBF; }
|
.attribute { color: #BFEBBF; }
|
||||||
.literal { color: #DFAF8F; }
|
.literal { color: #DFAF8F; }
|
||||||
.macro { color: #DFAF8F; }
|
.macro { color: #DFAF8F; }
|
||||||
|
.variable\.mut { color: #DFAF8F; }
|
||||||
|
|
||||||
.keyword { color: #F0DFAF; }
|
.keyword { color: #F0DFAF; }
|
||||||
.keyword\.unsafe { color: #F0DFAF; font-weight: bold; }
|
.keyword\.unsafe { color: #F0DFAF; font-weight: bold; }
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
|
use hir::{Mutability, Ty};
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast, AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T,
|
ast, AstNode, Direction, Pat, PatKind, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*,
|
||||||
|
TextRange, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{db::RootDatabase, FileId};
|
use crate::{db::RootDatabase, FileId};
|
||||||
|
@ -30,6 +32,27 @@ fn is_control_keyword(kind: SyntaxKind) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_variable_mutable(db: &RootDatabase, analyzer: &hir::SourceAnalyzer, pat: &Pat) -> bool {
|
||||||
|
let ty = analyzer.type_of_pat(db, pat).unwrap_or(Ty::Unknown);
|
||||||
|
let is_ty_mut = {
|
||||||
|
if let Some((_, mutability)) = ty.as_reference() {
|
||||||
|
match mutability {
|
||||||
|
Mutability::Shared => false,
|
||||||
|
Mutability::Mut => true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_pat_mut = match pat.kind() {
|
||||||
|
PatKind::BindPat(bind_pat) => bind_pat.is_mutable(),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
is_ty_mut || is_pat_mut
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
|
pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
|
||||||
let _p = profile("highlight");
|
let _p = profile("highlight");
|
||||||
let parse = db.parse(file_id);
|
let parse = db.parse(file_id);
|
||||||
|
@ -97,8 +120,12 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
|
||||||
calc_binding_hash(file_id, &text, *shadow_count)
|
calc_binding_hash(file_id, &text, *shadow_count)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if is_variable_mutable(db, &analyzer, ptr.to_node(root)) {
|
||||||
|
"variable.mut"
|
||||||
|
} else {
|
||||||
"variable"
|
"variable"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Some(SelfParam(_)) => "type",
|
Some(SelfParam(_)) => "type",
|
||||||
Some(GenericParam(_)) => "type",
|
Some(GenericParam(_)) => "type",
|
||||||
None => "text",
|
None => "text",
|
||||||
|
@ -109,7 +136,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
|
||||||
}
|
}
|
||||||
NAME => {
|
NAME => {
|
||||||
if let Some(name) = node.as_node().and_then(ast::Name::cast) {
|
if let Some(name) = node.as_node().and_then(ast::Name::cast) {
|
||||||
if name.syntax().ancestors().any(|x| ast::BindPat::cast(x).is_some()) {
|
let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None);
|
||||||
|
if let Some(pat) = name.syntax().ancestors().find_map(Pat::cast) {
|
||||||
binding_hash = Some({
|
binding_hash = Some({
|
||||||
let text = name.syntax().text().to_smol_string();
|
let text = name.syntax().text().to_smol_string();
|
||||||
let shadow_count =
|
let shadow_count =
|
||||||
|
@ -117,7 +145,12 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
|
||||||
*shadow_count += 1;
|
*shadow_count += 1;
|
||||||
calc_binding_hash(file_id, &text, *shadow_count)
|
calc_binding_hash(file_id, &text, *shadow_count)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if is_variable_mutable(db, &analyzer, pat) {
|
||||||
|
"variable.mut"
|
||||||
|
} else {
|
||||||
"variable"
|
"variable"
|
||||||
|
}
|
||||||
} else if name
|
} else if name
|
||||||
.syntax()
|
.syntax()
|
||||||
.parent()
|
.parent()
|
||||||
|
@ -253,6 +286,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
|
||||||
.attribute { color: #BFEBBF; }
|
.attribute { color: #BFEBBF; }
|
||||||
.literal { color: #DFAF8F; }
|
.literal { color: #DFAF8F; }
|
||||||
.macro { color: #DFAF8F; }
|
.macro { color: #DFAF8F; }
|
||||||
|
.variable\\.mut { color: #DFAF8F; }
|
||||||
|
|
||||||
.keyword { color: #F0DFAF; }
|
.keyword { color: #F0DFAF; }
|
||||||
.keyword\\.unsafe { color: #F0DFAF; font-weight: bold; }
|
.keyword\\.unsafe { color: #F0DFAF; font-weight: bold; }
|
||||||
|
@ -289,12 +323,18 @@ fn main() {
|
||||||
vec.push(Foo { x: 0, y: 1 });
|
vec.push(Foo { x: 0, y: 1 });
|
||||||
}
|
}
|
||||||
unsafe { vec.set_len(0); }
|
unsafe { vec.set_len(0); }
|
||||||
|
|
||||||
|
let mut x = 42;
|
||||||
|
let y = &mut x;
|
||||||
|
let z = &y;
|
||||||
|
|
||||||
|
y;
|
||||||
}
|
}
|
||||||
"#
|
"#
|
||||||
.trim(),
|
.trim(),
|
||||||
);
|
);
|
||||||
let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html");
|
let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html");
|
||||||
let actual_html = &analysis.highlight_as_html(file_id, true).unwrap();
|
let actual_html = &analysis.highlight_as_html(file_id, false).unwrap();
|
||||||
let expected_html = &read_text(&dst_file);
|
let expected_html = &read_text(&dst_file);
|
||||||
std::fs::write(dst_file, &actual_html).unwrap();
|
std::fs::write(dst_file, &actual_html).unwrap();
|
||||||
assert_eq_text!(expected_html, actual_html);
|
assert_eq_text!(expected_html, actual_html);
|
||||||
|
|
|
@ -38,7 +38,7 @@ use ra_text_edit::AtomTextEdit;
|
||||||
use crate::syntax_node::GreenNode;
|
use crate::syntax_node::GreenNode;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
ast::AstNode,
|
ast::{AstNode, Pat, PatKind},
|
||||||
parsing::{classify_literal, tokenize, Token},
|
parsing::{classify_literal, tokenize, Token},
|
||||||
ptr::{AstPtr, SyntaxNodePtr},
|
ptr::{AstPtr, SyntaxNodePtr},
|
||||||
syntax_error::{Location, SyntaxError, SyntaxErrorKind},
|
syntax_error::{Location, SyntaxError, SyntaxErrorKind},
|
||||||
|
|
|
@ -432,6 +432,15 @@
|
||||||
"highContrast": "#4EC9B0"
|
"highContrast": "#4EC9B0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "ralsp.variable.mut",
|
||||||
|
"description": "Color for mutable variables",
|
||||||
|
"defaults": {
|
||||||
|
"dark": "#4e65c9",
|
||||||
|
"light": "#263199",
|
||||||
|
"highContrast": "#4e65c9"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "ralsp.module",
|
"id": "ralsp.module",
|
||||||
"description": "Color for modules",
|
"description": "Color for modules",
|
||||||
|
|
|
@ -56,6 +56,7 @@ export class Highlighter {
|
||||||
colorContrib('literal'),
|
colorContrib('literal'),
|
||||||
colorContrib('macro'),
|
colorContrib('macro'),
|
||||||
colorContrib('variable'),
|
colorContrib('variable'),
|
||||||
|
colorContrib('variable.mut'),
|
||||||
colorContrib('field'),
|
colorContrib('field'),
|
||||||
colorContrib('module')
|
colorContrib('module')
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in a new issue