mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Move hir to a separate crate
This commit is contained in:
parent
0e4b710af8
commit
59e29aef63
26 changed files with 202 additions and 2432 deletions
|
@ -8,7 +8,7 @@ use std::{
|
|||
marker::PhantomData,
|
||||
};
|
||||
|
||||
pub(crate) struct Id<T> {
|
||||
pub struct Id<T> {
|
||||
idx: u32,
|
||||
_ty: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ use crate::{
|
|||
DefLoc, DefId, FnId,
|
||||
SourceFileItems, SourceItemId,
|
||||
query_definitions,
|
||||
function::{FnScopes},
|
||||
FnScopes,
|
||||
module::{ModuleId, ModuleTree, ModuleSource,
|
||||
nameres::{ItemMap, InputModuleItems}},
|
||||
};
|
||||
|
||||
salsa::query_group! {
|
||||
|
||||
pub(crate) trait HirDatabase: SyntaxDatabase
|
||||
pub trait HirDatabase: SyntaxDatabase
|
||||
+ AsRef<LocationIntener<DefLoc, DefId>>
|
||||
+ AsRef<LocationIntener<SourceItemId, FnId>>
|
||||
{
|
||||
|
|
|
@ -15,10 +15,10 @@ use crate::{
|
|||
FnId, HirDatabase, SourceItemId,
|
||||
};
|
||||
|
||||
pub(crate) use self::scope::FnScopes;
|
||||
pub use self::scope::FnScopes;
|
||||
|
||||
impl FnId {
|
||||
pub(crate) fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
|
||||
pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
|
||||
let file_items = db.file_items(file_id);
|
||||
let item_id = file_items.id_of(fn_def.syntax());
|
||||
let item_id = SourceItemId { file_id, item_id };
|
||||
|
@ -26,12 +26,12 @@ impl FnId {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Function {
|
||||
pub struct Function {
|
||||
fn_id: FnId,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub(crate) fn guess_from_source(
|
||||
pub fn guess_from_source(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
fn_def: ast::FnDef,
|
||||
|
@ -40,7 +40,7 @@ impl Function {
|
|||
Function { fn_id }
|
||||
}
|
||||
|
||||
pub(crate) fn guess_for_name_ref(
|
||||
pub fn guess_for_name_ref(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
name_ref: ast::NameRef,
|
||||
|
@ -48,7 +48,7 @@ impl Function {
|
|||
Function::guess_for_node(db, file_id, name_ref.syntax())
|
||||
}
|
||||
|
||||
pub(crate) fn guess_for_bind_pat(
|
||||
pub fn guess_for_bind_pat(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
bind_pat: ast::BindPat,
|
||||
|
@ -66,11 +66,11 @@ impl Function {
|
|||
Some(res)
|
||||
}
|
||||
|
||||
pub(crate) fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
|
||||
pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
|
||||
db.fn_scopes(self.fn_id)
|
||||
}
|
||||
|
||||
pub(crate) fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
|
||||
pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
|
||||
let syntax = db.fn_syntax(self.fn_id);
|
||||
FnSignatureInfo::new(syntax.borrowed())
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ pub(crate) type ScopeId = Id<ScopeData>;
|
|||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct FnScopes {
|
||||
pub(crate) self_param: Option<LocalSyntaxPtr>,
|
||||
pub self_param: Option<LocalSyntaxPtr>,
|
||||
scopes: Arena<ScopeData>,
|
||||
scope_for: FxHashMap<LocalSyntaxPtr, ScopeId>,
|
||||
}
|
||||
|
@ -27,13 +27,13 @@ pub struct ScopeEntry {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) struct ScopeData {
|
||||
pub struct ScopeData {
|
||||
parent: Option<ScopeId>,
|
||||
entries: Vec<ScopeEntry>,
|
||||
}
|
||||
|
||||
impl FnScopes {
|
||||
pub(crate) fn new(fn_def: ast::FnDef) -> FnScopes {
|
||||
pub fn new(fn_def: ast::FnDef) -> FnScopes {
|
||||
let mut scopes = FnScopes {
|
||||
self_param: fn_def
|
||||
.param_list()
|
||||
|
@ -49,7 +49,7 @@ impl FnScopes {
|
|||
}
|
||||
scopes
|
||||
}
|
||||
pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
|
||||
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
|
||||
&self.scopes[scope].entries
|
||||
}
|
||||
pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a {
|
||||
|
@ -57,10 +57,7 @@ impl FnScopes {
|
|||
self.scopes[scope].parent
|
||||
})
|
||||
}
|
||||
pub(crate) fn resolve_local_name<'a>(
|
||||
&'a self,
|
||||
name_ref: ast::NameRef,
|
||||
) -> Option<&'a ScopeEntry> {
|
||||
pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> {
|
||||
let mut shadowed = FxHashSet::default();
|
||||
let ret = self
|
||||
.scope_chain(name_ref.syntax())
|
||||
|
@ -138,10 +135,10 @@ impl ScopeEntry {
|
|||
};
|
||||
Some(res)
|
||||
}
|
||||
pub(crate) fn name(&self) -> &SmolStr {
|
||||
pub fn name(&self) -> &SmolStr {
|
||||
&self.name
|
||||
}
|
||||
pub(crate) fn ptr(&self) -> LocalSyntaxPtr {
|
||||
pub fn ptr(&self) -> LocalSyntaxPtr {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ macro_rules! ctry {
|
|||
};
|
||||
}
|
||||
|
||||
pub(crate) mod db;
|
||||
pub mod db;
|
||||
mod query_definitions;
|
||||
mod function;
|
||||
mod module;
|
||||
|
@ -31,36 +31,36 @@ use crate::{
|
|||
arena::{Arena, Id},
|
||||
};
|
||||
|
||||
pub(crate) use self::{
|
||||
pub use self::{
|
||||
path::{Path, PathKind},
|
||||
module::{Module, ModuleId, Problem},
|
||||
module::{Module, ModuleId, Problem, nameres::ItemMap},
|
||||
function::{Function, FnScopes},
|
||||
};
|
||||
|
||||
pub use self::function::FnSignatureInfo;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct FnId(u32);
|
||||
pub struct FnId(u32);
|
||||
ra_db::impl_numeric_id!(FnId);
|
||||
|
||||
impl FnId {
|
||||
pub(crate) fn from_loc(
|
||||
pub fn from_loc(
|
||||
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
|
||||
loc: &SourceItemId,
|
||||
) -> FnId {
|
||||
db.as_ref().loc2id(loc)
|
||||
}
|
||||
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
|
||||
pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
|
||||
db.as_ref().id2loc(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct DefId(u32);
|
||||
pub struct DefId(u32);
|
||||
ra_db::impl_numeric_id!(DefId);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DefLoc {
|
||||
pub enum DefLoc {
|
||||
Module {
|
||||
id: ModuleId,
|
||||
source_root: SourceRootId,
|
||||
|
@ -71,24 +71,24 @@ pub(crate) enum DefLoc {
|
|||
}
|
||||
|
||||
impl DefId {
|
||||
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
|
||||
pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
|
||||
db.as_ref().id2loc(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefLoc {
|
||||
pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
|
||||
pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
|
||||
db.as_ref().loc2id(&self)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum Def {
|
||||
pub enum Def {
|
||||
Module(Module),
|
||||
Item,
|
||||
}
|
||||
|
||||
impl DefId {
|
||||
pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
|
||||
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
|
||||
let loc = self.loc(db);
|
||||
let res = match loc {
|
||||
DefLoc::Module { id, source_root } => {
|
||||
|
@ -106,14 +106,14 @@ impl DefId {
|
|||
pub(crate) type SourceFileItemId = Id<SyntaxNode>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct SourceItemId {
|
||||
pub struct SourceItemId {
|
||||
file_id: FileId,
|
||||
item_id: SourceFileItemId,
|
||||
}
|
||||
|
||||
/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
pub(crate) struct SourceFileItems {
|
||||
pub struct SourceFileItems {
|
||||
arena: Arena<SyntaxNode>,
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ impl SourceFileItems {
|
|||
fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
pub fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
let (id, _item) = self
|
||||
.arena
|
||||
.iter()
|
||||
|
|
|
@ -18,7 +18,7 @@ use super::{
|
|||
};
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
||||
pub(crate) enum Submodule {
|
||||
pub enum Submodule {
|
||||
Declaration(SmolStr),
|
||||
Definition(SmolStr, ModuleSource),
|
||||
}
|
||||
|
|
|
@ -18,15 +18,16 @@ use crate::{
|
|||
arena::{Arena, Id},
|
||||
};
|
||||
|
||||
pub(crate) use self::nameres::ModuleScope;
|
||||
pub use self::nameres::ModuleScope;
|
||||
|
||||
/// `Module` is API entry point to get all the information
|
||||
/// about a particular module.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Module {
|
||||
pub struct Module {
|
||||
tree: Arc<ModuleTree>,
|
||||
source_root_id: SourceRootId,
|
||||
module_id: ModuleId,
|
||||
//TODO: make private
|
||||
pub module_id: ModuleId,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
|
@ -145,17 +146,13 @@ impl Module {
|
|||
}
|
||||
|
||||
/// Returns a `ModuleScope`: a set of items, visible in this module.
|
||||
pub(crate) fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
|
||||
pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
|
||||
let item_map = db.item_map(self.source_root_id)?;
|
||||
let res = item_map.per_module[&self.module_id].clone();
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
path: Path,
|
||||
) -> Cancelable<Option<DefId>> {
|
||||
pub fn resolve_path(&self, db: &impl HirDatabase, path: Path) -> Cancelable<Option<DefId>> {
|
||||
let mut curr = match path.kind {
|
||||
PathKind::Crate => self.crate_root(),
|
||||
PathKind::Self_ | PathKind::Plain => self.clone(),
|
||||
|
@ -188,7 +185,7 @@ impl Module {
|
|||
/// (which can have multiple parents) to the precise world of modules (which
|
||||
/// always have one parent).
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct ModuleTree {
|
||||
pub struct ModuleTree {
|
||||
mods: Arena<ModuleData>,
|
||||
links: Arena<LinkData>,
|
||||
}
|
||||
|
@ -214,19 +211,19 @@ impl ModuleTree {
|
|||
/// `ModuleSource` is the syntax tree element that produced this module:
|
||||
/// either a file, or an inlinde module.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum ModuleSource {
|
||||
pub enum ModuleSource {
|
||||
SourceFile(FileId),
|
||||
Module(SourceItemId),
|
||||
}
|
||||
|
||||
/// An owned syntax node for a module. Unlike `ModuleSource`,
|
||||
/// this holds onto the AST for the whole file.
|
||||
pub(crate) enum ModuleSourceNode {
|
||||
pub enum ModuleSourceNode {
|
||||
SourceFile(ast::SourceFileNode),
|
||||
Module(ast::ModuleNode),
|
||||
}
|
||||
|
||||
pub(crate) type ModuleId = Id<ModuleData>;
|
||||
pub type ModuleId = Id<ModuleData>;
|
||||
type LinkId = Id<LinkData>;
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
|
@ -308,7 +305,7 @@ impl LinkId {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct ModuleData {
|
||||
pub struct ModuleData {
|
||||
source: ModuleSource,
|
||||
parent: Option<LinkId>,
|
||||
children: Vec<LinkId>,
|
||||
|
@ -327,21 +324,21 @@ impl ModuleSource {
|
|||
ModuleSource::Module(id)
|
||||
}
|
||||
|
||||
pub(crate) fn as_file(self) -> Option<FileId> {
|
||||
pub fn as_file(self) -> Option<FileId> {
|
||||
match self {
|
||||
ModuleSource::SourceFile(f) => Some(f),
|
||||
ModuleSource::Module(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_id(self) -> FileId {
|
||||
pub fn file_id(self) -> FileId {
|
||||
match self {
|
||||
ModuleSource::SourceFile(f) => f,
|
||||
ModuleSource::Module(source_item_id) => source_item_id.file_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
|
||||
pub fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
|
||||
match self {
|
||||
ModuleSource::SourceFile(file_id) => {
|
||||
let syntax = db.source_file(file_id);
|
||||
|
|
|
@ -38,20 +38,20 @@ use crate::{
|
|||
/// Item map is the result of the name resolution. Item map contains, for each
|
||||
/// module, the set of visible items.
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct ItemMap {
|
||||
pub(crate) per_module: FxHashMap<ModuleId, ModuleScope>,
|
||||
pub struct ItemMap {
|
||||
pub per_module: FxHashMap<ModuleId, ModuleScope>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
pub(crate) struct ModuleScope {
|
||||
items: FxHashMap<SmolStr, Resolution>,
|
||||
pub struct ModuleScope {
|
||||
pub items: FxHashMap<SmolStr, Resolution>,
|
||||
}
|
||||
|
||||
impl ModuleScope {
|
||||
pub(crate) fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
|
||||
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
|
||||
self.items.iter()
|
||||
}
|
||||
pub(crate) fn get(&self, name: &SmolStr) -> Option<&Resolution> {
|
||||
pub fn get(&self, name: &SmolStr) -> Option<&Resolution> {
|
||||
self.items.get(name)
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ impl ModuleScope {
|
|||
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
|
||||
/// running name resolution.
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
pub(crate) struct InputModuleItems {
|
||||
pub struct InputModuleItems {
|
||||
items: Vec<ModuleItem>,
|
||||
imports: Vec<Import>,
|
||||
}
|
||||
|
@ -89,13 +89,13 @@ struct Import {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) struct NamedImport {
|
||||
file_item_id: SourceFileItemId,
|
||||
relative_range: TextRange,
|
||||
pub struct NamedImport {
|
||||
pub file_item_id: SourceFileItemId,
|
||||
pub relative_range: TextRange,
|
||||
}
|
||||
|
||||
impl NamedImport {
|
||||
pub(crate) fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
|
||||
pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
|
||||
let source_item_id = SourceItemId {
|
||||
file_id,
|
||||
item_id: self.file_item_id,
|
||||
|
@ -115,11 +115,11 @@ enum ImportKind {
|
|||
/// Resolution is basically `DefId` atm, but it should account for stuff like
|
||||
/// multiple namespaces, ambiguity and errors.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct Resolution {
|
||||
pub struct Resolution {
|
||||
/// None for unresolved
|
||||
pub(crate) def_id: Option<DefId>,
|
||||
pub def_id: Option<DefId>,
|
||||
/// ident by whitch this is imported into local scope.
|
||||
pub(crate) import: Option<NamedImport>,
|
||||
pub import: Option<NamedImport>,
|
||||
}
|
||||
|
||||
// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -336,109 +336,3 @@ where
|
|||
f(module_items)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ra_db::FilesDatabase;
|
||||
use crate::{
|
||||
AnalysisChange,
|
||||
mock_analysis::{MockAnalysis, analysis_and_position},
|
||||
hir::{self, HirDatabase},
|
||||
};
|
||||
use super::*;
|
||||
|
||||
fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
|
||||
let (analysis, pos) = analysis_and_position(fixture);
|
||||
let db = analysis.imp.db;
|
||||
let source_root = db.file_source_root(pos.file_id);
|
||||
let descr = hir::Module::guess_from_position(&*db, pos)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let module_id = descr.module_id;
|
||||
(db.item_map(source_root).unwrap(), module_id)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_item_map() {
|
||||
let (item_map, module_id) = item_map(
|
||||
"
|
||||
//- /lib.rs
|
||||
mod foo;
|
||||
|
||||
use crate::foo::bar::Baz;
|
||||
<|>
|
||||
|
||||
//- /foo/mod.rs
|
||||
pub mod bar;
|
||||
|
||||
//- /foo/bar.rs
|
||||
pub struct Baz;
|
||||
",
|
||||
);
|
||||
let name = SmolStr::from("Baz");
|
||||
let resolution = &item_map.per_module[&module_id].items[&name];
|
||||
assert!(resolution.def_id.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typing_inside_a_function_should_not_invalidate_item_map() {
|
||||
let mock_analysis = MockAnalysis::with_files(
|
||||
"
|
||||
//- /lib.rs
|
||||
mod foo;
|
||||
|
||||
use crate::foo::bar::Baz;
|
||||
|
||||
fn foo() -> i32 {
|
||||
1 + 1
|
||||
}
|
||||
//- /foo/mod.rs
|
||||
pub mod bar;
|
||||
|
||||
//- /foo/bar.rs
|
||||
pub struct Baz;
|
||||
",
|
||||
);
|
||||
|
||||
let file_id = mock_analysis.id_of("/lib.rs");
|
||||
let mut host = mock_analysis.analysis_host();
|
||||
|
||||
let source_root = host.analysis().imp.db.file_source_root(file_id);
|
||||
|
||||
{
|
||||
let db = host.analysis().imp.db;
|
||||
let events = db.log_executed(|| {
|
||||
db.item_map(source_root).unwrap();
|
||||
});
|
||||
assert!(format!("{:?}", events).contains("item_map"))
|
||||
}
|
||||
|
||||
let mut change = AnalysisChange::new();
|
||||
|
||||
change.change_file(
|
||||
file_id,
|
||||
"
|
||||
mod foo;
|
||||
|
||||
use crate::foo::bar::Baz;
|
||||
|
||||
fn foo() -> i32 { 92 }
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
host.apply_change(change);
|
||||
|
||||
{
|
||||
let db = host.analysis().imp.db;
|
||||
let events = db.log_executed(|| {
|
||||
db.item_map(source_root).unwrap();
|
||||
});
|
||||
assert!(
|
||||
!format!("{:?}", events).contains("_item_map"),
|
||||
"{:#?}",
|
||||
events
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use ra_syntax::{SmolStr, ast, AstNode, TextRange};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct Path {
|
||||
pub(crate) kind: PathKind,
|
||||
pub(crate) segments: Vec<SmolStr>,
|
||||
pub struct Path {
|
||||
pub kind: PathKind,
|
||||
pub segments: Vec<SmolStr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum PathKind {
|
||||
pub enum PathKind {
|
||||
Plain,
|
||||
Self_,
|
||||
Super,
|
||||
|
@ -16,14 +16,14 @@ pub(crate) enum PathKind {
|
|||
|
||||
impl Path {
|
||||
/// Calls `cb` with all paths, represented by this use item.
|
||||
pub(crate) fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
|
||||
pub fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
|
||||
if let Some(tree) = item.use_tree() {
|
||||
expand_use_tree(None, tree, &mut cb);
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||
pub(crate) fn from_ast(mut path: ast::Path) -> Option<Path> {
|
||||
pub fn from_ast(mut path: ast::Path) -> Option<Path> {
|
||||
let mut kind = PathKind::Plain;
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
|
@ -64,7 +64,7 @@ impl Path {
|
|||
}
|
||||
|
||||
/// `true` is this path is a single identifier, like `foo`
|
||||
pub(crate) fn is_ident(&self) -> bool {
|
||||
pub fn is_ident(&self) -> bool {
|
||||
self.kind == PathKind::Plain && self.segments.len() == 1
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue