Make ModPath's representation private

This commit is contained in:
Jonas Schievink 2021-02-04 20:49:24 +01:00
parent 36191543a6
commit 5d99ba1d9a
18 changed files with 70 additions and 51 deletions

View file

@ -151,8 +151,8 @@ fn insert_import(
ctx.config.insert_use.prefix_kind, ctx.config.insert_use.prefix_kind,
); );
if let Some(mut mod_path) = mod_path { if let Some(mut mod_path) = mod_path {
mod_path.segments.pop(); mod_path.pop_segment();
mod_path.segments.push(variant_hir_name.clone()); mod_path.push_segment(variant_hir_name.clone());
let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?; let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?;
*rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge); *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge);
} }

View file

@ -175,7 +175,7 @@ fn compute_fuzzy_completion_order_key(
user_input_lowercased: &str, user_input_lowercased: &str,
) -> usize { ) -> usize {
mark::hit!(certain_fuzzy_order_test); mark::hit!(certain_fuzzy_order_test);
let proposed_import_name = match proposed_mod_path.segments.last() { let proposed_import_name = match proposed_mod_path.segments().last() {
Some(name) => name.to_string().to_lowercase(), Some(name) => name.to_string().to_lowercase(),
None => return usize::MAX, None => return usize::MAX,
}; };

View file

@ -63,7 +63,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
// Variants with trivial paths are already added by the existing completion logic, // Variants with trivial paths are already added by the existing completion logic,
// so we should avoid adding these twice // so we should avoid adding these twice
if path.segments.len() > 1 { if path.segments().len() > 1 {
acc.add_qualified_enum_variant(ctx, variant, path); acc.add_qualified_enum_variant(ctx, variant, path);
} }
} }

View file

@ -332,9 +332,9 @@ impl Builder {
label = format!("{} ({})", label, import_to_add.import_path); label = format!("{} ({})", label, import_to_add.import_path);
} else { } else {
let mut import_path_without_last_segment = import_to_add.import_path.to_owned(); let mut import_path_without_last_segment = import_to_add.import_path.to_owned();
let _ = import_path_without_last_segment.segments.pop(); let _ = import_path_without_last_segment.pop_segment();
if !import_path_without_last_segment.segments.is_empty() { if !import_path_without_last_segment.segments().is_empty() {
lookup = lookup.or_else(|| Some(label.clone())); lookup = lookup.or_else(|| Some(label.clone()));
insert_text = insert_text.or_else(|| Some(label.clone())); insert_text = insert_text.or_else(|| Some(label.clone()));
label = format!("{}::{}", import_path_without_last_segment, label); label = format!("{}::{}", import_path_without_last_segment, label);

View file

@ -57,7 +57,7 @@ pub(crate) fn render_resolution_with_import<'a>(
ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(), ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(),
ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(), ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(),
ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(), ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(),
_ => import_edit.import_path.segments.last()?.to_string(), _ => import_edit.import_path.segments().last()?.to_string(),
}; };
Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| { Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| {
item.completion_kind = CompletionKind::Magic; item.completion_kind = CompletionKind::Magic;

View file

@ -45,8 +45,8 @@ impl<'a> EnumRender<'a> {
let (qualified_name, short_qualified_name) = match &path { let (qualified_name, short_qualified_name) = match &path {
Some(path) => { Some(path) => {
let full = path.to_string(); let full = path.to_string();
let short = let segments = path.segments();
path.segments[path.segments.len().saturating_sub(2)..].iter().join("::"); let short = segments[segments.len().saturating_sub(2)..].iter().join("::");
(full, short) (full, short)
} }
None => (name.to_string(), name.to_string()), None => (name.to_string(), name.to_string()),

View file

@ -36,13 +36,13 @@ const MAX_PATH_LEN: usize = 15;
impl ModPath { impl ModPath {
fn starts_with_std(&self) -> bool { fn starts_with_std(&self) -> bool {
self.segments.first() == Some(&known::std) self.segments().first() == Some(&known::std)
} }
// When std library is present, paths starting with `std::` // When std library is present, paths starting with `std::`
// should be preferred over paths starting with `core::` and `alloc::` // should be preferred over paths starting with `core::` and `alloc::`
fn can_start_with_std(&self) -> bool { fn can_start_with_std(&self) -> bool {
let first_segment = self.segments.first(); let first_segment = self.segments().first();
first_segment == Some(&known::alloc) || first_segment == Some(&known::core) first_segment == Some(&known::alloc) || first_segment == Some(&known::core)
} }
} }
@ -157,7 +157,7 @@ fn find_path_inner(
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) { if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) {
let data = db.enum_data(variant.parent); let data = db.enum_data(variant.parent);
path.segments.push(data.variants[variant.local_id].name.clone()); path.push_segment(data.variants[variant.local_id].name.clone());
return Some(path); return Some(path);
} }
// If this doesn't work, it seems we have no way of referring to the // If this doesn't work, it seems we have no way of referring to the
@ -186,7 +186,7 @@ fn find_path_inner(
best_path_len - 1, best_path_len - 1,
prefixed, prefixed,
) { ) {
path.segments.push(name); path.push_segment(name);
let new_path = if let Some(best_path) = best_path { let new_path = if let Some(best_path) = best_path {
select_best_path(best_path, path, prefer_no_std) select_best_path(best_path, path, prefer_no_std)
@ -215,7 +215,7 @@ fn find_path_inner(
prefixed, prefixed,
)?; )?;
mark::hit!(partially_imported); mark::hit!(partially_imported);
path.segments.push(info.path.segments.last().unwrap().clone()); path.push_segment(info.path.segments.last().unwrap().clone());
Some(path) Some(path)
}) })
}); });

