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,
);
if let Some(mut mod_path) = mod_path {
mod_path.segments.pop();
mod_path.segments.push(variant_hir_name.clone());
mod_path.pop_segment();
mod_path.push_segment(variant_hir_name.clone());
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);
}

View File

@ -175,7 +175,7 @@ fn compute_fuzzy_completion_order_key(
user_input_lowercased: &str,
) -> usize {
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(),
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)) {
// Variants with trivial paths are already added by the existing completion logic,
// 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);
}
}

View File

@ -332,9 +332,9 @@ impl Builder {
label = format!("{} ({})", label, import_to_add.import_path);
} else {
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()));
insert_text = insert_text.or_else(|| Some(label.clone()));
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::Const(c)) => c.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| {
item.completion_kind = CompletionKind::Magic;

View File

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

View File

@ -36,13 +36,13 @@ const MAX_PATH_LEN: usize = 15;
impl ModPath {
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::`
// should be preferred over paths starting with `core::` and `alloc::`
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)
}
}
@ -157,7 +157,7 @@ fn find_path_inner(
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) {
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);
}
// 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,
prefixed,
) {
path.segments.push(name);
path.push_segment(name);
let new_path = if let Some(best_path) = best_path {
select_best_path(best_path, path, prefer_no_std)
@ -215,7 +215,7 @@ fn find_path_inner(
prefixed,
)?;
mark::hit!(partially_imported);
path.segments.push(info.path.segments.last().unwrap().clone());
path.push_segment(info.path.segments.last().unwrap().clone());
Some(path)
})
});

View File

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

View File

@ -750,7 +750,8 @@ impl Ctx {
fn desugar_future_path(orig: TypeRef) -> Path {
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 binding =
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(
db.upcast(),
krate,
MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()),
MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()),
)
.into(),
)

View File

@ -655,7 +655,7 @@ impl DefCollector<'_> {
}
}
} else {
match import.path.segments.last() {
match import.path.segments().last() {
Some(last_segment) => {
let name = match &import.alias {
Some(ImportAlias::Alias(name)) => Some(name.clone()),
@ -956,7 +956,7 @@ impl DefCollector<'_> {
let item_tree = self.db.item_tree(import.file_id);
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) => {
if diagnosed_extern_crates.contains(krate) {
continue;

View File

@ -149,7 +149,7 @@ impl DefMap {
path: &ModPath,
shadow: BuiltinShadowMode,
) -> ResolvePathResult {
let mut segments = path.segments.iter().enumerate();
let mut segments = path.segments().iter().enumerate();
let mut curr_per_ns: PerNs = match path.kind {
PathKind::DollarCrate(krate) => {
if krate == self.krate {
@ -190,7 +190,7 @@ impl DefMap {
// BuiltinShadowMode wasn't Module, then we need to try
// resolving it as a builtin.
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);
self.resolve_name_in_module(db, original_module, &segment, prefer_module)
@ -203,10 +203,10 @@ impl DefMap {
None => match &self.block {
Some(block) => {
// Look up remaining path in parent `DefMap`
let new_path = ModPath {
kind: PathKind::Super(lvl - i),
segments: path.segments.clone(),
};
let new_path = ModPath::from_segments(
PathKind::Super(lvl - i),
path.segments().to_vec(),
);
log::debug!("`super` path: {} -> {} in parent map", path, new_path);
return block.parent.def_map(db).resolve_path_fp_with_macro(
db,
@ -258,10 +258,10 @@ impl DefMap {
curr_per_ns = match curr {
ModuleDefId::ModuleId(module) => {
if module.krate != self.krate {
let path = ModPath {
segments: path.segments[i..].to_vec(),
kind: PathKind::Super(0),
};
let path = ModPath::from_segments(
PathKind::Super(0),
path.segments()[i..].iter().cloned(),
);
log::debug!("resolving {:?} in other crate", path);
let defp_map = module.def_map(db);
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)]
pub struct ModPath {
pub kind: PathKind,
pub segments: Vec<Name>,
segments: Vec<Name>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -53,6 +53,11 @@ impl ModPath {
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.
pub(crate) fn expand_use_item(
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
/// `super`).
pub fn len(&self) -> usize {
@ -78,7 +95,7 @@ impl ModPath {
}
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 {
@ -87,10 +104,14 @@ impl ModPath {
/// If this path is a single identifier, like `foo`, return its name.
pub fn as_ident(&self) -> Option<&Name> {
if !self.is_ident() {
if self.kind != PathKind::Plain {
return None;
}
self.segments.first()
match &*self.segments {
[name] => Some(name),
_ => None,
}
}
}

View File

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

View File

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

View File

@ -461,7 +461,7 @@ impl<'a> InferenceContext<'a> {
(ty, variant)
}
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
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
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(
path.segments
path.segments()
.iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
);

View File

@ -1729,7 +1729,7 @@ fn fill_resolve_data(
) -> Option<()> {
let import_edit = item.import_to_add()?;
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(
to_value(CompletionResolveData {