Handle self/super/crate in PathSegment as NameRef

This commit is contained in:
Lukas Wirth 2021-01-15 18:57:32 +01:00
parent 0c58aa9dc0
commit cb863390f2
42 changed files with 258 additions and 254 deletions

4
Cargo.lock generated
View File

@ -1817,9 +1817,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]] [[package]]
name = "ungrammar" name = "ungrammar"
version = "1.7.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7758fccf6038d5c368a17c7224abc85d6508d5ae266d5a3de25faac3cc168509" checksum = "e33a2183403af89252547c4219a06a6cc8aef6302fee67e10e8431866af3ee72"
[[package]] [[package]]
name = "unicase" name = "unicase"

View File

@ -1,5 +1,5 @@
[workspace] [workspace]
members = [ "xtask/", "lib/*", "crates/*" ] members = ["xtask/", "lib/*", "crates/*"]
[profile.dev] [profile.dev]
# Disabling debug info speeds up builds a bunch, # Disabling debug info speeds up builds a bunch,

View File

@ -750,6 +750,7 @@ to_def_impls![
(crate::ConstParam, ast::ConstParam, const_param_to_def), (crate::ConstParam, ast::ConstParam, const_param_to_def),
(crate::MacroDef, ast::MacroRules, macro_rules_to_def), (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
(crate::Local, ast::IdentPat, bind_pat_to_def), (crate::Local, ast::IdentPat, bind_pat_to_def),
(crate::Local, ast::SelfParam, self_param_to_def),
(crate::Label, ast::Label, label_to_def), (crate::Label, ast::Label, label_to_def),
]; ];

View File

@ -114,6 +114,15 @@ impl SourceToDefCtx<'_, '_> {
let pat_id = source_map.node_pat(src.as_ref())?; let pat_id = source_map.node_pat(src.as_ref())?;
Some((container, pat_id)) Some((container, pat_id))
} }
pub(super) fn self_param_to_def(
&mut self,
src: InFile<ast::SelfParam>,
) -> Option<(DefWithBodyId, PatId)> {
let container = self.find_pat_or_label_container(src.as_ref().map(|it| it.syntax()))?;
let (_body, source_map) = self.db.body_with_source_map(container);
let pat_id = source_map.node_self_param(src.as_ref())?;
Some((container, pat_id))
}
pub(super) fn label_to_def( pub(super) fn label_to_def(
&mut self, &mut self,
src: InFile<ast::Label>, src: InFile<ast::Label>,

View File

@ -258,7 +258,7 @@ impl Resolver {
) -> Option<ResolveValueResult> { ) -> Option<ResolveValueResult> {
let n_segments = path.segments.len(); let n_segments = path.segments.len();
let tmp = name![self]; let tmp = name![self];
let first_name = if path.is_self() { &tmp } else { &path.segments.first()? }; let first_name = if path.is_self() { &tmp } else { path.segments.first()? };
let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
for scope in self.scopes.iter().rev() { for scope in self.scopes.iter().rev() {
match scope { match scope {

View File

@ -18,7 +18,7 @@ use itertools::Itertools;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use syntax::{ use syntax::{
ast::{self, AstNode}, ast::{self, AstNode},
SyntaxNode, TextRange, T, SyntaxNode, TextRange,
}; };
use text_edit::TextEdit; use text_edit::TextEdit;
@ -232,7 +232,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
single_use_tree: &ast::UseTree, single_use_tree: &ast::UseTree,
) -> Option<TextEdit> { ) -> Option<TextEdit> {
let use_tree_list_node = single_use_tree.syntax().parent()?; let use_tree_list_node = single_use_tree.syntax().parent()?;
if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { if single_use_tree.path()?.segment()?.self_token().is_some() {
let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
let end = use_tree_list_node.text_range().end(); let end = use_tree_list_node.text_range().end();
return Some(TextEdit::delete(TextRange::new(start, end))); return Some(TextEdit::delete(TextRange::new(start, end)));

View File

@ -400,24 +400,33 @@ impl TryToNav for hir::GenericParam {
impl ToNav for hir::Local { impl ToNav for hir::Local {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let src = self.source(db); let src = self.source(db);
let node = match &src.value { let (node, focus_range) = match &src.value {
Either::Left(bind_pat) => { Either::Left(bind_pat) => (
bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone()) bind_pat.syntax().clone(),
} bind_pat
Either::Right(it) => it.syntax().clone(), .name()
.map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range),
),
Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())),
}; };
let full_range = src.with_value(&node).original_file_range(db); let full_range = src.with_value(&node).original_file_range(db);
let name = match self.name(db) { let name = match self.name(db) {
Some(it) => it.to_string().into(), Some(it) => it.to_string().into(),
None => "".into(), None => "".into(),
}; };
let kind = if self.is_param(db) { SymbolKind::ValueParam } else { SymbolKind::Local }; let kind = if self.is_self(db) {
SymbolKind::SelfParam
} else if self.is_param(db) {
SymbolKind::ValueParam
} else {
SymbolKind::Local
};
NavigationTarget { NavigationTarget {
file_id: full_range.file_id, file_id: full_range.file_id,
name, name,
kind: Some(kind), kind: Some(kind),
full_range: full_range.range, full_range: full_range.range,
focus_range: None, focus_range,
container_name: None, container_name: None,
description: None, description: None,
docs: None, docs: None,

View File

@ -1,7 +1,6 @@
use either::Either; use either::Either;
use hir::{HasAttrs, ModuleDef, Semantics}; use hir::{HasAttrs, ModuleDef, Semantics};
use ide_db::{ use ide_db::{
base_db::FileId,
defs::{Definition, NameClass, NameRefClass}, defs::{Definition, NameClass, NameRefClass},
symbol_index, RootDatabase, symbol_index, RootDatabase,
}; };
@ -13,7 +12,7 @@ use crate::{
display::{ToNav, TryToNav}, display::{ToNav, TryToNav},
doc_links::extract_definitions_from_markdown, doc_links::extract_definitions_from_markdown,
runnables::doc_owner_to_def, runnables::doc_owner_to_def,
FilePosition, NavigationTarget, RangeInfo, SymbolKind, FilePosition, NavigationTarget, RangeInfo,
}; };
// Feature: Go to Definition // Feature: Go to Definition
@ -49,19 +48,6 @@ pub(crate) fn goto_definition(
let nav = def.try_to_nav(sema.db)?; let nav = def.try_to_nav(sema.db)?;
vec![nav] vec![nav]
}, },
ast::SelfParam(self_param) => {
vec![self_to_nav_target(self_param, position.file_id)?]
},
ast::PathSegment(segment) => {
segment.self_token()?;
let path = segment.parent_path();
if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
return None;
}
let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?;
let self_param = func.param_list()?.self_param()?;
vec![self_to_nav_target(self_param, position.file_id)?]
},
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
let def = name_class.referenced_or_defined(sema.db); let def = name_class.referenced_or_defined(sema.db);
let nav = def.try_to_nav(sema.db)?; let nav = def.try_to_nav(sema.db)?;
@ -69,6 +55,11 @@ pub(crate) fn goto_definition(
} else { } else {
reference_definition(&sema, Either::Left(&lt)).to_vec() reference_definition(&sema, Either::Left(&lt)).to_vec()
}, },
ast::SelfParam(self_param) => {
let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
let nav = def.try_to_nav(sema.db)?;
vec![nav]
},
_ => return None, _ => return None,
} }
}; };
@ -134,20 +125,6 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
} }
} }
fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> {
let self_token = self_param.self_token()?;
Some(NavigationTarget {
file_id,
full_range: self_param.syntax().text_range(),
focus_range: Some(self_token.text_range()),
name: self_token.text().clone(),
kind: Some(SymbolKind::SelfParam),
container_name: None,
description: None,
docs: None,
})
}
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum ReferenceResult { pub(crate) enum ReferenceResult {
Exact(NavigationTarget), Exact(NavigationTarget),

View File

@ -98,6 +98,7 @@ pub(crate) fn hover(
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
.map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)),
_ => None, _ => None,
} }
}; };
@ -134,17 +135,14 @@ pub(crate) fn hover(
return None; return None;
} }
let node = token.ancestors().find(|n| { let node = token
ast::Expr::can_cast(n.kind()) .ancestors()
|| ast::Pat::can_cast(n.kind()) .find(|n| ast::Expr::can_cast(n.kind()) || ast::Pat::can_cast(n.kind()))?;
|| ast::SelfParam::can_cast(n.kind())
})?;
let ty = match_ast! { let ty = match_ast! {
match node { match node {
ast::Expr(it) => sema.type_of_expr(&it)?, ast::Expr(it) => sema.type_of_expr(&it)?,
ast::Pat(it) => sema.type_of_pat(&it)?, ast::Pat(it) => sema.type_of_pat(&it)?,
ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
// If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
// (e.g expanding a builtin macro). So we give up here. // (e.g expanding a builtin macro). So we give up here.
ast::MacroCall(_it) => return None, ast::MacroCall(_it) => return None,
@ -386,7 +384,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
return tokens.max_by_key(priority); return tokens.max_by_key(priority);
fn priority(n: &SyntaxToken) -> usize { fn priority(n: &SyntaxToken) -> usize {
match n.kind() { match n.kind() {
IDENT | INT_NUMBER | LIFETIME_IDENT => 3, IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] => 3,
T!['('] | T![')'] => 2, T!['('] | T![')'] => 2,
kind if kind.is_trivia() => 0, kind if kind.is_trivia() => 0,
_ => 1, _ => 1,
@ -3129,6 +3127,39 @@ fn foo<T: Foo>(t: T$0){}
); );
} }
#[test]
fn test_hover_self_has_go_to_type() {
check_actions(
r#"
struct Foo;
impl Foo {
fn foo(&self$0) {}
}
"#,
expect![[r#"
[
GoToType(
[
HoverGotoTypeData {
mod_path: "test::Foo",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 0..11,
focus_range: 7..10,
name: "Foo",
kind: Struct,
description: "struct Foo",
},
},
],
),
]
"#]],
);
}
#[test] #[test]
fn hover_displays_normalized_crate_names() { fn hover_displays_normalized_crate_names() {
check( check(
@ -3193,6 +3224,7 @@ impl Foo {
"#, "#,
expect![[r#" expect![[r#"
*&self* *&self*
```rust ```rust
&Foo &Foo
``` ```
@ -3212,6 +3244,7 @@ impl Foo {
"#, "#,
expect![[r#" expect![[r#"
*self: Arc<Foo>* *self: Arc<Foo>*
```rust ```rust
Arc<Foo> Arc<Foo>
``` ```

View File

@ -11,6 +11,7 @@
pub(crate) mod rename; pub(crate) mod rename;
use either::Either;
use hir::Semantics; use hir::Semantics;
use ide_db::{ use ide_db::{
base_db::FileId, base_db::FileId,
@ -21,10 +22,10 @@ use ide_db::{
use syntax::{ use syntax::{
algo::find_node_at_offset, algo::find_node_at_offset,
ast::{self, NameOwner}, ast::{self, NameOwner},
match_ast, AstNode, SyntaxNode, TextRange, TokenAtOffset, T, AstNode, SyntaxNode, TextRange, TokenAtOffset, T,
}; };
use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ReferenceSearchResult { pub struct ReferenceSearchResult {
@ -90,10 +91,6 @@ pub(crate) fn find_all_refs(
let _p = profile::span("find_all_refs"); let _p = profile::span("find_all_refs");
let syntax = sema.parse(position.file_id).syntax().clone(); let syntax = sema.parse(position.file_id).syntax().clone();
if let Some(res) = try_find_self_references(&syntax, position) {
return Some(res);
}
let (opt_name, search_kind) = if let Some(name) = let (opt_name, search_kind) = if let Some(name) =
get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
{ {
@ -122,13 +119,16 @@ pub(crate) fn find_all_refs(
let mut kind = ReferenceKind::Other; let mut kind = ReferenceKind::Other;
if let Definition::Local(local) = def { if let Definition::Local(local) = def {
if let either::Either::Left(pat) = local.source(sema.db).value { match local.source(sema.db).value {
if matches!( Either::Left(pat) => {
pat.syntax().parent().and_then(ast::RecordPatField::cast), if matches!(
Some(pat_field) if pat_field.name_ref().is_none() pat.syntax().parent().and_then(ast::RecordPatField::cast),
) { Some(pat_field) if pat_field.name_ref().is_none()
kind = ReferenceKind::FieldShorthandForLocal; ) {
kind = ReferenceKind::FieldShorthandForLocal;
}
} }
Either::Right(_) => kind = ReferenceKind::SelfParam,
} }
} else if matches!( } else if matches!(
def, def,
@ -251,79 +251,6 @@ fn get_enum_def_name_for_struct_literal_search(
None None
} }
fn try_find_self_references(
syntax: &SyntaxNode,
position: FilePosition,
) -> Option<RangeInfo<ReferenceSearchResult>> {
let FilePosition { file_id, offset } = position;
let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?;
let parent = self_token.parent();
match_ast! {
match parent {
ast::SelfParam(it) => (),
ast::PathSegment(segment) => {
segment.self_token()?;
let path = segment.parent_path();
if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
return None;
}
},
_ => return None,
}
};
let function = parent.ancestors().find_map(ast::Fn::cast)?;
let self_param = function.param_list()?.self_param()?;
let param_self_token = self_param.self_token()?;
let declaration = Declaration {
nav: NavigationTarget {
file_id,
full_range: self_param.syntax().text_range(),
focus_range: Some(param_self_token.text_range()),
name: param_self_token.text().clone(),
kind: Some(SymbolKind::SelfParam),
container_name: None,
description: None,
docs: None,
},
kind: ReferenceKind::SelfKw,
access: Some(if self_param.mut_token().is_some() {
ReferenceAccess::Write
} else {
ReferenceAccess::Read
}),
};
let refs = function
.body()
.map(|body| {
body.syntax()
.descendants()
.filter_map(ast::PathExpr::cast)
.filter_map(|expr| {
let path = expr.path()?;
if path.qualifier().is_none() {
path.segment()?.self_token()
} else {
None
}
})
.map(|token| FileReference {
range: token.text_range(),
kind: ReferenceKind::SelfKw,
access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration
})
.collect()
})
.unwrap_or_default();
let mut references = UsageSearchResult::default();
references.references.insert(file_id, refs);
Some(RangeInfo::new(
param_self_token.text_range(),
ReferenceSearchResult { declaration, references },
))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use expect_test::{expect, Expect}; use expect_test::{expect, Expect};
@ -512,7 +439,7 @@ fn main() {
i = 5; i = 5;
}"#, }"#,
expect![[r#" expect![[r#"
i Local FileId(0) 24..25 Other Write i Local FileId(0) 20..25 24..25 Other Write
FileId(0) 50..51 Other Write FileId(0) 50..51 Other Write
FileId(0) 54..55 Other Read FileId(0) 54..55 Other Read
@ -536,7 +463,7 @@ fn bar() {
} }
"#, "#,
expect![[r#" expect![[r#"
spam Local FileId(0) 19..23 Other spam Local FileId(0) 19..23 19..23 Other
FileId(0) 34..38 Other Read FileId(0) 34..38 Other Read
FileId(0) 41..45 Other Read FileId(0) 41..45 Other Read
@ -551,7 +478,7 @@ fn bar() {
fn foo(i : u32) -> u32 { i$0 } fn foo(i : u32) -> u32 { i$0 }
"#, "#,
expect![[r#" expect![[r#"
i ValueParam FileId(0) 7..8 Other i ValueParam FileId(0) 7..8 7..8 Other
FileId(0) 25..26 Other Read FileId(0) 25..26 Other Read
"#]], "#]],
@ -565,7 +492,7 @@ fn foo(i : u32) -> u32 { i$0 }
fn foo(i$0 : u32) -> u32 { i } fn foo(i$0 : u32) -> u32 { i }
"#, "#,
expect![[r#" expect![[r#"
i ValueParam FileId(0) 7..8 Other i ValueParam FileId(0) 7..8 7..8 Other
FileId(0) 25..26 Other Read FileId(0) 25..26 Other Read
"#]], "#]],
@ -813,7 +740,7 @@ fn foo() {
} }
"#, "#,
expect![[r#" expect![[r#"
i Local FileId(0) 23..24 Other Write i Local FileId(0) 19..24 23..24 Other Write
FileId(0) 34..35 Other Write FileId(0) 34..35 Other Write
FileId(0) 38..39 Other Read FileId(0) 38..39 Other Read
@ -853,7 +780,7 @@ fn foo() {
} }
"#, "#,
expect![[r#" expect![[r#"
i Local FileId(0) 19..20 Other i Local FileId(0) 19..20 19..20 Other
FileId(0) 26..27 Other Write FileId(0) 26..27 Other Write
"#]], "#]],
@ -995,10 +922,10 @@ impl Foo {
} }
"#, "#,
expect![[r#" expect![[r#"
self SelfParam FileId(0) 47..51 47..51 SelfKw Read self SelfParam FileId(0) 47..51 47..51 SelfParam
FileId(0) 71..75 SelfKw Read FileId(0) 71..75 Other Read
FileId(0) 152..156 SelfKw Read FileId(0) 152..156 Other Read
"#]], "#]],
); );
} }
@ -1105,7 +1032,7 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
a Local FileId(0) 59..60 Other a Local FileId(0) 59..60 59..60 Other
FileId(0) 80..81 Other Read FileId(0) 80..81 Other Read
"#]], "#]],
@ -1123,7 +1050,7 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
a Local FileId(0) 59..60 Other a Local FileId(0) 59..60 59..60 Other
FileId(0) 80..81 Other Read FileId(0) 80..81 Other Read
"#]], "#]],

View File

@ -444,7 +444,7 @@ fn rename_reference(
mark::hit!(rename_not_an_ident_ref); mark::hit!(rename_not_an_ident_ref);
bail!("Invalid name `{}`: not an identifier", new_name) bail!("Invalid name `{}`: not an identifier", new_name)
} }
(IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { (IdentifierKind::ToSelf, ReferenceKind::SelfParam) => {
unreachable!("rename_self_to_param should've been called instead") unreachable!("rename_self_to_param should've been called instead")
} }
(IdentifierKind::ToSelf, _) => { (IdentifierKind::ToSelf, _) => {

View File

@ -226,35 +226,16 @@ pub(super) fn element(
T![unsafe] => h | HlMod::Unsafe, T![unsafe] => h | HlMod::Unsafe,
T![true] | T![false] => HlTag::BoolLiteral.into(), T![true] | T![false] => HlTag::BoolLiteral.into(),
T![self] => { T![self] => {
let self_param_is_mut = element let self_param = element.parent().and_then(ast::SelfParam::cast);
.parent() if let Some(NameClass::Definition(def)) = self_param
.and_then(ast::SelfParam::cast) .and_then(|self_param| NameClass::classify_self_param(sema, &self_param))
.and_then(|p| p.mut_token())
.is_some();
let self_path = &element
.parent()
.as_ref()
.and_then(SyntaxNode::parent)
.and_then(ast::Path::cast)
.and_then(|p| sema.resolve_path(&p));
let mut h = HlTag::Symbol(SymbolKind::SelfParam).into();
if self_param_is_mut
|| matches!(self_path,
Some(hir::PathResolution::Local(local))
if local.is_self(db)
&& (local.is_mut(db) || local.ty(db).is_mutable_reference())
)
{ {
h |= HlMod::Mutable highlight_def(db, def) | HlMod::Definition
} else if element.ancestors().any(|it| it.kind() == USE_TREE) {
HlTag::Symbol(SymbolKind::SelfParam).into()
} else {
return None;
} }
if let Some(hir::PathResolution::Local(local)) = self_path {
if is_consumed_lvalue(element, &local, db) {
h |= HlMod::Consuming;
}
}
h
} }
T![ref] => element T![ref] => element
.parent() .parent()
@ -345,7 +326,9 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam), hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam),
}, },
Definition::Local(local) => { Definition::Local(local) => {
let tag = if local.is_param(db) { let tag = if local.is_self(db) {
HlTag::Symbol(SymbolKind::SelfParam)
} else if local.is_param(db) {
HlTag::Symbol(SymbolKind::ValueParam) HlTag::Symbol(SymbolKind::ValueParam)
} else { } else {
HlTag::Symbol(SymbolKind::Local) HlTag::Symbol(SymbolKind::Local)

View File

@ -42,16 +42,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
</code></pre> </code></pre>

View File

@ -93,7 +93,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="comment documentation">/// ```sh</span> <span class="comment documentation">/// ```sh</span>
<span class="comment documentation">/// echo 1</span> <span class="comment documentation">/// echo 1</span>
<span class="comment documentation">/// ```</span> <span class="comment documentation">/// ```</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
<span class="bool_literal">true</span> <span class="bool_literal">true</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>

View File

@ -46,7 +46,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span>
<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span>
<span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span>
@ -61,11 +61,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>

View File

@ -66,25 +66,25 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
<span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span> <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
@ -95,15 +95,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
<span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
@ -213,7 +213,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
<span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
<span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
<span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span> <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>

View File

@ -10,7 +10,7 @@ use hir::{
Module, ModuleDef, Name, PathResolution, Semantics, Visibility, Module, ModuleDef, Name, PathResolution, Semantics, Visibility,
}; };
use syntax::{ use syntax::{
ast::{self, AstNode}, ast::{self, AstNode, PathSegmentKind},
match_ast, SyntaxKind, SyntaxNode, match_ast, SyntaxKind, SyntaxNode,
}; };
@ -117,6 +117,13 @@ impl NameClass {
} }
} }
pub fn classify_self_param(
sema: &Semantics<RootDatabase>,
self_param: &ast::SelfParam,
) -> Option<NameClass> {
sema.to_def(self_param).map(Definition::Local).map(NameClass::Definition)
}
pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
let _p = profile::span("classify_name"); let _p = profile::span("classify_name");
@ -135,24 +142,26 @@ impl NameClass {
let path = use_tree.path()?; let path = use_tree.path()?;
let path_segment = path.segment()?; let path_segment = path.segment()?;
let name_ref_class = path_segment let name_ref_class = path_segment
.name_ref() .kind()
// The rename might be from a `self` token, so fallback to the name higher .and_then(|kind| {
// in the use tree. match kind {
.or_else(||{ // The rename might be from a `self` token, so fallback to the name higher
if path_segment.self_token().is_none() { // in the use tree.
return None; PathSegmentKind::SelfKw => {
let use_tree = use_tree
.syntax()
.parent()
.as_ref()
// Skip over UseTreeList
.and_then(SyntaxNode::parent)
.and_then(ast::UseTree::cast)?;
let path = use_tree.path()?;
let path_segment = path.segment()?;
path_segment.name_ref()
},
PathSegmentKind::Name(name_ref) => Some(name_ref),
_ => return None,
} }
let use_tree = use_tree
.syntax()
.parent()
.as_ref()
// Skip over UseTreeList
.and_then(SyntaxNode::parent)
.and_then(ast::UseTree::cast)?;
let path = use_tree.path()?;
let path_segment = path.segment()?;
path_segment.name_ref()
}) })
.and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?; .and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;

View File

@ -444,8 +444,14 @@ fn use_tree_path_cmp(a: &ast::Path, a_has_tl: bool, b: &ast::Path, b_has_tl: boo
} }
fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering {
let a = a.name_ref(); let a = a.kind().and_then(|kind| match kind {
let b = b.name_ref(); PathSegmentKind::Name(name_ref) => Some(name_ref),
_ => None,
});
let b = b.kind().and_then(|kind| match kind {
PathSegmentKind::Name(name_ref) => Some(name_ref),
_ => None,
});
a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text)) a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text))
} }

View File

@ -65,7 +65,7 @@ pub enum ReferenceKind {
FieldShorthandForLocal, FieldShorthandForLocal,
StructLiteral, StructLiteral,
RecordFieldExprOrPat, RecordFieldExprOrPat,
SelfKw, SelfParam,
EnumLiteral, EnumLiteral,
Lifetime, Lifetime,
Other, Other,

View File

@ -82,7 +82,11 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
} }
// test crate_path // test crate_path
// use crate::foo; // use crate::foo;
T![self] | T![super] | T![crate] => p.bump_any(), T![self] | T![super] | T![crate] => {
let m = p.start();
p.bump_any();
m.complete(p, NAME_REF);
}
_ => { _ => {
p.err_recover("expected identifier", items::ITEM_RECOVERY_SET); p.err_recover("expected identifier", items::ITEM_RECOVERY_SET);
if empty { if empty {

View File

@ -883,7 +883,7 @@ use crate::AstNode;
replacements: replacements:
Line 2: Node(NAME_REF@5..14) -> crate Line 2: Token(IDENT@5..14 "text_edit") -> crate
Line 2: Token(IDENT@16..24 "TextEdit") -> AstNode Line 2: Token(IDENT@16..24 "TextEdit") -> AstNode
Line 2: Token(WHITESPACE@25..27 "\n\n") -> "\n" Line 2: Token(WHITESPACE@25..27 "\n\n") -> "\n"

View File

@ -18,6 +18,9 @@ pub struct NameRef {
} }
impl NameRef { impl NameRef {
pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Lifetime { pub struct Lifetime {
@ -42,9 +45,6 @@ pub struct PathSegment {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl PathSegment { impl PathSegment {
pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) } pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }

View File

@ -156,14 +156,28 @@ impl ast::PathSegment {
.expect("segments are always nested in paths") .expect("segments are always nested in paths")
} }
pub fn crate_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.crate_token())
}
pub fn self_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.self_token())
}
pub fn super_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.super_token())
}
pub fn kind(&self) -> Option<PathSegmentKind> { pub fn kind(&self) -> Option<PathSegmentKind> {
let res = if let Some(name_ref) = self.name_ref() { let res = if let Some(name_ref) = self.name_ref() {
PathSegmentKind::Name(name_ref) match name_ref.syntax().first_token().map(|it| it.kind()) {
Some(T![self]) => PathSegmentKind::SelfKw,
Some(T![super]) => PathSegmentKind::SuperKw,
Some(T![crate]) => PathSegmentKind::CrateKw,
_ => PathSegmentKind::Name(name_ref),
}
} else { } else {
match self.syntax().first_child_or_token()?.kind() { match self.syntax().first_child_or_token()?.kind() {
T![self] => PathSegmentKind::SelfKw,
T![super] => PathSegmentKind::SuperKw,
T![crate] => PathSegmentKind::CrateKw,
T![<] => { T![<] => {
// <T> or <T as Trait> // <T> or <T as Trait>
// T is any TypeRef, Trait has to be a PathType // T is any TypeRef, Trait has to be a PathType

View File

@ -256,7 +256,7 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
)); ));
} }
} else if let Some(token) = segment.super_token() { } else if let Some(token) = segment.super_token() {
if !all_supers(&path) { if segment.coloncolon_token().is_some() || !all_supers(&path) {
errors.push(SyntaxError::new( errors.push(SyntaxError::new(
"The `super` keyword may only be preceded by other `super`s", "The `super` keyword may only be preceded by other `super`s",
token.text_range(), token.text_range(),

View File

@ -49,7 +49,8 @@ SOURCE_FILE@0..183
PATH_EXPR@67..71 PATH_EXPR@67..71
PATH@67..71 PATH@67..71
PATH_SEGMENT@67..71 PATH_SEGMENT@67..71
SELF_KW@67..71 "self" NAME_REF@67..71
SELF_KW@67..71 "self"
DOT@71..72 "." DOT@71..72 "."
NAME_REF@72..78 NAME_REF@72..78
IDENT@72..78 "scopes" IDENT@72..78 "scopes"
@ -66,7 +67,8 @@ SOURCE_FILE@0..183
PATH_EXPR@94..98 PATH_EXPR@94..98
PATH@94..98 PATH@94..98
PATH_SEGMENT@94..98 PATH_SEGMENT@94..98
SELF_KW@94..98 "self" NAME_REF@94..98
SELF_KW@94..98 "self"
DOT@98..99 "." DOT@98..99 "."
NAME_REF@99..105 NAME_REF@99..105
IDENT@99..105 "scopes" IDENT@99..105 "scopes"

View File

@ -24,7 +24,8 @@ SOURCE_FILE@0..48
PATH@22..32 PATH@22..32
PATH@22..27 PATH@22..27
PATH_SEGMENT@22..27 PATH_SEGMENT@22..27
CRATE_KW@22..27 "crate" NAME_REF@22..27
CRATE_KW@22..27 "crate"
COLON2@27..29 "::" COLON2@27..29 "::"
PATH_SEGMENT@29..32 PATH_SEGMENT@29..32
NAME_REF@29..32 NAME_REF@29..32

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..98
PATH@4..11 PATH@4..11
PATH_SEGMENT@4..11 PATH_SEGMENT@4..11
COLON2@4..6 "::" COLON2@4..6 "::"
CRATE_KW@6..11 "crate" NAME_REF@6..11
CRATE_KW@6..11 "crate"
SEMICOLON@11..12 ";" SEMICOLON@11..12 ";"
WHITESPACE@12..13 "\n" WHITESPACE@12..13 "\n"
USE@13..54 USE@13..54
@ -18,7 +19,8 @@ SOURCE_FILE@0..98
USE_TREE@18..23 USE_TREE@18..23
PATH@18..23 PATH@18..23
PATH_SEGMENT@18..23 PATH_SEGMENT@18..23
CRATE_KW@18..23 "crate" NAME_REF@18..23
CRATE_KW@18..23 "crate"
COMMA@23..24 "," COMMA@23..24 ","
WHITESPACE@24..25 " " WHITESPACE@24..25 " "
USE_TREE@25..52 USE_TREE@25..52
@ -35,7 +37,8 @@ SOURCE_FILE@0..98
PATH@31..41 PATH@31..41
PATH@31..36 PATH@31..36
PATH_SEGMENT@31..36 PATH_SEGMENT@31..36
CRATE_KW@31..36 "crate" NAME_REF@31..36
CRATE_KW@31..36 "crate"
COLON2@36..38 "::" COLON2@36..38 "::"
PATH_SEGMENT@38..41 PATH_SEGMENT@38..41
NAME_REF@38..41 NAME_REF@38..41
@ -63,7 +66,8 @@ SOURCE_FILE@0..98
IDENT@59..64 "hello" IDENT@59..64 "hello"
COLON2@64..66 "::" COLON2@64..66 "::"
PATH_SEGMENT@66..71 PATH_SEGMENT@66..71
CRATE_KW@66..71 "crate" NAME_REF@66..71
CRATE_KW@66..71 "crate"
SEMICOLON@71..72 ";" SEMICOLON@71..72 ";"
WHITESPACE@72..73 "\n" WHITESPACE@72..73 "\n"
USE@73..97 USE@73..97
@ -78,7 +82,8 @@ SOURCE_FILE@0..98
IDENT@77..82 "hello" IDENT@77..82 "hello"
COLON2@82..84 "::" COLON2@82..84 "::"
PATH_SEGMENT@84..89 PATH_SEGMENT@84..89
CRATE_KW@84..89 "crate" NAME_REF@84..89
CRATE_KW@84..89 "crate"
COLON2@89..91 "::" COLON2@89..91 "::"
PATH_SEGMENT@91..96 PATH_SEGMENT@91..96
NAME_REF@91..96 NAME_REF@91..96

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..67
PATH@4..11 PATH@4..11
PATH_SEGMENT@4..11 PATH_SEGMENT@4..11
COLON2@4..6 "::" COLON2@4..6 "::"
SUPER_KW@6..11 "super" NAME_REF@6..11
SUPER_KW@6..11 "super"
SEMICOLON@11..12 ";" SEMICOLON@11..12 ";"
WHITESPACE@12..13 "\n" WHITESPACE@12..13 "\n"
USE@13..26 USE@13..26
@ -20,7 +21,8 @@ SOURCE_FILE@0..67
IDENT@17..18 "a" IDENT@17..18 "a"
COLON2@18..20 "::" COLON2@18..20 "::"
PATH_SEGMENT@20..25 PATH_SEGMENT@20..25
SUPER_KW@20..25 "super" NAME_REF@20..25
SUPER_KW@20..25 "super"
SEMICOLON@25..26 ";" SEMICOLON@25..26 ";"
WHITESPACE@26..27 "\n" WHITESPACE@26..27 "\n"
USE@27..47 USE@27..47
@ -31,14 +33,16 @@ SOURCE_FILE@0..67
PATH@31..39 PATH@31..39
PATH@31..36 PATH@31..36
PATH_SEGMENT@31..36 PATH_SEGMENT@31..36
SUPER_KW@31..36 "super" NAME_REF@31..36
SUPER_KW@31..36 "super"
COLON2@36..38 "::" COLON2@36..38 "::"
PATH_SEGMENT@38..39 PATH_SEGMENT@38..39
NAME_REF@38..39 NAME_REF@38..39
IDENT@38..39 "a" IDENT@38..39 "a"
COLON2@39..41 "::" COLON2@39..41 "::"
PATH_SEGMENT@41..46 PATH_SEGMENT@41..46
SUPER_KW@41..46 "super" NAME_REF@41..46
SUPER_KW@41..46 "super"
SEMICOLON@46..47 ";" SEMICOLON@46..47 ";"
WHITESPACE@47..48 "\n" WHITESPACE@47..48 "\n"
USE@48..66 USE@48..66
@ -56,7 +60,8 @@ SOURCE_FILE@0..67
PATH@56..64 PATH@56..64
PATH@56..61 PATH@56..61
PATH_SEGMENT@56..61 PATH_SEGMENT@56..61
SUPER_KW@56..61 "super" NAME_REF@56..61
SUPER_KW@56..61 "super"
COLON2@61..63 "::" COLON2@61..63 "::"
PATH_SEGMENT@63..64 PATH_SEGMENT@63..64
NAME_REF@63..64 NAME_REF@63..64

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..25
PATH@4..10 PATH@4..10
PATH_SEGMENT@4..10 PATH_SEGMENT@4..10
COLON2@4..6 "::" COLON2@4..6 "::"
SELF_KW@6..10 "self" NAME_REF@6..10
SELF_KW@6..10 "self"
SEMICOLON@10..11 ";" SEMICOLON@10..11 ";"
WHITESPACE@11..12 "\n" WHITESPACE@11..12 "\n"
USE@12..24 USE@12..24
@ -20,7 +21,8 @@ SOURCE_FILE@0..25
IDENT@16..17 "a" IDENT@16..17 "a"
COLON2@17..19 "::" COLON2@17..19 "::"
PATH_SEGMENT@19..23 PATH_SEGMENT@19..23
SELF_KW@19..23 "self" NAME_REF@19..23
SELF_KW@19..23 "self"
SEMICOLON@23..24 ";" SEMICOLON@23..24 ";"
WHITESPACE@24..25 "\n" WHITESPACE@24..25 "\n"
error 6..10: The `self` keyword is only allowed as the first segment of a path error 6..10: The `self` keyword is only allowed as the first segment of a path

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..13
PATH@4..11 PATH@4..11
PATH@4..9 PATH@4..9
PATH_SEGMENT@4..9 PATH_SEGMENT@4..9
CRATE_KW@4..9 "crate" NAME_REF@4..9
CRATE_KW@4..9 "crate"
COLON2@9..11 "::" COLON2@9..11 "::"
SEMICOLON@11..12 ";" SEMICOLON@11..12 ";"
WHITESPACE@12..13 "\n" WHITESPACE@12..13 "\n"

View File

@ -11,7 +11,8 @@ SOURCE_FILE@0..248
PATH@5..16 PATH@5..16
PATH@5..10 PATH@5..10
PATH_SEGMENT@5..10 PATH_SEGMENT@5..10
CRATE_KW@5..10 "crate" NAME_REF@5..10
CRATE_KW@5..10 "crate"
COLON2@10..12 "::" COLON2@10..12 "::"
PATH_SEGMENT@12..16 PATH_SEGMENT@12..16
NAME_REF@12..16 NAME_REF@12..16

View File

@ -42,7 +42,8 @@ SOURCE_FILE@0..71
PATH@39..48 PATH@39..48
PATH@39..43 PATH@39..43
PATH_SEGMENT@39..43 PATH_SEGMENT@39..43
SELF_KW@39..43 "self" NAME_REF@39..43
SELF_KW@39..43 "self"
COLON2@43..45 "::" COLON2@43..45 "::"
PATH_SEGMENT@45..48 PATH_SEGMENT@45..48
NAME_REF@45..48 NAME_REF@45..48
@ -61,7 +62,8 @@ SOURCE_FILE@0..71
PATH@59..69 PATH@59..69
PATH@59..64 PATH@59..64
PATH_SEGMENT@59..64 PATH_SEGMENT@59..64
SUPER_KW@59..64 "super" NAME_REF@59..64
SUPER_KW@59..64 "super"
COLON2@64..66 "::" COLON2@64..66 "::"
PATH_SEGMENT@66..69 PATH_SEGMENT@66..69
NAME_REF@66..69 NAME_REF@66..69

View File

@ -43,7 +43,8 @@ SOURCE_FILE@0..70
PATH@45..55 PATH@45..55
PATH@45..50 PATH@45..50
PATH_SEGMENT@45..50 PATH_SEGMENT@45..50
SUPER_KW@45..50 "super" NAME_REF@45..50
SUPER_KW@45..50 "super"
COLON2@50..52 "::" COLON2@50..52 "::"
PATH_SEGMENT@52..55 PATH_SEGMENT@52..55
NAME_REF@52..55 NAME_REF@52..55

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..16
PATH@4..14 PATH@4..14
PATH@4..9 PATH@4..9
PATH_SEGMENT@4..9 PATH_SEGMENT@4..9
CRATE_KW@4..9 "crate" NAME_REF@4..9
CRATE_KW@4..9 "crate"
COLON2@9..11 "::" COLON2@9..11 "::"
PATH_SEGMENT@11..14 PATH_SEGMENT@11..14
NAME_REF@11..14 NAME_REF@11..14

View File

@ -5,7 +5,8 @@ SOURCE_FILE@0..37
USE_TREE@4..17 USE_TREE@4..17
PATH@4..9 PATH@4..9
PATH_SEGMENT@4..9 PATH_SEGMENT@4..9
CRATE_KW@4..9 "crate" NAME_REF@4..9
CRATE_KW@4..9 "crate"
COLON2@9..11 "::" COLON2@9..11 "::"
USE_TREE_LIST@11..17 USE_TREE_LIST@11..17
L_CURLY@11..12 "{" L_CURLY@11..12 "{"
@ -23,7 +24,8 @@ SOURCE_FILE@0..37
USE_TREE@23..35 USE_TREE@23..35
PATH@23..27 PATH@23..27
PATH_SEGMENT@23..27 PATH_SEGMENT@23..27
SELF_KW@23..27 "self" NAME_REF@23..27
SELF_KW@23..27 "self"
COLON2@27..29 "::" COLON2@27..29 "::"
USE_TREE_LIST@29..35 USE_TREE_LIST@29..35
L_CURLY@29..30 "{" L_CURLY@29..30 "{"

View File

@ -30,7 +30,8 @@ SOURCE_FILE@0..41
PATH@26..36 PATH@26..36
PATH@26..31 PATH@26..31
PATH_SEGMENT@26..31 PATH_SEGMENT@26..31
CRATE_KW@26..31 "crate" NAME_REF@26..31
CRATE_KW@26..31 "crate"
COLON2@31..33 "::" COLON2@31..33 "::"
PATH_SEGMENT@33..36 PATH_SEGMENT@33..36
NAME_REF@33..36 NAME_REF@33..36

View File

@ -17,7 +17,8 @@ SOURCE_FILE@0..27
PATH@11..21 PATH@11..21
PATH@11..16 PATH@11..16
PATH_SEGMENT@11..16 PATH_SEGMENT@11..16
CRATE_KW@11..16 "crate" NAME_REF@11..16
CRATE_KW@11..16 "crate"
COLON2@16..18 "::" COLON2@16..18 "::"
PATH_SEGMENT@18..21 PATH_SEGMENT@18..21
NAME_REF@18..21 NAME_REF@18..21

View File

@ -16,7 +16,8 @@ SOURCE_FILE@0..53
PATH@14..22 PATH@14..22
PATH@14..19 PATH@14..19
PATH_SEGMENT@14..19 PATH_SEGMENT@14..19
SUPER_KW@14..19 "super" NAME_REF@14..19
SUPER_KW@14..19 "super"
COLON2@19..21 "::" COLON2@19..21 "::"
PATH_SEGMENT@21..22 PATH_SEGMENT@21..22
NAME_REF@21..22 NAME_REF@21..22
@ -42,7 +43,8 @@ SOURCE_FILE@0..53
PATH@40..48 PATH@40..48
PATH@40..45 PATH@40..45
PATH_SEGMENT@40..45 PATH_SEGMENT@40..45
CRATE_KW@40..45 "crate" NAME_REF@40..45
CRATE_KW@40..45 "crate"
COLON2@45..47 "::" COLON2@45..47 "::"
PATH_SEGMENT@47..48 PATH_SEGMENT@47..48
NAME_REF@47..48 NAME_REF@47..48

View File

@ -6,7 +6,8 @@ SOURCE_FILE@0..38
PATH@4..13 PATH@4..13
PATH@4..8 PATH@4..8
PATH_SEGMENT@4..8 PATH_SEGMENT@4..8
SELF_KW@4..8 "self" NAME_REF@4..8
SELF_KW@4..8 "self"
COLON2@8..10 "::" COLON2@8..10 "::"
PATH_SEGMENT@10..13 PATH_SEGMENT@10..13
NAME_REF@10..13 NAME_REF@10..13
@ -21,10 +22,12 @@ SOURCE_FILE@0..38
PATH@19..31 PATH@19..31
PATH@19..24 PATH@19..24
PATH_SEGMENT@19..24 PATH_SEGMENT@19..24
SUPER_KW@19..24 "super" NAME_REF@19..24
SUPER_KW@19..24 "super"
COLON2@24..26 "::" COLON2@24..26 "::"
PATH_SEGMENT@26..31 PATH_SEGMENT@26..31
SUPER_KW@26..31 "super" NAME_REF@26..31
SUPER_KW@26..31 "super"
COLON2@31..33 "::" COLON2@31..33 "::"
PATH_SEGMENT@33..36 PATH_SEGMENT@33..36
NAME_REF@33..36 NAME_REF@33..36

View File

@ -187,7 +187,8 @@ SOURCE_FILE@0..250
PATH@164..173 PATH@164..173
PATH@164..168 PATH@164..168
PATH_SEGMENT@164..168 PATH_SEGMENT@164..168
SELF_KW@164..168 "self" NAME_REF@164..168
SELF_KW@164..168 "self"
COLON2@168..170 "::" COLON2@168..170 "::"
PATH_SEGMENT@170..173 PATH_SEGMENT@170..173
NAME_REF@170..173 NAME_REF@170..173

View File

@ -25,7 +25,8 @@ SOURCE_FILE@0..62
PATH@27..44 PATH@27..44
PATH@27..32 PATH@27..32
PATH_SEGMENT@27..32 PATH_SEGMENT@27..32
CRATE_KW@27..32 "crate" NAME_REF@27..32
CRATE_KW@27..32 "crate"
COLON2@32..34 "::" COLON2@32..34 "::"
PATH_SEGMENT@34..44 PATH_SEGMENT@34..44
NAME_REF@34..44 NAME_REF@34..44

View File

@ -15,7 +15,7 @@ flate2 = "1.0"
pico-args = "0.3.1" pico-args = "0.3.1"
proc-macro2 = "1.0.8" proc-macro2 = "1.0.8"
quote = "1.0.2" quote = "1.0.2"
ungrammar = "1.7" ungrammar = "1.8"
walkdir = "2.3.1" walkdir = "2.3.1"
write-json = "0.1.0" write-json = "0.1.0"
xshell = "0.1" xshell = "0.1"