View file

@ -240,7 +240,7 @@ impl ItemVisibilities {
fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
match &vis { match &vis {
RawVisibility::Public => RawVisibilityId::PUB, RawVisibility::Public => RawVisibilityId::PUB,
RawVisibility::Module(path) if path.segments.is_empty() => match &path.kind { RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind {
PathKind::Super(0) => RawVisibilityId::PRIV, PathKind::Super(0) => RawVisibilityId::PRIV,
PathKind::Crate => RawVisibilityId::PUB_CRATE, PathKind::Crate => RawVisibilityId::PUB_CRATE,
_ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
@ -251,10 +251,8 @@ impl ItemVisibilities {
} }
static VIS_PUB: RawVisibility = RawVisibility::Public; static VIS_PUB: RawVisibility = RawVisibility::Public;
static VIS_PRIV: RawVisibility = static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)));
RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() }); static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
static VIS_PUB_CRATE: RawVisibility =
RawVisibility::Module(ModPath { kind: PathKind::Crate, segments: Vec::new() });
#[derive(Default, Debug, Eq, PartialEq)] #[derive(Default, Debug, Eq, PartialEq)]
struct GenericParamsStorage { struct GenericParamsStorage {

View file

@ -750,7 +750,8 @@ impl Ctx {
fn desugar_future_path(orig: TypeRef) -> Path { fn desugar_future_path(orig: TypeRef) -> Path {
let path = path![core::future::Future]; let path = path![core::future::Future];
let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); let mut generic_args: Vec<_> =
std::iter::repeat(None).take(path.segments().len() - 1).collect();
let mut last = GenericArgs::empty(); let mut last = GenericArgs::empty();
let binding = let binding =
AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() };

View file

@ -662,7 +662,7 @@ impl AsMacroCall for AstIdWithPath<ast::Item> {
def.as_lazy_macro( def.as_lazy_macro(
db.upcast(), db.upcast(),
krate, krate,
MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()), MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()),
) )
.into(), .into(),
) )

View file

