From 1c7c67060da6a1ce832222de64f1fbf0ecec1797 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 12 Oct 2021 23:54:48 +0200 Subject: [PATCH] better result and error handling for importModule() --- compiler/src/prog8/compiler/Compiler.kt | 3 +- compiler/src/prog8/compiler/ModuleImporter.kt | 11 ++-- compiler/test/ModuleImporterTests.kt | 60 +++++++++---------- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 5015f9fc2..6f67e2e87 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -181,7 +181,8 @@ fun parseImports(filepath: Path, bf.program = programAst val importer = ModuleImporter(programAst, compTarget.name, errors, libdirs) - importer.importModule(filepath) + val importedModuleResult = importer.importModule(filepath) + importedModuleResult.onFailure { throw it } errors.report() val importedFiles = programAst.modules diff --git a/compiler/src/prog8/compiler/ModuleImporter.kt b/compiler/src/prog8/compiler/ModuleImporter.kt index a0555ad37..a4f5344ee 100644 --- a/compiler/src/prog8/compiler/ModuleImporter.kt +++ b/compiler/src/prog8/compiler/ModuleImporter.kt @@ -1,5 +1,8 @@ package prog8.compiler +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result import prog8.ast.Module import prog8.ast.Program import prog8.ast.base.Position @@ -19,7 +22,7 @@ class ModuleImporter(private val program: Program, private val libpaths: List = libdirs.map { Path(it) } - fun importModule(filePath: Path): Module { + fun importModule(filePath: Path): Result { val currentDir = Path("").absolute() val searchIn = listOf(currentDir) + libpaths val candidates = searchIn @@ -29,9 +32,9 @@ class ModuleImporter(private val program: Program, .map { if (it.isAbsolute) it else Path(".", "$it") } val srcPath = when (candidates.size) { - 0 -> throw NoSuchFileException( + 0 -> return Err(NoSuchFileException( file = filePath.normalize().toFile(), - reason = "searched in $searchIn") + reason = "searched in $searchIn")) 1 -> candidates.first() else -> candidates.first() // TODO: report error if more than 1 candidate? } @@ -39,7 +42,7 @@ class ModuleImporter(private val program: Program, val logMsg = "importing '${filePath.nameWithoutExtension}' (from file $srcPath)" println(logMsg) - return importModule(SourceCode.fromPath(srcPath)) + return Ok(importModule(SourceCode.fromPath(srcPath))) } fun importLibraryModule(name: String): Module? { diff --git a/compiler/test/ModuleImporterTests.kt b/compiler/test/ModuleImporterTests.kt index f39f9096b..49c23c0cd 100644 --- a/compiler/test/ModuleImporterTests.kt +++ b/compiler/test/ModuleImporterTests.kt @@ -1,19 +1,22 @@ package prog8tests +import kotlin.test.* +import com.github.michaelbull.result.getErrorOrElse +import com.github.michaelbull.result.getOrElse import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.* import org.hamcrest.core.Is -import org.junit.jupiter.api.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.Disabled import prog8.ast.Program import prog8.compiler.IErrorReporter import prog8.compiler.ModuleImporter import prog8.parser.ParseError import prog8tests.helpers.* import kotlin.io.path.* -import kotlin.test.assertContains -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -60,31 +63,26 @@ class TestModuleImporter { val importer = makeImporter(null, dirRel.invariantSeparatorsPathString) val srcPathRel = assumeNotExists(dirRel, "i_do_not_exist") val srcPathAbs = srcPathRel.absolute() - - assertFailsWith { importer.importModule(srcPathRel) } - .let { - assertThat( - ".file should be normalized", - "${it.file}", equalTo("${it.file.normalize()}") - ) - assertThat( - ".file should point to specified path", - it.file.absolutePath, equalTo("${srcPathAbs.normalize()}") - ) - } + val error1 = importer.importModule(srcPathRel).getErrorOrElse { fail("should have import error") } + assertThat( + ".file should be normalized", + "${error1.file}", equalTo("${error1.file.normalize()}") + ) + assertThat( + ".file should point to specified path", + error1.file.absolutePath, equalTo("${srcPathAbs.normalize()}") + ) assertThat(program.modules.size, equalTo(1)) - assertFailsWith { importer.importModule(srcPathAbs) } - .let { - assertThat( - ".file should be normalized", - "${it.file}", equalTo("${it.file.normalize()}") - ) - assertThat( - ".file should point to specified path", - it.file.absolutePath, equalTo("${srcPathAbs.normalize()}") - ) - } + val error2 = importer.importModule(srcPathAbs).getErrorOrElse { fail("should have import error") } + assertThat( + ".file should be normalized", + "${error2.file}", equalTo("${error2.file.normalize()}") + ) + assertThat( + ".file should point to specified path", + error2.file.absolutePath, equalTo("${srcPathAbs.normalize()}") + ) assertThat(program.modules.size, equalTo(1)) } @@ -135,7 +133,7 @@ class TestModuleImporter { val fileName = "simple_main.p8" val path = assumeReadableFile(searchIn[0], fileName) - val module = importer.importModule(path.absolute()) + val module = importer.importModule(path.absolute()).getOrElse { throw it } assertThat(program.modules.size, equalTo(2)) assertContains(program.modules, module) assertThat(module.program, equalTo(program)) @@ -151,7 +149,7 @@ class TestModuleImporter { val path = assumeReadableFile(searchIn[0], fileName) assertThat("sanity check: path should NOT be absolute", path.isAbsolute, equalTo(false)) - val module = importer.importModule(path) + val module = importer.importModule(path).getOrElse { throw it } assertThat(program.modules.size, equalTo(2)) assertContains(program.modules, module) assertThat(module.program, equalTo(program)) @@ -167,7 +165,7 @@ class TestModuleImporter { val path = Path(".", fileName) assumeReadableFile(searchIn, path) - val module = importer.importModule(path) + val module = importer.importModule(path).getOrElse { throw it } assertThat(program.modules.size, equalTo(2)) assertContains(program.modules, module) assertThat(module.program, equalTo(program))