mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 13:15:52 +03:00
Submodules can be private (#8581)
This commit is contained in:
parent
277dfb1991
commit
4cb2439890
@ -1,3 +1,5 @@
|
||||
private
|
||||
|
||||
import project.Any.Any
|
||||
import project.Data.Array.Array
|
||||
import project.Data.Maybe.Maybe
|
||||
|
@ -58,11 +58,11 @@ methods and constructors.
|
||||
Modules can be specified as private. Private modules cannot be imported from
|
||||
other projects. Private modules can be imported from the same project.
|
||||
|
||||
A hierarchy of submodules cannot mix public and private modules. In other words,
|
||||
if a module is public, its whole subtree must be public as well. For example,
|
||||
having a public module `A` and private submodule `A.B` is forbidden and shall be
|
||||
reported as an error during compilation. But having a private module `A` as well
|
||||
as private module `A.B` is OK.
|
||||
A hierarchy of submodules can mix public and private modules. By _hierarchy_, we
|
||||
mean a parent-child relationship between modules. It does not make sense to
|
||||
create a public submodule of a private module and export it, but it is allowed.
|
||||
Note that this is because of current limitations of the implementation, this
|
||||
might be more strict in the future.
|
||||
|
||||
### Types
|
||||
|
||||
|
@ -65,6 +65,7 @@ public final class PrivateModuleAnalysis implements IRPass {
|
||||
List<Import> importErrors = new ArrayList<>();
|
||||
List<Export> exportErrors = new ArrayList<>();
|
||||
var isCurrentModulePrivate = moduleIr.isPrivate();
|
||||
var isCurrentModuleSynthetic = moduleContext.isSynthetic();
|
||||
|
||||
// Ensure that imported modules from a different project are not private.
|
||||
bindingsMap
|
||||
@ -97,38 +98,21 @@ public final class PrivateModuleAnalysis implements IRPass {
|
||||
ImportExport.apply$default$4()));
|
||||
}
|
||||
|
||||
// Ensure that private modules are not exported and that the hierarchy of submodules
|
||||
// does not mix public and private modules.
|
||||
// Ensure that private modules are not exported
|
||||
bindingsMap
|
||||
.getDirectlyExportedModules()
|
||||
.foreach(
|
||||
expModule -> {
|
||||
var expModuleRef = expModule.target().module().unsafeAsModule("should succeed");
|
||||
if (expModuleRef.isPrivate()) {
|
||||
if (expModuleRef.isPrivate() && !isCurrentModuleSynthetic) {
|
||||
var associatedExportIR = findExportIRByName(moduleIr, expModuleRef.getName());
|
||||
assert associatedExportIR.isDefined();
|
||||
if (isSubmoduleName(moduleContext.getName(), expModuleRef.getName())) {
|
||||
var haveSameVisibility = isCurrentModulePrivate == expModuleRef.isPrivate();
|
||||
if (!haveSameVisibility) {
|
||||
exportErrors.add(
|
||||
ImportExport.apply(
|
||||
associatedExportIR.get(),
|
||||
new ImportExport.SubmoduleVisibilityMismatch(
|
||||
moduleContext.getName().toString(),
|
||||
expModuleRef.getName().toString(),
|
||||
isCurrentModulePrivate ? "private" : "public",
|
||||
expModuleRef.isPrivate() ? "private" : "public"),
|
||||
ImportExport.apply$default$3(),
|
||||
ImportExport.apply$default$4()));
|
||||
}
|
||||
} else {
|
||||
exportErrors.add(
|
||||
ImportExport.apply(
|
||||
associatedExportIR.get(),
|
||||
new ImportExport.ExportPrivateModule(expModuleRef.getName().toString()),
|
||||
ImportExport.apply$default$3(),
|
||||
ImportExport.apply$default$4()));
|
||||
}
|
||||
exportErrors.add(
|
||||
ImportExport.apply(
|
||||
associatedExportIR.get(),
|
||||
new ImportExport.ExportPrivateModule(expModuleRef.getName().toString()),
|
||||
ImportExport.apply$default$3(),
|
||||
ImportExport.apply$default$4()));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@ -152,14 +136,6 @@ public final class PrivateModuleAnalysis implements IRPass {
|
||||
moduleIr.id());
|
||||
}
|
||||
|
||||
private boolean isSubmoduleName(QualifiedName parentModName, QualifiedName subModName) {
|
||||
if (subModName.getParent().isDefined()) {
|
||||
return parentModName.item().equals(subModName.getParent().get().item());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression runExpression(Expression ir, InlineContext inlineContext) {
|
||||
return ir;
|
||||
|
@ -1,7 +1,5 @@
|
||||
import project.Sub
|
||||
export project.Sub
|
||||
|
||||
# Fails at compile time - cannot mix private and public modules in a module subtree.
|
||||
|
||||
main =
|
||||
42
|
||||
|
@ -0,0 +1,7 @@
|
||||
name: Test_Private_Modules_6
|
||||
license: APLv2
|
||||
enso-version: default
|
||||
version: "0.0.1"
|
||||
author: "Enso Team <contact@enso.org>"
|
||||
maintainer: "Enso Team <contact@enso.org>"
|
||||
prefer-local-libraries: true
|
@ -0,0 +1,5 @@
|
||||
import project.Sub.Priv
|
||||
|
||||
main =
|
||||
Priv.foo
|
||||
|
@ -0,0 +1,6 @@
|
||||
# This is a private module, that is under a synthetic "Sub" module.
|
||||
# By default, synthetic modules are public.
|
||||
|
||||
private
|
||||
|
||||
foo = 42
|
@ -0,0 +1,7 @@
|
||||
name: Test_Private_Modules_7
|
||||
license: APLv2
|
||||
enso-version: default
|
||||
version: "0.0.1"
|
||||
author: "Enso Team <contact@enso.org>"
|
||||
maintainer: "Enso Team <contact@enso.org>"
|
||||
prefer-local-libraries: true
|
@ -0,0 +1,6 @@
|
||||
import project.Sub.Pub
|
||||
export project.Sub.Pub
|
||||
|
||||
main =
|
||||
Pub.foo
|
||||
|
@ -0,0 +1,4 @@
|
||||
# This is a private parent module
|
||||
|
||||
private
|
||||
|
@ -0,0 +1,2 @@
|
||||
|
||||
foo = 42
|
@ -226,7 +226,7 @@ class ImportsTest extends PackageTest {
|
||||
).toString shouldEqual "42"
|
||||
}
|
||||
|
||||
"Private modules" should "be able to import non-private stuff" in {
|
||||
"Private modules" should "be able to import non-private stuff from different project" in {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_2"
|
||||
).toString shouldEqual "(Pub_Mod_Type.Value 42)"
|
||||
@ -243,13 +243,10 @@ class ImportsTest extends PackageTest {
|
||||
)
|
||||
}
|
||||
|
||||
"Private modules" should "not be able to mix private and public submodules" in {
|
||||
val e = the[InterpreterException] thrownBy evalTestProject(
|
||||
"Private modules" should "be able to mix private and public submodules" in {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_4"
|
||||
)
|
||||
e.getMessage() should include(
|
||||
"Cannot export submodule 'local.Test_Private_Modules_4.Sub.Priv_SubMod' of module 'local.Test_Private_Modules_4.Sub'"
|
||||
)
|
||||
) shouldEqual 42
|
||||
}
|
||||
|
||||
"Private module" should "be able to have only private submodules" in {
|
||||
@ -258,17 +255,22 @@ class ImportsTest extends PackageTest {
|
||||
) shouldEqual 42
|
||||
}
|
||||
|
||||
"Private modules" should "be able to mix private and public submodules when private checks are disabled" in {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_4",
|
||||
Map(RuntimeOptions.DISABLE_PRIVATE_CHECK -> "true")
|
||||
) shouldEqual 42
|
||||
}
|
||||
|
||||
"Private modules" should "be able to import private modules from different project when private checks are disabled" in {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_3",
|
||||
Map(RuntimeOptions.DISABLE_PRIVATE_CHECK -> "true")
|
||||
) shouldEqual "Success"
|
||||
}
|
||||
|
||||
"Private modules" should "be able to have a private submodule under a public synthetic module" in {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_6"
|
||||
) shouldEqual 42
|
||||
}
|
||||
|
||||
"Private modules" should "be able to have a public submodule under a private module" ignore {
|
||||
evalTestProject(
|
||||
"Test_Private_Modules_7"
|
||||
) shouldEqual 42
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user