@ -655,7 +655,7 @@ impl DefCollector<'_> {
} }
} }
} else { } else {
match import.path.segments.last() { match import.path.segments().last() {
Some(last_segment) => { Some(last_segment) => {
let name = match &import.alias { let name = match &import.alias {
Some(ImportAlias::Alias(name)) => Some(name.clone()), Some(ImportAlias::Alias(name)) => Some(name.clone()),
@ -956,7 +956,7 @@ impl DefCollector<'_> {
let item_tree = self.db.item_tree(import.file_id); let item_tree = self.db.item_tree(import.file_id);
let import_data = &item_tree[import.value]; let import_data = &item_tree[import.value];
match (import_data.path.segments.first(), &import_data.path.kind) { match (import_data.path.segments().first(), &import_data.path.kind) {
(Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
if diagnosed_extern_crates.contains(krate) { if diagnosed_extern_crates.contains(krate) {
continue; continue;

View file

@ -149,7 +149,7 @@ impl DefMap {
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
) -> ResolvePathResult { ) -> ResolvePathResult {
let mut segments = path.segments.iter().enumerate(); let mut segments = path.segments().iter().enumerate();
let mut curr_per_ns: PerNs = match path.kind { let mut curr_per_ns: PerNs = match path.kind {
PathKind::DollarCrate(krate) => { PathKind::DollarCrate(krate) => {
if krate == self.krate { if krate == self.krate {
@ -190,7 +190,7 @@ impl DefMap {
// BuiltinShadowMode wasn't Module, then we need to try // BuiltinShadowMode wasn't Module, then we need to try
// resolving it as a builtin. // resolving it as a builtin.
let prefer_module = let prefer_module =
if path.segments.len() == 1 { shadow } else { BuiltinShadowMode::Module }; if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
log::debug!("resolving {:?} in module", segment); log::debug!("resolving {:?} in module", segment);
self.resolve_name_in_module(db, original_module, &segment, prefer_module) self.resolve_name_in_module(db, original_module, &segment, prefer_module)
@ -203,10 +203,10 @@ impl DefMap {
None => match &self.block { None => match &self.block {
Some(block) => { Some(block) => {
// Look up remaining path in parent `DefMap` // Look up remaining path in parent `DefMap`
let new_path = ModPath { let new_path = ModPath::from_segments(
kind: PathKind::Super(lvl - i), PathKind::Super(lvl - i),
segments: path.segments.clone(), path.segments().to_vec(),
}; );
log::debug!("`super` path: {} -> {} in parent map", path, new_path); log::debug!("`super` path: {} -> {} in parent map", path, new_path);
return block.parent.def_map(db).resolve_path_fp_with_macro( return block.parent.def_map(db).resolve_path_fp_with_macro(
db, db,
@ -258,10 +258,10 @@ impl DefMap {
curr_per_ns = match curr { curr_per_ns = match curr {
ModuleDefId::ModuleId(module) => { ModuleDefId::ModuleId(module) => {
if module.krate != self.krate { if module.krate != self.krate {
let path = ModPath { let path = ModPath::from_segments(
segments: path.segments[i..].to_vec(), PathKind::Super(0),
kind: PathKind::Super(0), path.segments()[i..].iter().cloned(),
}; );
log::debug!("resolving {:?} in other crate", path); log::debug!("resolving {:?} in other crate", path);
let defp_map = module.def_map(db); let defp_map = module.def_map(db);
let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);

View file

@ -20,7 +20,7 @@ use crate::{
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModPath { pub struct ModPath {
pub kind: PathKind, pub kind: PathKind,
pub segments: Vec<Name>, segments: Vec<Name>,
} }
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -53,6 +53,11 @@ impl ModPath {
ModPath { kind, segments } ModPath { kind, segments }
} }
/// Creates a `ModPath` from a `PathKind`, with no extra path segments.
pub const fn from_kind(kind: PathKind) -> ModPath {
ModPath { kind, segments: Vec::new() }
}
/// Calls `cb` with all paths, represented by this use item. /// Calls `cb` with all paths, represented by this use item.
pub(crate) fn expand_use_item( pub(crate) fn expand_use_item(
item_src: InFile<ast::Use>, item_src: InFile<ast::Use>,
@ -64,6 +69,18 @@ impl ModPath {
} }
} }
pub fn segments(&self) -> &[Name] {
&self.segments
}
pub fn push_segment(&mut self, segment: Name) {
self.segments.push(segment);
}
pub fn pop_segment(&mut self) -> Option<Name> {
self.segments.pop()
}
/// Returns the number of segments in the path (counting special segments like `$crate` and /// Returns the number of segments in the path (counting special segments like `$crate` and
/// `super`). /// `super`).
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
@ -78,7 +95,7 @@ impl ModPath {
} }
pub fn is_ident(&self) -> bool { pub fn is_ident(&self) -> bool {
self.kind == PathKind::Plain && self.segments.len() == 1 self.as_ident().is_some()
} }
pub fn is_self(&self) -> bool { pub fn is_self(&self) -> bool {
@ -87,10 +104,14 @@ impl ModPath {
/// If this path is a single identifier, like `foo`, return its name. /// If this path is a single identifier, like `foo`, return its name.
pub fn as_ident(&self) -> Option<&Name> { pub fn as_ident(&self) -> Option<&Name> {
if !self.is_ident() { if self.kind != PathKind::Plain {
return None; return None;
} }
self.segments.first()
match &*self.segments {
[name] => Some(name),
_ => None,
}
} }
} }

View file

@ -164,7 +164,7 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
) -> Option<(TypeNs, Option<usize>)> { ) -> Option<(TypeNs, Option<usize>)> {
let first_name = path.segments.first()?; let first_name = path.segments().first()?;
let skip_to_mod = path.kind != PathKind::Plain; let skip_to_mod = path.kind != PathKind::Plain;
for scope in self.scopes.iter().rev() { for scope in self.scopes.iter().rev() {
match scope { match scope {
@ -179,7 +179,7 @@ impl Resolver {
Scope::GenericParams { params, def } => { Scope::GenericParams { params, def } => {
if let Some(local_id) = params.find_type_by_name(first_name) { if let Some(local_id) = params.find_type_by_name(first_name) {
let idx = if path.segments.len() == 1 { None } else { Some(1) }; let idx = if path.segments().len() == 1 { None } else { Some(1) };
return Some(( return Some((
TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
idx, idx,
@ -188,13 +188,13 @@ impl Resolver {
} }
Scope::ImplDefScope(impl_) => { Scope::ImplDefScope(impl_) => {
if first_name == &name![Self] { if first_name == &name![Self] {
let idx = if path.segments.len() == 1 { None } else { Some(1) }; let idx = if path.segments().len() == 1 { None } else { Some(1) };
return Some((TypeNs::SelfType(*impl_), idx)); return Some((TypeNs::SelfType(*impl_), idx));
} }
} }
Scope::AdtScope(adt) => { Scope::AdtScope(adt) => {
if first_name == &name![Self] { if first_name == &name![Self] {
let idx = if path.segments.len() == 1 { None } else { Some(1) }; let idx = if path.segments().len() == 1 { None } else { Some(1) };
return Some((TypeNs::AdtSelfType(*adt), idx)); return Some((TypeNs::AdtSelfType(*adt), idx));
} }
} }
@ -270,9 +270,9 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
) -> 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

@ -22,8 +22,7 @@ pub enum RawVisibility {
impl RawVisibility { impl RawVisibility {
pub(crate) const fn private() -> RawVisibility { pub(crate) const fn private() -> RawVisibility {
let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() }; RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)))
RawVisibility::Module(path)
} }
pub(crate) fn from_ast( pub(crate) fn from_ast(
@ -59,15 +58,15 @@ impl RawVisibility {
RawVisibility::Module(path) RawVisibility::Module(path)
} }
ast::VisibilityKind::PubCrate => { ast::VisibilityKind::PubCrate => {
let path = ModPath { kind: PathKind::Crate, segments: Vec::new() }; let path = ModPath::from_kind(PathKind::Crate);
RawVisibility::Module(path) RawVisibility::Module(path)
} }
ast::VisibilityKind::PubSuper => { ast::VisibilityKind::PubSuper => {
let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; let path = ModPath::from_kind(PathKind::Super(1));
RawVisibility::Module(path) RawVisibility::Module(path)
} }
ast::VisibilityKind::PubSelf => { ast::VisibilityKind::PubSelf => {
let path = ModPath { kind: PathKind::Plain, segments: Vec::new() }; let path = ModPath::from_kind(PathKind::Plain);
RawVisibility::Module(path) RawVisibility::Module(path)
} }
ast::VisibilityKind::Pub => RawVisibility::Public, ast::VisibilityKind::Pub => RawVisibility::Public,

View file

@ -461,7 +461,7 @@ impl<'a> InferenceContext<'a> {
(ty, variant) (ty, variant)
} }
Some(1) => { Some(1) => {
let segment = path.mod_path().segments.last().unwrap(); let segment = path.mod_path().segments().last().unwrap();
// this could be an enum variant or associated type // this could be an enum variant or associated type
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
let enum_data = self.db.enum_data(enum_id); let enum_data = self.db.enum_data(enum_id);

View file

@ -24,7 +24,7 @@ pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
} }
segments.extend( segments.extend(
path.segments path.segments()
.iter() .iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))), .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
); );

View file

@ -1729,7 +1729,7 @@ fn fill_resolve_data(
) -> Option<()> { ) -> Option<()> {
let import_edit = item.import_to_add()?; let import_edit = item.import_to_add()?;
let full_import_path = import_edit.import_path.to_string(); let full_import_path = import_edit.import_path.to_string();
let imported_name = import_edit.import_path.segments.clone().pop()?.to_string(); let imported_name = import_edit.import_path.segments().last()?.to_string();
*resolve_data = Some( *resolve_data = Some(
to_value(CompletionResolveData { to_value(CompletionResolveData {