better result and error handling for importModule()

This commit is contained in:
Irmen de Jong 2021-10-12 23:54:48 +02:00
parent 9827ee97ad
commit 1c7c67060d
3 changed files with 38 additions and 36 deletions

View File

@ -181,7 +181,8 @@ fun parseImports(filepath: Path,
bf.program = programAst bf.program = programAst
val importer = ModuleImporter(programAst, compTarget.name, errors, libdirs) val importer = ModuleImporter(programAst, compTarget.name, errors, libdirs)
importer.importModule(filepath) val importedModuleResult = importer.importModule(filepath)
importedModuleResult.onFailure { throw it }
errors.report() errors.report()
val importedFiles = programAst.modules val importedFiles = programAst.modules

View File

@ -1,5 +1,8 @@
package prog8.compiler 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.Module
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.Position import prog8.ast.base.Position
@ -19,7 +22,7 @@ class ModuleImporter(private val program: Program,
private val libpaths: List<Path> = libdirs.map { Path(it) } private val libpaths: List<Path> = libdirs.map { Path(it) }
fun importModule(filePath: Path): Module { fun importModule(filePath: Path): Result<Module, NoSuchFileException> {
val currentDir = Path("").absolute() val currentDir = Path("").absolute()
val searchIn = listOf(currentDir) + libpaths val searchIn = listOf(currentDir) + libpaths
val candidates = searchIn val candidates = searchIn
@ -29,9 +32,9 @@ class ModuleImporter(private val program: Program,
.map { if (it.isAbsolute) it else Path(".", "$it") } .map { if (it.isAbsolute) it else Path(".", "$it") }
val srcPath = when (candidates.size) { val srcPath = when (candidates.size) {
0 -> throw NoSuchFileException( 0 -> return Err(NoSuchFileException(
file = filePath.normalize().toFile(), file = filePath.normalize().toFile(),
reason = "searched in $searchIn") reason = "searched in $searchIn"))
1 -> candidates.first() 1 -> candidates.first()
else -> candidates.first() // TODO: report error if more than 1 candidate? 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)" val logMsg = "importing '${filePath.nameWithoutExtension}' (from file $srcPath)"
println(logMsg) println(logMsg)
return importModule(SourceCode.fromPath(srcPath)) return Ok(importModule(SourceCode.fromPath(srcPath)))
} }
fun importLibraryModule(name: String): Module? { fun importLibraryModule(name: String): Module? {

View File

@ -1,19 +1,22 @@
package prog8tests 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.MatcherAssert.assertThat
import org.hamcrest.Matchers.* import org.hamcrest.Matchers.*
import org.hamcrest.core.Is 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.ast.Program
import prog8.compiler.IErrorReporter import prog8.compiler.IErrorReporter
import prog8.compiler.ModuleImporter import prog8.compiler.ModuleImporter
import prog8.parser.ParseError import prog8.parser.ParseError
import prog8tests.helpers.* import prog8tests.helpers.*
import kotlin.io.path.* 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) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ -60,31 +63,26 @@ class TestModuleImporter {
val importer = makeImporter(null, dirRel.invariantSeparatorsPathString) val importer = makeImporter(null, dirRel.invariantSeparatorsPathString)
val srcPathRel = assumeNotExists(dirRel, "i_do_not_exist") val srcPathRel = assumeNotExists(dirRel, "i_do_not_exist")
val srcPathAbs = srcPathRel.absolute() val srcPathAbs = srcPathRel.absolute()
val error1 = importer.importModule(srcPathRel).getErrorOrElse { fail("should have import error") }
assertFailsWith<NoSuchFileException> { importer.importModule(srcPathRel) } assertThat(
.let { ".file should be normalized",
assertThat( "${error1.file}", equalTo("${error1.file.normalize()}")
".file should be normalized", )
"${it.file}", equalTo("${it.file.normalize()}") assertThat(
) ".file should point to specified path",
assertThat( error1.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
".file should point to specified path", )
it.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
)
}
assertThat(program.modules.size, equalTo(1)) assertThat(program.modules.size, equalTo(1))
assertFailsWith<NoSuchFileException> { importer.importModule(srcPathAbs) } val error2 = importer.importModule(srcPathAbs).getErrorOrElse { fail("should have import error") }
.let { assertThat(
assertThat( ".file should be normalized",
".file should be normalized", "${error2.file}", equalTo("${error2.file.normalize()}")
"${it.file}", equalTo("${it.file.normalize()}") )
) assertThat(
assertThat( ".file should point to specified path",
".file should point to specified path", error2.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
it.file.absolutePath, equalTo("${srcPathAbs.normalize()}") )
)
}
assertThat(program.modules.size, equalTo(1)) assertThat(program.modules.size, equalTo(1))
} }
@ -135,7 +133,7 @@ class TestModuleImporter {
val fileName = "simple_main.p8" val fileName = "simple_main.p8"
val path = assumeReadableFile(searchIn[0], fileName) 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)) assertThat(program.modules.size, equalTo(2))
assertContains(program.modules, module) assertContains(program.modules, module)
assertThat(module.program, equalTo(program)) assertThat(module.program, equalTo(program))
@ -151,7 +149,7 @@ class TestModuleImporter {
val path = assumeReadableFile(searchIn[0], fileName) val path = assumeReadableFile(searchIn[0], fileName)
assertThat("sanity check: path should NOT be absolute", path.isAbsolute, equalTo(false)) 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)) assertThat(program.modules.size, equalTo(2))
assertContains(program.modules, module) assertContains(program.modules, module)
assertThat(module.program, equalTo(program)) assertThat(module.program, equalTo(program))
@ -167,7 +165,7 @@ class TestModuleImporter {
val path = Path(".", fileName) val path = Path(".", fileName)
assumeReadableFile(searchIn, path) assumeReadableFile(searchIn, path)
val module = importer.importModule(path) val module = importer.importModule(path).getOrElse { throw it }
assertThat(program.modules.size, equalTo(2)) assertThat(program.modules.size, equalTo(2))
assertContains(program.modules, module) assertContains(program.modules, module)
assertThat(module.program, equalTo(program)) assertThat(module.program, equalTo(program))