Description
After commit ba53bc1 ("refactor(visibility): improve type visibility"), emmylua_check produces false positive warnings like:
warning: module 'global' visibility is not `public` [require-module-not-visible]
This happens when a project has a file (e.g. global.lua) that shares the same module name as an internal EmmyLua file (e.g. the built-in global.lua in std/library workspace).
Root Cause Analysis
The issue has two layers:
1. exact_find_module does not prioritize by workspace
In LuaModuleIndex::exact_find_module, when multiple files map to the same module path, it simply returns file_ids.first():
let node = self.module_nodes.get(&parent_node_id)?;
let file_id = node.file_ids.first()?; // No priority — just the first registered file
self.file_module_map.get(file_id)
The ModuleNode::file_ids is a Vec<FileId> populated via push() in registration order. There is no sorting or priority based on workspace type (main vs. library vs. std). So whichever file gets registered first wins.
2. New visibility model is stricter for cross-workspace Internal modules
The old check_export_visibility treated modules without @export as visible by default (unless require_export_global was enabled). The new check_module_visibility + is_requireable_from applies stricter rules:
ModuleVisibility::Internal => {
(!self.workspace_id.is_library() && !workspace_id.is_library())
|| self.workspace_id == workspace_id
}
When find_module resolves to the wrong file (e.g. a library/std global.lua marked Internal), and the requiring file is in the main workspace, this check fails → false require-module-not-visible warning.
Suggested Fix
As an LLM that analyzed the codebase, I would suggest adding workspace-aware priority to exact_find_module. When ModuleNode.file_ids contains multiple entries, prefer the main workspace file over library/std files:
fn exact_find_module(&self, module_parts: &Vec<&str>) -> Option<&ModuleInfo> {
let mut parent_node_id = self.module_root_id;
for part in module_parts {
let parent_node = self.module_nodes.get(&parent_node_id)?;
let child_id = match parent_node.children.get(*part) {
Some(id) => *id,
None => return None,
};
parent_node_id = child_id;
}
let node = self.module_nodes.get(&parent_node_id)?;
// When only one file, fast path
if node.file_ids.len() == 1 {
let file_id = node.file_ids.first()?;
return self.file_module_map.get(file_id);
}
// When multiple files share the same module path,
// prioritize: main > library > std
node.file_ids
.iter()
.filter_map(|fid| self.file_module_map.get(fid))
.min_by_key(|info| match info.workspace_id {
id if id.is_main() => 0,
id if id.is_library() => 1,
_ => 2,
})
}
Alternatively, the require_module_visibility checker could iterate over all candidate files for a module path and only report the warning if none of them are visible.
cc @xuhuanzy
Description
After commit ba53bc1 ("refactor(visibility): improve type visibility"),
emmylua_checkproduces false positive warnings like:This happens when a project has a file (e.g.
global.lua) that shares the same module name as an internal EmmyLua file (e.g. the built-inglobal.luain std/library workspace).Root Cause Analysis
The issue has two layers:
1.
exact_find_moduledoes not prioritize by workspaceIn
LuaModuleIndex::exact_find_module, when multiple files map to the same module path, it simply returnsfile_ids.first():The
ModuleNode::file_idsis aVec<FileId>populated viapush()in registration order. There is no sorting or priority based on workspace type (main vs. library vs. std). So whichever file gets registered first wins.2. New visibility model is stricter for cross-workspace
InternalmodulesThe old
check_export_visibilitytreated modules without@exportas visible by default (unlessrequire_export_globalwas enabled). The newcheck_module_visibility+is_requireable_fromapplies stricter rules:When
find_moduleresolves to the wrong file (e.g. a library/stdglobal.luamarkedInternal), and the requiring file is in the main workspace, this check fails → falserequire-module-not-visiblewarning.Suggested Fix
As an LLM that analyzed the codebase, I would suggest adding workspace-aware priority to
exact_find_module. WhenModuleNode.file_idscontains multiple entries, prefer the main workspace file over library/std files:Alternatively, the
require_module_visibilitychecker could iterate over all candidate files for a module path and only report the warning if none of them are visible.cc @xuhuanzy