From 1e9a9f9c217a89b95a5bdc3b542922283cfc9cb3 Mon Sep 17 00:00:00 2001 From: "Todd V. Jonker" Date: Fri, 28 Aug 2026 17:57:36 -0700 Subject: [PATCH] Move module display into `SourceLocation` This lets `SourceName` satisify the contract of `ResourceDescription.display()` contract by returning (only) the path or URI when it exists. --- .../runtime/base/SourceLocation.java | 21 +++++++++++++------ .../runtime/base/SourceNameImpl.java | 2 +- .../ClassLoaderModuleRepositoryTest.java | 16 ++++++++------ .../ionfusion/fusion/StandardReaderTest.java | 10 +++++++-- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/runtime/src/main/java/dev/ionfusion/runtime/base/SourceLocation.java b/runtime/src/main/java/dev/ionfusion/runtime/base/SourceLocation.java index fed63409e..17abd74f7 100644 --- a/runtime/src/main/java/dev/ionfusion/runtime/base/SourceLocation.java +++ b/runtime/src/main/java/dev/ionfusion/runtime/base/SourceLocation.java @@ -399,17 +399,15 @@ public static SourceLocation forCurrentSpan(IonReader source) public void display(Appendable out) throws IOException { - SourceName name = getSourceName(); long line = getLine(); long column = getColumn(); if (line < 1) { out.append("unknown location"); - if (name != null) + if (!myResource.isUnknown()) { - out.append(" in "); - out.append(name.display()); + out.append(" in ").append(myResource.display()); } } else @@ -424,10 +422,21 @@ public void display(Appendable out) out.append(" column"); } - if (name != null) + if (!myResource.isUnknown()) { out.append(" of "); - out.append(name.display()); + ModuleIdentity module = getModuleIdentity(); + if (module != null) + { + out.append(module.absolutePath()) + .append(" (at ") + .append(myResource.display()) + .append(')'); + } + else + { + out.append(myResource.display()); + } } } } diff --git a/runtime/src/main/java/dev/ionfusion/runtime/base/SourceNameImpl.java b/runtime/src/main/java/dev/ionfusion/runtime/base/SourceNameImpl.java index 031f72b62..a2582bf00 100644 --- a/runtime/src/main/java/dev/ionfusion/runtime/base/SourceNameImpl.java +++ b/runtime/src/main/java/dev/ionfusion/runtime/base/SourceNameImpl.java @@ -125,7 +125,7 @@ static class ModuleSourceName ModuleSourceName(ResourceIdentifier rsrc, ModuleIdentity id) { - super(id + " (at " + rsrc.toString() + ")", rsrc); + super(rsrc); myId = id; } diff --git a/runtime/src/test/java/dev/ionfusion/fusion/ClassLoaderModuleRepositoryTest.java b/runtime/src/test/java/dev/ionfusion/fusion/ClassLoaderModuleRepositoryTest.java index fdc32d0a0..b2b1f6eca 100644 --- a/runtime/src/test/java/dev/ionfusion/fusion/ClassLoaderModuleRepositoryTest.java +++ b/runtime/src/test/java/dev/ionfusion/fusion/ClassLoaderModuleRepositoryTest.java @@ -8,6 +8,11 @@ import static dev.ionfusion.fusion.StandardReader.openIonReader; import static dev.ionfusion.testing.ProjectLayout.PROJECT_DIRECTORY; import static dev.ionfusion.testing.ProjectLayout.testRepositoryDirectory; +import static java.nio.file.Files.isRegularFile; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -17,7 +22,6 @@ import dev.ionfusion.runtime.base.SourceName; import java.net.URL; import java.net.URLClassLoader; -import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; @@ -49,7 +53,7 @@ private void checkActualModule(ModuleRepository repo) assertNotNull(loc.toString()); SourceName name = loc.sourceName(); - assertTrue(name.display().contains("/ftst/symbol.fusion")); + assertThat(name.display(), endsWith("/ftst/symbol.fusion")); Evaluator eval = evaluator(); IonReader ionReader = openIonReader(eval, name.getResourceId()); @@ -77,10 +81,10 @@ public void loadModuleFromDirectory() Path dir = testRepositoryDirectory(); URL url = dir.toUri().toURL(); - assert url.getProtocol().equals("file"); + assertEquals("file", url.getProtocol()); // Precondition for URLClassLoader to treat the URL as a directory: - assert url.getFile().endsWith("/"); + assertThat(url.getFile(), endsWith("/")); checkRepository(url, "."); } @@ -96,12 +100,12 @@ public void loadModuleFromJar() Path jar = PROJECT_DIRECTORY.resolve("build") .resolve("libs") .resolve("ftst-repo.jar"); - assert Files.isRegularFile(jar); + assertTrue(isRegularFile(jar), "regular file"); URL url = jar.toUri().toURL(); // Precondition for URLClassLoader to treat the URL as a JAR file: - assert ! url.getFile().endsWith("/"); + assertThat(url.getFile(), not(endsWith("/"))); checkRepository(url, "FUSION-REPO"); } diff --git a/runtime/src/test/java/dev/ionfusion/fusion/StandardReaderTest.java b/runtime/src/test/java/dev/ionfusion/fusion/StandardReaderTest.java index b097387cc..0a37bc4d1 100644 --- a/runtime/src/test/java/dev/ionfusion/fusion/StandardReaderTest.java +++ b/runtime/src/test/java/dev/ionfusion/fusion/StandardReaderTest.java @@ -4,8 +4,12 @@ package dev.ionfusion.fusion; import static dev.ionfusion.fusion.FusionStruct.unsafeStructSize; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; + import com.amazon.ion.IonReader; import org.junit.jupiter.api.Test; @@ -23,7 +27,9 @@ public void testIonSyntaxError() Throwable e = assertEvalThrows(FusionErrorException.class, "(require '''/malformed/ion_syntax_error''')"); - assertTrue(e.getMessage().contains("Error reading /malformed/ion_syntax_error")); + assertThat(e.getMessage(), + allOf(startsWith("Error reading "), + containsString("/malformed/ion_syntax_error.fusion"))); } @Test