From 5d99ba1d9a5acf02a5cd50e456f164bd80b523b5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 4 Feb 2021 20:49:24 +0100 Subject: Make `ModPath`'s representation private --- .../handlers/extract_struct_from_enum_variant.rs | 4 +-- crates/completion/src/completions/flyimport.rs | 2 +- .../completion/src/completions/unqualified_path.rs | 2 +- crates/completion/src/item.rs | 4 +-- crates/completion/src/render.rs | 2 +- crates/completion/src/render/enum_variant.rs | 4 +-- crates/hir_def/src/find_path.rs | 10 ++++---- crates/hir_def/src/item_tree.rs | 8 +++--- crates/hir_def/src/item_tree/lower.rs | 3 ++- crates/hir_def/src/lib.rs | 2 +- crates/hir_def/src/nameres/collector.rs | 4 +-- crates/hir_def/src/nameres/path_resolution.rs | 20 +++++++-------- crates/hir_def/src/path.rs | 29 +++++++++++++++++++--- crates/hir_def/src/resolver.rs | 12 ++++----- crates/hir_def/src/visibility.rs | 9 +++---- crates/hir_ty/src/infer.rs | 2 +- crates/ide_db/src/helpers.rs | 2 +- crates/rust-analyzer/src/handlers.rs | 2 +- 18 files changed, 70 insertions(+), 51 deletions(-) diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index e3ef04932..5c7678b53 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs @@ -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); } diff --git a/crates/completion/src/completions/flyimport.rs b/crates/completion/src/completions/flyimport.rs index 9c6a5a40c..c9f928483 100644 --- a/crates/completion/src/completions/flyimport.rs +++ b/crates/completion/src/completions/flyimport.rs @@ -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, }; diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 5d62fab97..e2482f959 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs @@ -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); } } diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 8ec4ac65e..884711f11 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs @@ -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); diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index e11b881ca..eddaaa6f3 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs @@ -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; diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs index adcddebd1..9214193b4 100644 --- a/crates/completion/src/render/enum_variant.rs +++ b/crates/completion/src/render/enum_variant.rs @@ -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()), diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 94a1d567d..aa2c6e04e 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs @@ -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) }) }); diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 401556931..3233b1957 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -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 { diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 93cdca55d..8f2f0b340 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -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() }; diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 5dd3705b0..b50923747 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -662,7 +662,7 @@ impl AsMacroCall for AstIdWithPath { 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(), ) diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index f904a97de..6bd41bc08 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -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; diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 2a3ac5d7b..f2b59172d 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs @@ -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); diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 84ea09b53..0caad53d3 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs @@ -20,7 +20,7 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ModPath { pub kind: PathKind, - pub segments: Vec, + segments: Vec, } #[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, @@ -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 { + 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, + } } } diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 9021ea712..f9ad50301 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -164,7 +164,7 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, ) -> Option<(TypeNs, Option)> { - 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 { - 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 { diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index e79a91102..38da3132b 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs @@ -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, diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index d08867c70..4b683c5a7 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -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); diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index 0dcc4dd29..bc7aee110 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -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()))), ); diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 07204436c..5a6501216 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -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 { -- cgit v1.2.3