implements PR013
This commit is contained in:
parent
7dfaf6b49b
commit
c0bccba092
@ -8,5 +8,7 @@ public enum PbsLinkErrors {
|
|||||||
E_LINK_DUPLICATE_BARREL_ENTRY,
|
E_LINK_DUPLICATE_BARREL_ENTRY,
|
||||||
E_LINK_UNRESOLVED_BARREL_ENTRY,
|
E_LINK_UNRESOLVED_BARREL_ENTRY,
|
||||||
E_LINK_AMBIGUOUS_BARREL_ENTRY,
|
E_LINK_AMBIGUOUS_BARREL_ENTRY,
|
||||||
|
E_LINK_IMPORT_MODULE_NOT_FOUND,
|
||||||
|
E_LINK_IMPORT_SYMBOL_UNRESOLVED,
|
||||||
E_LINK_IMPORT_SYMBOL_NOT_PUBLIC
|
E_LINK_IMPORT_SYMBOL_NOT_PUBLIC
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@ public final class PbsModuleVisibilityValidator {
|
|||||||
|
|
||||||
final var barrel = module.barrelFiles().getFirst();
|
final var barrel = module.barrelFiles().getFirst();
|
||||||
final var declarations = collectDeclarations(module, nameTable);
|
final var declarations = collectDeclarations(module, nameTable);
|
||||||
|
exports.declaredNameIds.addAll(declarations.declaredNameIds);
|
||||||
final Map<NonFunctionSymbolKey, Span> seenNonFunctionEntries = new HashMap<>();
|
final Map<NonFunctionSymbolKey, Span> seenNonFunctionEntries = new HashMap<>();
|
||||||
final Map<FunctionSymbolKey, Span> seenFunctionEntries = new HashMap<>();
|
final Map<FunctionSymbolKey, Span> seenFunctionEntries = new HashMap<>();
|
||||||
|
|
||||||
@ -179,20 +180,36 @@ public final class PbsModuleVisibilityValidator {
|
|||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
for (final var source : module.sourceFiles()) {
|
for (final var source : module.sourceFiles()) {
|
||||||
for (final var importDecl : source.ast().imports()) {
|
for (final var importDecl : source.ast().imports()) {
|
||||||
if (importDecl.items().isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final var targetModule = new ModuleRefKey(
|
final var targetModule = new ModuleRefKey(
|
||||||
importDecl.moduleRef().project(),
|
importDecl.moduleRef().project(),
|
||||||
importDecl.moduleRef().pathSegments());
|
importDecl.moduleRef().pathSegments());
|
||||||
final var targetExports = exportsByModule.get(targetModule);
|
final var targetExports = exportsByModule.get(targetModule);
|
||||||
if (targetExports == null) {
|
if (targetExports == null) {
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
||||||
|
PbsLinkErrors.E_LINK_IMPORT_MODULE_NOT_FOUND.name(),
|
||||||
|
"Import target module %s was not found".formatted(displayModule(targetModule)),
|
||||||
|
importDecl.moduleRef().span());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importDecl.items().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final var importItem : importDecl.items()) {
|
for (final var importItem : importDecl.items()) {
|
||||||
final var importedNameId = nameTable.register(importItem.name());
|
final var importedNameId = nameTable.register(importItem.name());
|
||||||
|
if (targetExports.publicNameIds.contains(importedNameId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!targetExports.declaredNameIds.contains(importedNameId)) {
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
||||||
|
PbsLinkErrors.E_LINK_IMPORT_SYMBOL_UNRESOLVED.name(),
|
||||||
|
"Symbol '%s' does not exist in module %s".formatted(
|
||||||
|
importItem.name(),
|
||||||
|
displayModule(targetModule)),
|
||||||
|
importItem.span());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!targetExports.publicNameIds.contains(importedNameId)) {
|
if (!targetExports.publicNameIds.contains(importedNameId)) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
||||||
PbsLinkErrors.E_LINK_IMPORT_SYMBOL_NOT_PUBLIC.name(),
|
PbsLinkErrors.E_LINK_IMPORT_SYMBOL_NOT_PUBLIC.name(),
|
||||||
@ -224,6 +241,7 @@ public final class PbsModuleVisibilityValidator {
|
|||||||
declarations.functionsBySignature
|
declarations.functionsBySignature
|
||||||
.computeIfAbsent(key, ignored -> new ArrayList<>())
|
.computeIfAbsent(key, ignored -> new ArrayList<>())
|
||||||
.add(functionDecl.span());
|
.add(functionDecl.span());
|
||||||
|
declarations.declaredNameIds.add(key.nameId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,6 +277,7 @@ public final class PbsModuleVisibilityValidator {
|
|||||||
declarations.nonFunctionsByKindAndName
|
declarations.nonFunctionsByKindAndName
|
||||||
.computeIfAbsent(key, ignored -> new ArrayList<>())
|
.computeIfAbsent(key, ignored -> new ArrayList<>())
|
||||||
.add(span);
|
.add(span);
|
||||||
|
declarations.declaredNameIds.add(key.nameId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private FunctionSymbolKey functionKey(
|
private FunctionSymbolKey functionKey(
|
||||||
@ -467,9 +486,11 @@ public final class PbsModuleVisibilityValidator {
|
|||||||
private static final class ModuleDeclarations {
|
private static final class ModuleDeclarations {
|
||||||
private final Map<NonFunctionSymbolKey, List<Span>> nonFunctionsByKindAndName = new HashMap<>();
|
private final Map<NonFunctionSymbolKey, List<Span>> nonFunctionsByKindAndName = new HashMap<>();
|
||||||
private final Map<FunctionSymbolKey, List<Span>> functionsBySignature = new HashMap<>();
|
private final Map<FunctionSymbolKey, List<Span>> functionsBySignature = new HashMap<>();
|
||||||
|
private final Set<NameId> declaredNameIds = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ModuleExports {
|
private static final class ModuleExports {
|
||||||
|
private final Set<NameId> declaredNameIds = new HashSet<>();
|
||||||
private final Set<NameId> publicNameIds = new HashSet<>();
|
private final Set<NameId> publicNameIds = new HashSet<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,6 +149,54 @@ class PbsModuleVisibilityTest {
|
|||||||
assertTrue(importVisibilityDiagnostics.getFirst().getMessage().contains("secret"));
|
assertTrue(importVisibilityDiagnostics.getFirst().getMessage().contains("secret"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRejectImportFromMissingModule() {
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
final var nextFileId = new AtomicInteger(0);
|
||||||
|
|
||||||
|
final var moduleApp = module("core", "app", List.of(
|
||||||
|
"""
|
||||||
|
import { open } from @core:missing;
|
||||||
|
fn use() -> int { return 1; }
|
||||||
|
"""
|
||||||
|
), """
|
||||||
|
pub fn use() -> int;
|
||||||
|
""", nextFileId, diagnostics);
|
||||||
|
|
||||||
|
new PbsModuleVisibilityValidator().validate(ReadOnlyList.wrap(List.of(moduleApp)), diagnostics);
|
||||||
|
|
||||||
|
assertTrue(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsLinkErrors.E_LINK_IMPORT_MODULE_NOT_FOUND.name())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRejectImportOfUnknownSymbol() {
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
final var nextFileId = new AtomicInteger(0);
|
||||||
|
|
||||||
|
final var moduleMath = module("core", "math", List.of(
|
||||||
|
"""
|
||||||
|
fn open() -> int { return 2; }
|
||||||
|
"""
|
||||||
|
), """
|
||||||
|
pub fn open() -> int;
|
||||||
|
""", nextFileId, diagnostics);
|
||||||
|
|
||||||
|
final var moduleApp = module("core", "app", List.of(
|
||||||
|
"""
|
||||||
|
import { missing } from @core:math;
|
||||||
|
fn use() -> int { return 1; }
|
||||||
|
"""
|
||||||
|
), """
|
||||||
|
pub fn use() -> int;
|
||||||
|
""", nextFileId, diagnostics);
|
||||||
|
|
||||||
|
new PbsModuleVisibilityValidator().validate(ReadOnlyList.wrap(List.of(moduleMath, moduleApp)), diagnostics);
|
||||||
|
|
||||||
|
assertTrue(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsLinkErrors.E_LINK_IMPORT_SYMBOL_UNRESOLVED.name())));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldResolveBarrelFunctionWithResultReturnSurface() {
|
void shouldResolveBarrelFunctionWithResultReturnSurface() {
|
||||||
final var diagnostics = DiagnosticSink.empty();
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user