Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22743 from dfireBird/fix-nameref-classify
fix: resolve path on all namespace on resolve_path
| -rw-r--r-- | crates/hir-def/src/per_ns.rs | 8 | ||||
| -rw-r--r-- | crates/hir-def/src/resolver.rs | 83 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower/path.rs | 4 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 156 | ||||
| -rw-r--r-- | crates/ide-assists/src/tests.rs | 1 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/highlight_module_macro_conflict.html | 50 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/private_multi_namespace.html | 46 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/tests.rs | 48 |
8 files changed, 309 insertions, 87 deletions
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 8721cd65db..f7e5ac316a 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -109,16 +109,16 @@ impl PerNs { self.values.map(|it| it.def) } - pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportOrGlob>)> { - self.values.map(|it| (it.def, it.import)) + pub fn take_values_full(self) -> Option<ValuesItem> { + self.values } pub fn take_macros(self) -> Option<MacroId> { self.macros.map(|it| it.def) } - pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrExternCrate>)> { - self.macros.map(|it| (it.def, it.import)) + pub fn take_macros_full(self) -> Option<MacrosItem> { + self.macros } pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 63ff384de0..5b11f5ff8b 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -33,7 +33,7 @@ use crate::{ item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ItemScope}, lang_item::LangItemTarget, nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map}, - per_ns::PerNs, + per_ns::{MacrosItem, PerNs}, signatures::ImplSignature, src::HasSource, type_ref::LifetimeRef, @@ -174,7 +174,9 @@ impl<'db> Resolver<'db> { path: &Path, ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> { self.resolve_path_in_type_ns_with_prefix_info(db, path).map( - |(resolution, remaining_segments, import, _)| (resolution, remaining_segments, import), + |(resolution, remaining_segments, import, _, _)| { + (resolution, remaining_segments, import) + }, ) } @@ -182,8 +184,13 @@ impl<'db> Resolver<'db> { &self, db: &dyn SourceDatabase, path: &Path, - ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)> - { + ) -> Option<( + TypeNs, + Option<usize>, + Option<ImportOrExternCrate>, + ResolvePathResultPrefixInfo, + Visibility, + )> { let path = match path { Path::BarePath(mod_path) => mod_path, Path::Normal(it) => &it.mod_path, @@ -206,6 +213,7 @@ impl<'db> Resolver<'db> { seg.as_ref().map(|_| 1), None, ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } }; @@ -230,6 +238,7 @@ impl<'db> Resolver<'db> { remaining_idx(), None, ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } else if let &GenericDefId::AdtId(adt) = def @@ -240,6 +249,7 @@ impl<'db> Resolver<'db> { remaining_idx(), None, ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } if let Some(id) = params.find_type_by_name(first_name, *def) { @@ -248,6 +258,7 @@ impl<'db> Resolver<'db> { remaining_idx(), None, ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } @@ -264,6 +275,7 @@ impl<'db> Resolver<'db> { remaining_idx(), None, ResolvePathResultPrefixInfo::default(), + Visibility::Public, ) } else { res @@ -323,7 +335,7 @@ impl<'db> Resolver<'db> { path: &Path, hygiene_id: HygieneId, ) -> Option<ResolveValueResult> { - self.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene_id).map(|(it, _)| it) + self.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene_id).map(|(it, _, _)| it) } fn skip_to_mod<'this, T>( @@ -343,7 +355,7 @@ impl<'db> Resolver<'db> { db: &dyn SourceDatabase, path: &Path, mut hygiene_id: HygieneId, - ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> { + ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo, Visibility)> { let path = match path { Path::BarePath(mod_path) => mod_path, Path::Normal(it) => &it.mod_path, @@ -363,6 +375,7 @@ impl<'db> Resolver<'db> { | LangItemTarget::MacroId(_) => return None, }), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } Path::LangItem(l, Some(_)) => { @@ -383,6 +396,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::Partial(type_ns, 0), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } }; @@ -408,6 +422,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.binding())), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } @@ -421,6 +436,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_)), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } if let Some(id) = params.find_const_by_name(first_name, *def) { @@ -428,6 +444,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::ValueNs(val), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } @@ -448,6 +465,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } else if let &GenericDefId::AdtId(adt) = def @@ -457,6 +475,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::Partial(ty, 1), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } if let Some(id) = params.find_type_by_name(first_name, *def) { @@ -464,6 +483,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::Partial(ty, 1), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } } @@ -490,6 +510,7 @@ impl<'db> Resolver<'db> { return Some(( ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1), ResolvePathResultPrefixInfo::default(), + Visibility::Public, )); } @@ -513,7 +534,7 @@ impl<'db> Resolver<'db> { db: &dyn SourceDatabase, path: &ModPath, expected_macro_kind: Option<MacroSubNs>, - ) -> Option<(MacroId, Option<ImportOrExternCrate>)> { + ) -> Option<MacrosItem> { let (item_map, item_local_map, module) = self.item_scope_(); item_map .resolve_path( @@ -525,7 +546,7 @@ impl<'db> Resolver<'db> { expected_macro_kind, ) .0 - .take_macros_import() + .take_macros_full() } pub fn resolve_path_as_macro_def( @@ -534,7 +555,7 @@ impl<'db> Resolver<'db> { path: &ModPath, expected_macro_kind: Option<MacroSubNs>, ) -> Option<MacroDefId> { - self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| it.definition(db)) + self.resolve_path_as_macro(db, path, expected_macro_kind).map(|it| it.def.definition(db)) } pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> { @@ -1166,7 +1187,7 @@ impl<'db> ModuleItemMap<'db> { &self, db: &'db dyn SourceDatabase, path: &ModPath, - ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> { + ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo, Visibility)> { let (module_def, unresolved_idx, prefix_info) = self.def_map.resolve_path_locally( self.local_def_map, db, @@ -1176,12 +1197,12 @@ impl<'db> ModuleItemMap<'db> { ); match unresolved_idx { None => { - let value = to_value_ns(module_def, self.def_map)?; - Some((ResolveValueResult::ValueNs(value), prefix_info)) + let (value, vis) = to_value_ns(module_def, self.def_map)?; + Some((ResolveValueResult::ValueNs(value), prefix_info, vis)) } Some(unresolved_idx) => { - let def = module_def.take_types()?; - let ty = match def { + let res = module_def.take_types_full()?; + let ty = match res.def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), @@ -1194,7 +1215,7 @@ impl<'db> ModuleItemMap<'db> { | ModuleDefId::MacroId(_) | ModuleDefId::StaticId(_) => return None, }; - Some((ResolveValueResult::Partial(ty, unresolved_idx), prefix_info)) + Some((ResolveValueResult::Partial(ty, unresolved_idx), prefix_info, res.vis)) } } } @@ -1203,8 +1224,13 @@ impl<'db> ModuleItemMap<'db> { &self, db: &dyn SourceDatabase, path: &ModPath, - ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)> - { + ) -> Option<( + TypeNs, + Option<usize>, + Option<ImportOrExternCrate>, + ResolvePathResultPrefixInfo, + Visibility, + )> { let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally( self.local_def_map, db, @@ -1212,17 +1238,22 @@ impl<'db> ModuleItemMap<'db> { path, BuiltinShadowMode::Other, ); - let (res, import) = to_type_ns(module_def)?; - Some((res, idx, import, prefix_info)) + let (res, import, vis) = to_type_ns(module_def)?; + Some((res, idx, import, prefix_info, vis)) } } -fn to_value_ns(per_ns: PerNs, def_map: &DefMap) -> Option<ValueNs> { - let def = per_ns.take_values().or_else(|| { - let Some(MacroId::ProcMacroId(proc_macro)) = per_ns.take_macros() else { return None }; +fn to_value_ns(per_ns: PerNs, def_map: &DefMap) -> Option<(ValueNs, Visibility)> { + let (def, vis) = per_ns.take_values_full().map(|res| (res.def, res.vis)).or_else(|| { + let Some(MacrosItem { def: MacroId::ProcMacroId(proc_macro), vis, .. }) = + per_ns.take_macros_full() + else { + return None; + }; // If we cannot resolve to value ns, but we can resolve to a proc macro, and this is the crate // defining this proc macro - inside this crate, we should treat the macro as a function. - def_map.proc_macro_as_fn(proc_macro).map(ModuleDefId::FunctionId) + let def = ModuleDefId::FunctionId(def_map.proc_macro_as_fn(proc_macro)?); + Some((def, vis)) })?; let res = match def { ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), @@ -1238,10 +1269,10 @@ fn to_value_ns(per_ns: PerNs, def_map: &DefMap) -> Option<ValueNs> { | ModuleDefId::MacroId(_) | ModuleDefId::ModuleId(_) => return None, }; - Some(res) + Some((res, vis)) } -fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> { +fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>, Visibility)> { let def = per_ns.take_types_full()?; let res = match def.def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), @@ -1259,7 +1290,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> { | ModuleDefId::MacroId(_) | ModuleDefId::StaticId(_) => return None, }; - Some((res, def.import)) + Some((res, def.import, def.vis)) } #[derive(Default)] diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index 77037c5b12..554a191d9d 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -334,7 +334,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { #[tracing::instrument(skip(self), ret)] pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option<usize>)> { - let (resolution, remaining_index, _, prefix_info) = + let (resolution, remaining_index, _, prefix_info, _) = self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?; let segments = self.segments; @@ -385,7 +385,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { &mut self, hygiene_id: HygieneId, ) -> Option<ResolveValueResult> { - let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( + let (res, prefix_info, _) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( self.ctx.db, self.path, hygiene_id, diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index fb27f9dec4..e80567641b 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -24,8 +24,9 @@ use hir_def::{ hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams}, lang_item::LangItems, nameres::MacroSubNs, - resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope}, + resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypeRefId}, + visibility::Visibility, }; use hir_expand::{ HirFileId, InFile, @@ -1060,7 +1061,7 @@ impl<'db> SourceAnalyzer<'db> { }; let store_owner = self.resolver.expression_store_owner(); - let res = resolve_hir_value_path( + let (res, _) = resolve_hir_value_path( db, &self.resolver, store_owner, @@ -1643,7 +1644,8 @@ impl<'db> SourceAnalyzer<'db> { Some(name.clone()), )), hygiene, - ), + ) + .map(|(it, _)| it), ) }) } @@ -1683,7 +1685,8 @@ impl<'db> SourceAnalyzer<'db> { Some(name.clone()), )), hygiene, - ), + ) + .map(|(it, _)| it), ) })) } @@ -1865,7 +1868,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro( ) -> Option<Macro> { resolver .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr)) - .map(|(it, _)| it) + .map(|it| it.def) .map(Into::into) } @@ -1880,7 +1883,7 @@ fn resolve_hir_path_<'db>( resolve_per_ns: bool, ) -> PathResolutionPerNs<'db> { let types = || { - let (ty, unresolved) = match path.type_anchor() { + let (ty, unresolved, ty_is_visible) = match path.type_anchor() { Some(type_ref) => resolver.generic_def().and_then(|def| { let generics = OnceCell::new(); let (_, res) = TyLoweringContext::new( @@ -1894,19 +1897,20 @@ fn resolve_hir_path_<'db>( LifetimeLoweringMode::LateParam, ) .lower_ty_ext(type_ref); - res.map(|ty_ns| (ty_ns, path.segments().first())) + res.map(|ty_ns| (ty_ns, path.segments().first(), Visibility::Public)) }), None => { - let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?; + let (ty, remaining_idx, _, _, vis) = + resolver.resolve_path_in_type_ns_with_prefix_info(db, path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { - Some((ty, path.segments().last())) + Some((ty, path.segments().last(), vis)) } else { None } } - None => Some((ty, None)), + None => Some((ty, None, vis)), } } }?; @@ -1917,7 +1921,10 @@ fn resolve_hir_path_<'db>( && let Some(type_alias_id) = trait_id.trait_items(db).associated_type_by_name(unresolved.name) { - return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); + return Some(( + PathResolution::Def(ModuleDefId::from(type_alias_id).into()), + ty_is_visible, + )); } let res = match ty { @@ -1945,8 +1952,8 @@ fn resolve_hir_path_<'db>( }) .map(TypeAlias::from) .map(Into::into) - .map(PathResolution::Def), - None => Some(res), + .map(|def| (PathResolution::Def(def), ty_is_visible)), + None => Some((res, ty_is_visible)), } }; @@ -1956,41 +1963,79 @@ fn resolve_hir_path_<'db>( let items = || { resolver .resolve_module_path_in_items(db, path.mod_path()?) - .take_types() - .map(|it| PathResolution::Def(it.into())) + .take_types_full() + .map(|it| (PathResolution::Def(it.def.into()), it.vis)) }; let macros = || { resolver .resolve_path_as_macro(db, path.mod_path()?, None) - .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into()))) + .map(|res| (PathResolution::Def(ModuleDef::Macro(res.def.into())), res.vis)) }; - if resolve_per_ns { - PathResolutionPerNs { - type_ns: types().or_else(items), - value_ns: values(), - macro_ns: macros(), - } - } else { - let res = if prefer_value_ns { - values() - .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None)) - .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None)) - } else { - types() - .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None)) - .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None)) - }; + let mut types_ns: Option<Option<_>> = None; + let mut values_ns: Option<Option<_>> = None; + + let mut types_is_visible: Option<bool> = None; + let mut values_is_visible: Option<bool> = None; - if res.any().is_some() { - res - } else if let Some(type_ns) = items() { - PathResolutionPerNs::new(Some(type_ns), None, None) + if !resolve_per_ns { + if prefer_value_ns { + values_ns = Some(values().inspect(|(_, vis)| { + values_is_visible = Some(resolver.is_visible(db, *vis)); + })); + + if let Some(Some((res, _))) = values_ns + && values_is_visible.unwrap_or_default() + { + return PathResolutionPerNs::new(None, Some(res), None); + } } else { - PathResolutionPerNs::new(None, None, macros()) + types_ns = Some(types().or_else(items).inspect(|(_, vis)| { + types_is_visible = Some(resolver.is_visible(db, *vis)); + })); + + if let Some(Some((res, _))) = types_ns + && types_is_visible.unwrap_or_default() + { + return PathResolutionPerNs::new(Some(res), None, None); + } + } + } + + let mut macros_is_visible = false; + + let mut types = types_ns.unwrap_or_else(|| types().or_else(items)).map(|(res, vis)| { + types_is_visible = Some(types_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis))); + res + }); + let mut values = values_ns.unwrap_or_else(values).map(|(res, vis)| { + values_is_visible = Some(values_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis))); + res + }); + let mut macros = macros().map(|(res, vis)| { + macros_is_visible = resolver.is_visible(db, vis); + res + }); + + let types_is_visible = types_is_visible.unwrap_or_default(); + let values_is_visible = values_is_visible.unwrap_or_default(); + + // If there is a visible resolution and an invisible one, we only want to include the visible one. But if all are + // invisible, we want to include them all. + if types_is_visible || values_is_visible || macros_is_visible { + if !types_is_visible { + types = None; + } + if !values_is_visible { + values = None; + } + if !macros_is_visible { + macros = None; } } + + PathResolutionPerNs { type_ns: types, value_ns: values, macro_ns: macros } } fn resolve_hir_value_path<'db>( @@ -2000,23 +2045,26 @@ fn resolve_hir_value_path<'db>( infer_body: Option<InferBodyId<'db>>, path: &Path, hygiene: HygieneId, -) -> Option<PathResolution<'db>> { - resolver.resolve_path_in_value_ns_fully(db, path, hygiene).and_then(|val| { - let res = match val { - ValueNs::LocalBinding(binding_id) => { - let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id }; - PathResolution::Local(var) - } - ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), - ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), - ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), - ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), - ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), - ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), - ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()), - }; - Some(res) - }) +) -> Option<(PathResolution<'db>, Visibility)> { + resolver.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene).and_then( + |(val, _, vis)| { + let ResolveValueResult::ValueNs(val) = val else { return None }; + let res = match val { + ValueNs::LocalBinding(binding_id) => { + let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id }; + PathResolution::Local(var) + } + ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), + ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), + ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), + ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), + ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), + ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()), + }; + Some((res, vis)) + }, + ) } /// Resolves a path where we know it is a qualifier of another path. diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs index 135e750ca0..3624099b13 100644 --- a/crates/ide-assists/src/tests.rs +++ b/crates/ide-assists/src/tests.rs @@ -354,7 +354,6 @@ fn check_with_config( handler(&mut acc, &ctx); }); let mut res = acc.finish(); - let assist = match assist_label { Some(label) => res.into_iter().find(|resolved| resolved.label == label), None if res.is_empty() => None, diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_module_macro_conflict.html b/crates/ide/src/syntax_highlighting/test_data/highlight_module_macro_conflict.html new file mode 100644 index 0000000000..b61f574f0e --- /dev/null +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_module_macro_conflict.html @@ -0,0 +1,50 @@ + +<style> +body { margin: 0; } +pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } + +.lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } +.comment { color: #7F9F7F; } +.documentation { color: #629755; } +.intra_doc_link { font-style: italic; } +.injected { opacity: 0.65 ; } +.struct, .enum { color: #7CB8BB; } +.enum_variant { color: #BDE0F3; } +.string_literal { color: #CC9393; } +.field { color: #94BFF3; } +.function { color: #93E0E3; } +.parameter { color: #94BFF3; } +.text { color: #DCDCCC; } +.type { color: #7CB8BB; } +.builtin_type { color: #8CD0D3; } +.type_param { color: #DFAF8F; } +.attribute { color: #94BFF3; } +.numeric_literal { color: #BFEBBF; } +.bool_literal { color: #BFE6EB; } +.macro { color: #94BFF3; } +.proc_macro { color: #94BFF3; text-decoration: underline; } +.derive { color: #94BFF3; font-style: italic; } +.module { color: #AFD8AF; } +.value_param { color: #DCDCCC; } +.variable { color: #DCDCCC; } +.format_specifier { color: #CC696B; } +.mutable { text-decoration: underline; } +.escape_sequence { color: #94BFF3; } +.keyword { color: #F0DFAF; font-weight: bold; } +.control { font-style: italic; } +.reference { font-style: italic; font-weight: bold; } +.const { font-weight: bolder; } +.unsafe { color: #BC8383; } +.deprecated { text-decoration: line-through; } + +.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } +.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } +</style> +<pre><code><span class="keyword">use</span> <span class="crate_root library">foo</span><span class="operator">::</span><span class="macro library">bar</span><span class="semicolon">;</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="macro library">bar</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span> +<span class="brace">}</span> + +</code></pre>
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/private_multi_namespace.html b/crates/ide/src/syntax_highlighting/test_data/private_multi_namespace.html new file mode 100644 index 0000000000..06fc3f0772 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/test_data/private_multi_namespace.html @@ -0,0 +1,46 @@ + +<style> +body { margin: 0; } +pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } + +.lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } +.comment { color: #7F9F7F; } +.documentation { color: #629755; } +.intra_doc_link { font-style: italic; } +.injected { opacity: 0.65 ; } +.struct, .enum { color: #7CB8BB; } +.enum_variant { color: #BDE0F3; } +.string_literal { color: #CC9393; } +.field { color: #94BFF3; } +.function { color: #93E0E3; } +.parameter { color: #94BFF3; } +.text { color: #DCDCCC; } +.type { color: #7CB8BB; } +.builtin_type { color: #8CD0D3; } +.type_param { color: #DFAF8F; } +.attribute { color: #94BFF3; } +.numeric_literal { color: #BFEBBF; } +.bool_literal { color: #BFE6EB; } +.macro { color: #94BFF3; } +.proc_macro { color: #94BFF3; text-decoration: underline; } +.derive { color: #94BFF3; font-style: italic; } +.module { color: #AFD8AF; } +.value_param { color: #DCDCCC; } +.variable { color: #DCDCCC; } +.format_specifier { color: #CC696B; } +.mutable { text-decoration: underline; } +.escape_sequence { color: #94BFF3; } +.keyword { color: #F0DFAF; font-weight: bold; } +.control { font-style: italic; } +.reference { font-style: italic; font-weight: bold; } +.const { font-weight: bolder; } +.unsafe { color: #BC8383; } +.deprecated { text-decoration: line-through; } + +.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } +.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } +</style> +<pre><code><span class="keyword">use</span> <span class="crate_root library">foo</span><span class="operator">::</span><span class="macro library">foo</span><span class="semicolon">;</span> + +</code></pre>
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index f4b1039024..6cb323b46a 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -1601,3 +1601,51 @@ async fn get_double_async(num: u32) -> u32 { false, ); } + +#[test] +fn private_multi_namespace() { + check_highlighting( + r#" +//- /bar.rs crate:bar deps:foo +use foo::foo; + +//- /foo.rs crate:foo +struct foo; + +#[macro_export] +macro_rules! foo { + () => {}; +} + "#, + expect_file!["./test_data/private_multi_namespace.html"], + false, + ); +} + +#[test] +fn mod_and_macro_name_conflict() { + check_highlighting( + r#" +//- /main.rs crate:main deps:foo +use foo::bar; + +fn main() { + bar!() +} + +//- /foo.rs crate:foo +mod bar { + fn random() {} +} + +#[macro_export] +macro_rules! bar { + () => { + println!("Hello"); + }; +} +"#, + expect_file!["./test_data/highlight_module_macro_conflict.html"], + false, + ); +} |