diff --git a/pom.xml b/pom.xml
index c05f3ef..5e646ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
UTF-8
- 1.2.31
+ 1.2.41
5.1.0
false
diff --git a/src/main/kotlin/error/Severity.kt b/src/main/kotlin/error/Severity.kt
index 91e048d..761d476 100644
--- a/src/main/kotlin/error/Severity.kt
+++ b/src/main/kotlin/error/Severity.kt
@@ -6,21 +6,21 @@ enum class Severity {
WARNING {
override fun decorate(output: String, environment: RuntimeEnvironment): String =
- RuntimeEnvironment.decorateWarningOutput(output)!!
+ RuntimeEnvironment.decorateWarningOutput(output)
override fun toDisplayString() = "warning"
},
ERROR {
override fun decorate(output: String, environment: RuntimeEnvironment): String =
- RuntimeEnvironment.decorateErrorOutput(output)!!
+ RuntimeEnvironment.decorateErrorOutput(output)
override fun toDisplayString() = "error"
},
CRITICAL {
override fun decorate(output: String, environment: RuntimeEnvironment): String =
- RuntimeEnvironment.decorateCriticalOutput(output)!!
+ RuntimeEnvironment.decorateCriticalOutput(output)
override fun toDisplayString() = "critical"
};
diff --git a/src/main/kotlin/file/FilePosition.java b/src/main/kotlin/file/FilePosition.java
deleted file mode 100644
index 83cf0e1..0000000
--- a/src/main/kotlin/file/FilePosition.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package file;
-
-public class FilePosition {
-
- private String fileName;
- private int lineNumber;
- private int columnNumber;
-
- public FilePosition(String fileName) {
- this.fileName = fileName;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public int getLineNumber() {
- return lineNumber;
- }
-
- public void setLineNumber(int lineNumber) {
- this.lineNumber = lineNumber;
- }
-
- public int getColumnNumber() {
- return columnNumber;
- }
-
- public void setColumnNumber(int columnNumber) {
- this.columnNumber = columnNumber;
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/file/FilePosition.kt b/src/main/kotlin/file/FilePosition.kt
new file mode 100644
index 0000000..3332798
--- /dev/null
+++ b/src/main/kotlin/file/FilePosition.kt
@@ -0,0 +1,3 @@
+package file
+
+data class FilePosition(val fileName: String, val lineNumber: Int, val columnNumber: Int)
\ No newline at end of file
diff --git a/src/main/kotlin/file/FilePositionTracker.java b/src/main/kotlin/file/FilePositionTracker.java
deleted file mode 100644
index bf6c33e..0000000
--- a/src/main/kotlin/file/FilePositionTracker.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package file;
-
-public class FilePositionTracker {
-
- private String fileName;
- private int lineNumber;
- private int columnNumber;
-
- public FilePositionTracker(String fileName) {
- this.fileName = fileName;
- this.lineNumber = 1;
- this.columnNumber = 0;
- }
-
- public FilePosition getCurrentPosition() {
- FilePosition currentPosition = new FilePosition(fileName);
- currentPosition.setLineNumber(lineNumber);
- currentPosition.setColumnNumber(columnNumber);
-
- return currentPosition;
- }
-
- public void incrementColumn() {
- columnNumber++;
- }
-
- public void incrementLine() {
- lineNumber++;
- columnNumber = 0;
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/file/FilePositionTracker.kt b/src/main/kotlin/file/FilePositionTracker.kt
new file mode 100644
index 0000000..06b2f36
--- /dev/null
+++ b/src/main/kotlin/file/FilePositionTracker.kt
@@ -0,0 +1,18 @@
+package file
+
+class FilePositionTracker(private val fileName: String) {
+
+ private var lineNumber = 1
+ private var columnNumber = 0
+
+ fun currentPosition() = FilePosition(fileName = fileName, lineNumber = lineNumber, columnNumber = columnNumber)
+
+ fun incrementColumn() {
+ columnNumber++
+ }
+
+ fun incrementLine() {
+ lineNumber++
+ columnNumber = 0
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/interpreter/LispInterpreterBuilder.kt b/src/main/kotlin/interpreter/LispInterpreterBuilder.kt
index d57630b..f57b0ff 100644
--- a/src/main/kotlin/interpreter/LispInterpreterBuilder.kt
+++ b/src/main/kotlin/interpreter/LispInterpreterBuilder.kt
@@ -77,7 +77,7 @@ object LispInterpreterBuilder {
this.languageFiles = ArrayList()
for (fileName in languageFiles)
- this.languageFiles!!.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
+ this.languageFiles.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
}
fun setTerminationFunction(terminationFunction: () -> Unit) {
@@ -135,7 +135,7 @@ object LispInterpreterBuilder {
private fun configurePath() {
if (isFileBased)
- RuntimeEnvironment.path = Path.getPathPrefix(inputName!!)
+ RuntimeEnvironment.path = Path.getPathPrefix(inputName)
else
RuntimeEnvironment.path = ""
}
diff --git a/src/main/kotlin/scanner/LispScanner.java b/src/main/kotlin/scanner/LispScanner.java
index 74efabb..e4030f7 100644
--- a/src/main/kotlin/scanner/LispScanner.java
+++ b/src/main/kotlin/scanner/LispScanner.java
@@ -40,11 +40,11 @@ public class LispScanner {
positionTracker.incrementLine();
}
- return tokenFactory.createEofToken(positionTracker.getCurrentPosition());
+ return tokenFactory.createEofToken(positionTracker.currentPosition());
}
private Token createTokenFromCharacter(char c) {
- FilePosition currentPosition = positionTracker.getCurrentPosition();
+ FilePosition currentPosition = positionTracker.currentPosition();
String tokenText = retrieveTokenText(c);
return tokenFactory.createToken(tokenText, currentPosition);
@@ -107,7 +107,7 @@ public class LispScanner {
public ComplexTokenTextRetriever(char firstCharacter, Function isPartOfToken) {
this.isPartOfToken = isPartOfToken;
this.text = new StringBuilder();
- this.position = positionTracker.getCurrentPosition();
+ this.position = positionTracker.currentPosition();
this.firstCharacter = firstCharacter;
this.currentCharacter = firstCharacter;
this.previousCharacter = firstCharacter;
diff --git a/src/test/kotlin/application/MainTest.kt b/src/test/kotlin/application/MainTest.kt
index b5a063e..ecf75ed 100644
--- a/src/test/kotlin/application/MainTest.kt
+++ b/src/test/kotlin/application/MainTest.kt
@@ -89,7 +89,7 @@ class MainTest : SymbolAndFunctionCleaner() {
}
@Test
- fun runWithBadFile() {
+ fun `bad file displays correct error message`() {
val expectedMessage = "[critical] bad.lisp (No such file or directory)"
exit.expectSystemExitWithStatus(1)
@@ -102,7 +102,7 @@ class MainTest : SymbolAndFunctionCleaner() {
}
@Test
- fun runWithFile_PrintsDecoratedLastValueOnly() {
+ fun `interpret file prints the decorated last value only`() {
runInterpreterWithFile(FILE)
assertEquals("", systemErrLog())
@@ -110,7 +110,7 @@ class MainTest : SymbolAndFunctionCleaner() {
}
@Test
- fun runInteractive() {
+ fun `run interactive interpreter`() {
val terminal = runInterpreterAndGetInteractor()
terminal.waitForPrompt()
diff --git a/src/test/kotlin/environment/RuntimeEnvironmentTest.kt b/src/test/kotlin/environment/RuntimeEnvironmentTest.kt
index 2d87826..e1d21d9 100644
--- a/src/test/kotlin/environment/RuntimeEnvironmentTest.kt
+++ b/src/test/kotlin/environment/RuntimeEnvironmentTest.kt
@@ -90,7 +90,7 @@ class RuntimeEnvironmentTest {
}
@Test
- fun `assing a prompt decorator`() {
+ fun `assign a prompt decorator`() {
RuntimeEnvironment.promptDecorator = { "[$it]" }
assertThat(RuntimeEnvironment.decoratePrompt("test")).isEqualTo("[test]")
diff --git a/src/test/kotlin/file/FilePositionTrackerTest.java b/src/test/kotlin/file/FilePositionTrackerTest.java
deleted file mode 100644
index 882705f..0000000
--- a/src/test/kotlin/file/FilePositionTrackerTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package file;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Objects;
-
-import static org.junit.Assert.assertTrue;
-
-public class FilePositionTrackerTest {
-
- public static final String FILE_NAME = "testFile";
-
- private FilePositionTracker trackerUnderTest;
-
- private FilePosition createFilePosition(int lineNumber, int columnNumber) {
- FilePosition position = new FilePosition(FILE_NAME);
- position.setLineNumber(lineNumber);
- position.setColumnNumber(columnNumber);
-
- return position;
- }
-
- private void assertTrackerPositionEquals(FilePosition expectedPosition) {
- assertTrue(arePositionsEqual(expectedPosition, trackerUnderTest.getCurrentPosition()));
- }
-
- private boolean arePositionsEqual(FilePosition position1, FilePosition position2) {
- return Objects.equals(position1.getFileName(), position2.getFileName())
- && Objects.equals(position1.getLineNumber(), position2.getLineNumber())
- && Objects.equals(position1.getColumnNumber(), position2.getColumnNumber());
- }
-
- @Before
- public void setUp() {
- trackerUnderTest = new FilePositionTracker(FILE_NAME);
- }
-
- @Test
- public void noMovement_ReturnsInitialPosition() {
- assertTrackerPositionEquals(createFilePosition(1, 0));
- }
-
- @Test
- public void advanceOneColumn_ReturnsCorrectPosition() {
- trackerUnderTest.incrementColumn();
-
- assertTrackerPositionEquals(createFilePosition(1, 1));
- }
-
- @Test
- public void advanceOneLine_ReturnsCorrectPosition() {
- trackerUnderTest.incrementLine();
-
- assertTrackerPositionEquals(createFilePosition(2, 0));
- }
-
- @Test
- public void advanceOneLine_ResetsColumn() {
- trackerUnderTest.incrementColumn();
- trackerUnderTest.incrementLine();
-
- assertTrackerPositionEquals(createFilePosition(2, 0));
- }
-}
diff --git a/src/test/kotlin/file/FilePositionTrackerTest.kt b/src/test/kotlin/file/FilePositionTrackerTest.kt
new file mode 100644
index 0000000..c4ddf5d
--- /dev/null
+++ b/src/test/kotlin/file/FilePositionTrackerTest.kt
@@ -0,0 +1,58 @@
+package file
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.TestInstance
+import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
+
+@TestInstance(PER_CLASS)
+class FilePositionTrackerTest {
+
+ companion object {
+ const val FILE_NAME = "testFile"
+ }
+
+ private lateinit var trackerUnderTest: FilePositionTracker
+
+ private fun createFilePosition(lineNumber: Int, columnNumber: Int): FilePosition {
+ return FilePosition(FILE_NAME, lineNumber, columnNumber)
+ }
+
+ private fun assertTrackerPositionEquals(expectedPosition: FilePosition) {
+ assertThat(trackerUnderTest.currentPosition()).isEqualTo(expectedPosition)
+ }
+
+ @BeforeEach
+ fun setUp() {
+ trackerUnderTest = FilePositionTracker(FILE_NAME)
+ }
+
+ @Test
+ fun noMovement_ReturnsInitialPosition() {
+ assertTrackerPositionEquals(createFilePosition(1, 0))
+ }
+
+ @Test
+ fun advanceOneColumn_ReturnsCorrectPosition() {
+ trackerUnderTest.incrementColumn()
+
+ assertTrackerPositionEquals(createFilePosition(1, 1))
+ }
+
+ @Test
+ fun advanceOneLine_ReturnsCorrectPosition() {
+ trackerUnderTest.incrementLine()
+
+ assertTrackerPositionEquals(createFilePosition(2, 0))
+ }
+
+ @Test
+ fun advanceOneLine_ResetsColumn() {
+ trackerUnderTest.incrementColumn()
+ trackerUnderTest.incrementLine()
+
+ assertTrackerPositionEquals(createFilePosition(2, 0))
+ }
+
+}
diff --git a/src/test/kotlin/interpreter/LispInterpreterTest.kt b/src/test/kotlin/interpreter/LispInterpreterTest.kt
index e3b063a..67ae1e2 100644
--- a/src/test/kotlin/interpreter/LispInterpreterTest.kt
+++ b/src/test/kotlin/interpreter/LispInterpreterTest.kt
@@ -16,52 +16,50 @@ import java.util.HashSet
class LispInterpreterTest {
- private var indicatorSet: MutableSet? = null
- private var outputStream: ByteArrayOutputStream? = null
- private var errorOutputStream: ByteArrayOutputStream? = null
- private val environment: RuntimeEnvironment
- private val builder: LispInterpreterBuilder
-
- init {
- this.environment = RuntimeEnvironment
- this.builder = LispInterpreterBuilder
+ companion object {
+ private const val TERMINATED = "terminated"
+ private val FILE = LispInterpreterTest::class.java.getResource("file.lisp").file
}
+ private var indicatorSet = HashSet()
+ private var outputStream = ByteArrayOutputStream()
+ private var errorOutputStream = ByteArrayOutputStream()
+
private fun setCommonFeatures() {
- builder.setOutput(PrintStream(outputStream!!))
- builder.setErrorOutput(PrintStream(errorOutputStream!!))
- builder.setTerminationFunction { }
- builder.setErrorTerminationFunction { indicatorSet!!.add(TERMINATED) }
+ LispInterpreterBuilder.setOutput(PrintStream(outputStream))
+ LispInterpreterBuilder.setErrorOutput(PrintStream(errorOutputStream))
+ LispInterpreterBuilder.setTerminationFunction { }
+ LispInterpreterBuilder.setErrorTerminationFunction { indicatorSet.add(TERMINATED) }
}
private fun assertTerminated() {
- assertTrue(indicatorSet!!.contains(TERMINATED))
+ assertTrue(indicatorSet.contains(TERMINATED))
}
private fun assertErrorMessageWritten() {
- assertTrue(errorOutputStream!!.toByteArray().size > 0)
+ assertTrue(errorOutputStream.toByteArray().isNotEmpty())
}
@Before
fun setUp() {
- indicatorSet = HashSet()
- outputStream = ByteArrayOutputStream()
- errorOutputStream = ByteArrayOutputStream()
- environment.reset()
- builder.reset()
+ indicatorSet.clear()
+ outputStream.reset()
+ errorOutputStream.reset()
+ RuntimeEnvironment.reset()
+ LispInterpreterBuilder.reset()
}
@After
fun tearDown() {
- environment.reset()
- builder.reset()
+ RuntimeEnvironment.reset()
+ LispInterpreterBuilder.reset()
}
@Test
fun buildInteractiveInterpreter() {
setCommonFeatures()
- builder.setInput(System.`in`, "stdin")
- val interpreter = builder.build()
+ LispInterpreterBuilder.setInput(System.`in`, "stdin")
+ val interpreter = LispInterpreterBuilder.build()
assertTrue(interpreter is InteractiveLispInterpreter)
}
@@ -69,9 +67,9 @@ class LispInterpreterTest {
@Test
fun buildNonInteractiveInterpreter() {
setCommonFeatures()
- builder.setInput(System.`in`, "stdin")
- builder.setNotInteractive()
- val interpreter = builder.build()
+ LispInterpreterBuilder.setInput(System.`in`, "stdin")
+ LispInterpreterBuilder.setNotInteractive()
+ val interpreter = LispInterpreterBuilder.build()
assertFalse(interpreter is InteractiveLispInterpreter)
assertFalse(interpreter is FileLispInterpreter)
@@ -80,8 +78,8 @@ class LispInterpreterTest {
@Test
fun buildFileBasedInterpreter() {
setCommonFeatures()
- builder.useFile(FILE)
- val interpreter = builder.build()
+ LispInterpreterBuilder.useFile(FILE)
+ val interpreter = LispInterpreterBuilder.build()
assertTrue(interpreter is FileLispInterpreter)
}
@@ -89,8 +87,8 @@ class LispInterpreterTest {
@Test
fun attemptToBuildInterpreterOnBadFile() {
setCommonFeatures()
- builder.useFile("does-not-exist.lisp")
- builder.build()
+ LispInterpreterBuilder.useFile("does-not-exist.lisp")
+ LispInterpreterBuilder.build()
assertErrorMessageWritten()
assertTerminated()
@@ -98,65 +96,59 @@ class LispInterpreterTest {
@Test
fun makeSureDecoratorsAreInitializedWithDefaults() {
- builder.build()
+ LispInterpreterBuilder.build()
- assertEquals("", environment.decoratePrompt(""))
- assertEquals("", environment.decorateValueOutput(""))
- assertEquals("", environment.decorateWarningOutput(""))
- assertEquals("", environment.decorateErrorOutput(""))
- assertEquals("", environment.decorateCriticalOutput(""))
+ assertEquals("", RuntimeEnvironment.decoratePrompt(""))
+ assertEquals("", RuntimeEnvironment.decorateValueOutput(""))
+ assertEquals("", RuntimeEnvironment.decorateWarningOutput(""))
+ assertEquals("", RuntimeEnvironment.decorateErrorOutput(""))
+ assertEquals("", RuntimeEnvironment.decorateCriticalOutput(""))
}
@Test
fun makeSureDecoratorsAreSetCorrectly() {
- builder.setPromptDecorator { s -> "#$s#" }
- builder.setValueOutputDecorator { s -> "@$s@" }
- builder.setWarningOutputDecorator { s -> "%$s%" }
- builder.setErrorOutputDecorator { s -> "*$s*" }
- builder.setCriticalOutputDecorator { s -> "$$s$" }
- builder.build()
+ LispInterpreterBuilder.setPromptDecorator { s -> "#$s#" }
+ LispInterpreterBuilder.setValueOutputDecorator { s -> "@$s@" }
+ LispInterpreterBuilder.setWarningOutputDecorator { s -> "%$s%" }
+ LispInterpreterBuilder.setErrorOutputDecorator { s -> "*$s*" }
+ LispInterpreterBuilder.setCriticalOutputDecorator { s -> "$$s$" }
+ LispInterpreterBuilder.build()
- assertEquals("#x#", environment.decoratePrompt("x"))
- assertEquals("@x@", environment.decorateValueOutput("x"))
- assertEquals("%x%", environment.decorateWarningOutput("x"))
- assertEquals("*x*", environment.decorateErrorOutput("x"))
- assertEquals("\$x$", environment.decorateCriticalOutput("x"))
+ assertEquals("#x#", RuntimeEnvironment.decoratePrompt("x"))
+ assertEquals("@x@", RuntimeEnvironment.decorateValueOutput("x"))
+ assertEquals("%x%", RuntimeEnvironment.decorateWarningOutput("x"))
+ assertEquals("*x*", RuntimeEnvironment.decorateErrorOutput("x"))
+ assertEquals("\$x$", RuntimeEnvironment.decorateCriticalOutput("x"))
}
@Test
fun fileBasedInterpreterWorks_PrintsLastValueOnly() {
setCommonFeatures()
- builder.useFile(FILE)
- builder.build().interpret()
+ LispInterpreterBuilder.useFile(FILE)
+ LispInterpreterBuilder.build().interpret()
- assertEquals("PICKLE\n\n", outputStream!!.toString())
- assertEquals("", errorOutputStream!!.toString())
+ assertEquals("PICKLE\n\n", outputStream.toString())
+ assertEquals("", errorOutputStream.toString())
}
@Test
fun interactiveInterpreterWorks() {
setCommonFeatures()
- builder.setInput(createInputStreamFromString("'pickle"), "input")
- builder.build().interpret()
+ LispInterpreterBuilder.setInput(createInputStreamFromString("'pickle"), "input")
+ LispInterpreterBuilder.build().interpret()
- assertEquals(format("{0}\n{1}\n{0}\n", PROMPT, "PICKLE"), outputStream!!.toString())
- assertEquals("", errorOutputStream!!.toString())
+ assertEquals(format("{0}\n{1}\n{0}\n", PROMPT, "PICKLE"), outputStream.toString())
+ assertEquals("", errorOutputStream.toString())
}
@Test
fun interpreterHandlesError() {
setCommonFeatures()
- builder.setNotInteractive()
- builder.setInput(createInputStreamFromString("pickle"), "input")
- builder.build().interpret()
+ LispInterpreterBuilder.setNotInteractive()
+ LispInterpreterBuilder.setInput(createInputStreamFromString("pickle"), "input")
+ LispInterpreterBuilder.build().interpret()
- assertEquals("\n", outputStream!!.toString())
- assertEquals("[error] symbol PICKLE has no value\n", errorOutputStream!!.toString())
- }
-
- companion object {
-
- private val TERMINATED = "terminated"
- private val FILE = LispInterpreterTest::class.java.getResource("file.lisp").file
+ assertEquals("\n", outputStream.toString())
+ assertEquals("[error] symbol PICKLE has no value\n", errorOutputStream.toString())
}
}
diff --git a/src/test/kotlin/testutil/SymbolAndFunctionCleaner.kt b/src/test/kotlin/testutil/SymbolAndFunctionCleaner.kt
index d16b86f..ab18a68 100644
--- a/src/test/kotlin/testutil/SymbolAndFunctionCleaner.kt
+++ b/src/test/kotlin/testutil/SymbolAndFunctionCleaner.kt
@@ -29,6 +29,5 @@ abstract class SymbolAndFunctionCleaner {
}
open fun additionalSetUp() {}
-
open fun additionalTearDown() {}
}
diff --git a/src/test/kotlin/token/TokenFactoryTest.java b/src/test/kotlin/token/TokenFactoryTest.java
index 2354909..170b6f8 100644
--- a/src/test/kotlin/token/TokenFactoryTest.java
+++ b/src/test/kotlin/token/TokenFactoryTest.java
@@ -21,9 +21,7 @@ public class TokenFactoryTest {
@Before
public void setUp() {
tokenFactory = new TokenFactoryImpl();
- testPosition = new FilePosition("testFile");
- testPosition.setLineNumber(0);
- testPosition.setColumnNumber(0);
+ testPosition = new FilePosition("testFile", 0, 0);
}
private Token createToken(String text) {