Hide alias (#4432)

* Add alias interning

Now, AliasId is used to reference aliases stored in EngineState, similar
to decls, blocks, etc.

* Fix wrong message

* Fix using decl instead of alias

* Extend also alias id visibility

* Merge also aliases from delta

* Add alias hiding code

Does not work yet but passes tests at least.

* Fix wrong alias lookup and visibility appending

* Add hide alias tests

* Fmt & Clippy

* Fix random clippy warnings in "which" command
This commit is contained in:
Jakub Žádník
2022-02-12 11:50:37 +02:00
committed by GitHub
parent fcc13224c1
commit 328f7e92a0
9 changed files with 378 additions and 57 deletions

View File

@ -1320,14 +1320,21 @@ pub fn parse_hide(
if let Some(overlay_id) = working_set.find_overlay(&import_pattern.head.name) {
(true, working_set.get_overlay(overlay_id).clone())
} else if import_pattern.members.is_empty() {
// The pattern head can be e.g. a function name, not just a module
if let Some(id) = working_set.find_decl(&import_pattern.head.name) {
// The pattern head can be:
if let Some(id) = working_set.find_alias(&import_pattern.head.name) {
// an alias,
let mut overlay = Overlay::new();
overlay.add_alias(&import_pattern.head.name, id);
(false, overlay)
} else if let Some(id) = working_set.find_decl(&import_pattern.head.name) {
// a custom command,
let mut overlay = Overlay::new();
overlay.add_decl(&import_pattern.head.name, id);
(false, overlay)
} else {
// Or it could be an env var
// , or it could be an env var (handled by the engine)
(false, Overlay::new())
}
} else {
@ -1338,49 +1345,71 @@ pub fn parse_hide(
};
// This kind of inverts the import pattern matching found in parse_use()
let decls_to_hide = if import_pattern.members.is_empty() {
let (aliases_to_hide, decls_to_hide) = if import_pattern.members.is_empty() {
if is_module {
overlay.decls_with_head(&import_pattern.head.name)
(
overlay.alias_names_with_head(&import_pattern.head.name),
overlay.decl_names_with_head(&import_pattern.head.name),
)
} else {
overlay.decls()
(overlay.alias_names(), overlay.decl_names())
}
} else {
match &import_pattern.members[0] {
ImportPatternMember::Glob { .. } => overlay.decls(),
ImportPatternMember::Glob { .. } => (overlay.alias_names(), overlay.decl_names()),
ImportPatternMember::Name { name, span } => {
let mut output = vec![];
let mut aliases = vec![];
let mut decls = vec![];
if let Some(item) = overlay.decl_with_head(name, &import_pattern.head.name) {
output.push(item);
if let Some(item) =
overlay.alias_name_with_head(name, &import_pattern.head.name)
{
aliases.push(item);
} else if let Some(item) =
overlay.decl_name_with_head(name, &import_pattern.head.name)
{
decls.push(item);
} else if !overlay.has_env_var(name) {
error = error.or(Some(ParseError::ExportNotFound(*span)));
}
output
(aliases, decls)
}
ImportPatternMember::List { names } => {
let mut output = vec![];
let mut aliases = vec![];
let mut decls = vec![];
for (name, span) in names {
if let Some(item) = overlay.decl_with_head(name, &import_pattern.head.name)
if let Some(item) =
overlay.alias_name_with_head(name, &import_pattern.head.name)
{
output.push(item);
aliases.push(item);
} else if let Some(item) =
overlay.decl_name_with_head(name, &import_pattern.head.name)
{
decls.push(item);
} else if !overlay.has_env_var(name) {
error = error.or(Some(ParseError::ExportNotFound(*span)));
break;
}
}
output
(aliases, decls)
}
}
};
let import_pattern = {
let aliases: HashSet<Vec<u8>> = aliases_to_hide.iter().cloned().collect();
let decls: HashSet<Vec<u8>> = decls_to_hide.iter().cloned().collect();
import_pattern.with_hidden(decls.union(&aliases).cloned().collect())
};
// TODO: `use spam; use spam foo; hide foo` will hide both `foo` and `spam foo` since
// they point to the same DeclId. Do we want to keep it that way?
working_set.hide_decls(&decls_to_hide);
let import_pattern = import_pattern
.with_hidden(decls_to_hide.iter().map(|(name, _)| name.clone()).collect());
working_set.hide_aliases(&aliases_to_hide);
// Create a new Use command call to pass the new import pattern
let import_pattern_expr = Expression {

View File

@ -828,9 +828,11 @@ pub fn parse_call(
if expand_aliases {
// If the word is an alias, expand it and re-parse the expression
if let Some(expansion) = working_set.find_alias(&name) {
if let Some(alias_id) = working_set.find_alias(&name) {
trace!("expanding alias");
let expansion = working_set.get_alias(alias_id);
let orig_span = spans[pos];
let mut new_spans: Vec<Span> = vec![];
new_spans.extend(&spans[0..pos]);