Skip to content

Commit 65fb45f

Browse files
committed
feat(lsp): report diagnostics and keep up with changes
1 parent 763a29f commit 65fb45f

File tree

22 files changed

+296
-199
lines changed

22 files changed

+296
-199
lines changed

cli/src/main/kotlin/tools/samt/cli/CliCompiler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal fun compile(command: CompileCommand, controller: DiagnosticController)
1616
// attempt to parse each source file into an AST
1717
val fileNodes = buildList {
1818
for (source in sourceFiles) {
19-
val context = controller.createContext(source)
19+
val context = controller.getOrCreateContext(source)
2020
val tokenStream = Lexer.scan(source.content.reader(), context)
2121

2222
if (context.hasErrors()) {

cli/src/main/kotlin/tools/samt/cli/CliDumper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal fun dump(command: DumpCommand, terminal: Terminal, controller: Diagnost
1919
// attempt to parse each source file into an AST
2020
val fileNodes = buildList {
2121
for (source in sourceFiles) {
22-
val context = controller.createContext(source)
22+
val context = controller.getOrCreateContext(source)
2323

2424
if (dumpAll || command.dumpTokens) {
2525
// create duplicate scan because sequence can only be iterated once

cli/src/main/kotlin/tools/samt/cli/CliFileResolution.kt

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,11 @@ package tools.samt.cli
22

33
import tools.samt.common.DiagnosticController
44
import tools.samt.common.SourceFile
5+
import tools.samt.common.collectSamtFiles
6+
import tools.samt.common.readSamtSource
57
import java.io.File
68

7-
internal fun List<String>.readSamtSourceFiles(controller: DiagnosticController): List<SourceFile> {
8-
val files = map { File(it) }.ifEmpty { gatherSamtFiles(controller.workingDirectoryAbsolutePath) }
9+
internal fun List<String>.readSamtSourceFiles(controller: DiagnosticController): List<SourceFile> =
10+
map { File(it) }.ifEmpty { collectSamtFiles(controller.workingDirectoryAbsolutePath) }
11+
.readSamtSource(controller)
912

10-
return buildList {
11-
for (file in files) {
12-
if (!file.exists()) {
13-
controller.reportGlobalError("File '${file.canonicalPath}' does not exist")
14-
continue
15-
}
16-
17-
if (!file.canRead()) {
18-
controller.reportGlobalError("File '${file.canonicalPath}' cannot be read, bad file permissions?")
19-
continue
20-
}
21-
22-
if (file.extension != "samt") {
23-
controller.reportGlobalError("File '${file.canonicalPath}' must end in .samt")
24-
continue
25-
}
26-
27-
add(SourceFile(file.canonicalPath, content = file.readText()))
28-
}
29-
}
30-
}
31-
32-
internal fun gatherSamtFiles(directory: String): List<File> {
33-
val dir = File(directory)
34-
return dir.walkTopDown().filter { it.isFile && it.extension == "samt" }.toList()
35-
}

cli/src/test/kotlin/tools/samt/cli/ASTPrinterTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class ASTPrinterTest {
8484
val filePath = "/tmp/ASTPrinterTest.samt"
8585
val sourceFile = SourceFile(filePath, source)
8686
val diagnosticController = DiagnosticController("/tmp")
87-
val diagnosticContext = diagnosticController.createContext(sourceFile)
87+
val diagnosticContext = diagnosticController.getOrCreateContext(sourceFile)
8888
val stream = Lexer.scan(source.reader(), diagnosticContext)
8989
val fileTree = Parser.parse(sourceFile, stream, diagnosticContext)
9090
assertFalse(diagnosticContext.hasErrors(), "Expected no errors, but had errors")

cli/src/test/kotlin/tools/samt/cli/DiagnosticFormatterTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class DiagnosticFormatterTest {
4545
val controller = DiagnosticController(baseDirectory)
4646
val source = ""
4747
val sourceFile = SourceFile(filePath, source)
48-
val context = controller.createContext(sourceFile)
48+
val context = controller.getOrCreateContext(sourceFile)
4949

5050
context.error {
5151
message("some error")
@@ -484,7 +484,7 @@ class DiagnosticFormatterTest {
484484
val filePath = Path("/tmp", "DiagnosticFormatterTest.samt").absolutePathString()
485485
val sourceFile = SourceFile(filePath, source)
486486
val diagnosticController = DiagnosticController(baseDirectory)
487-
val diagnosticContext = diagnosticController.createContext(sourceFile)
487+
val diagnosticContext = diagnosticController.getOrCreateContext(sourceFile)
488488
val stream = Lexer.scan(source.reader(), diagnosticContext)
489489
val fileTree = Parser.parse(sourceFile, stream, diagnosticContext)
490490
assertFalse(diagnosticContext.hasErrors(), "Expected no errors, but had errors")

cli/src/test/kotlin/tools/samt/cli/TokenPrinterTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class TokenPrinterTest {
4949
val filePath = "/tmp/TokenPrinterTest.samt"
5050
val sourceFile = SourceFile(filePath, source)
5151
val diagnosticController = DiagnosticController("/tmp")
52-
val diagnosticContext = diagnosticController.createContext(sourceFile)
52+
val diagnosticContext = diagnosticController.getOrCreateContext(sourceFile)
5353
val stream = Lexer.scan(source.reader(), diagnosticContext)
5454
assertFalse(diagnosticContext.hasErrors(), "Expected no errors, but had errors")
5555
return stream

common/src/main/kotlin/tools/samt/common/Diagnostics.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class DiagnosticController(val workingDirectoryAbsolutePath: String) {
5656
/**
5757
* Creates a new diagnostic context for the given source file or returns already existing one.
5858
* */
59-
fun createContext(source: SourceFile): DiagnosticContext {
59+
fun getOrCreateContext(source: SourceFile): DiagnosticContext {
6060
val foundContext = contexts.find { it.source == source}
6161
if (foundContext != null) return foundContext
6262
return DiagnosticContext(source).also { contexts.add(it) }
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package tools.samt.common
2+
3+
import java.io.File
4+
5+
fun List<File>.readSamtSource(controller: DiagnosticController): List<SourceFile> {
6+
return buildList {
7+
for (file in this@readSamtSource) {
8+
if (!file.exists()) {
9+
controller.reportGlobalError("File '${file.canonicalPath}' does not exist")
10+
continue
11+
}
12+
13+
if (!file.canRead()) {
14+
controller.reportGlobalError("File '${file.canonicalPath}' cannot be read, bad file permissions?")
15+
continue
16+
}
17+
18+
if (file.extension != "samt") {
19+
controller.reportGlobalError("File '${file.canonicalPath}' must end in .samt")
20+
continue
21+
}
22+
23+
add(SourceFile(file.canonicalPath, content = file.readText()))
24+
}
25+
}
26+
}
27+
28+
fun collectSamtFiles(directory: String): List<File> {
29+
val dir = File(directory)
30+
return dir.walkTopDown().filter { it.isFile && it.extension == "samt" }.toList()
31+
}

common/src/test/kotlin/tools/samt/common/DiagnosticsTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class DiagnosticsTest {
3636
package debug
3737
""".trimIndent()
3838
val sourceFile = SourceFile(sourcePath, sourceCode)
39-
val context = controller.createContext(sourceFile)
39+
val context = controller.getOrCreateContext(sourceFile)
4040

4141
assertThrows<DiagnosticException>("some fatal error") {
4242
context.fatal {
@@ -65,7 +65,7 @@ class DiagnosticsTest {
6565
package debug
6666
""".trimIndent().trim()
6767
val sourceFile = SourceFile(sourcePath, sourceCode)
68-
val context = controller.createContext(sourceFile)
68+
val context = controller.getOrCreateContext(sourceFile)
6969

7070
val importStatementStartOffset = FileOffset(0, 0, 0)
7171
val importStatementEndOffset = FileOffset(17, 0, 17)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package tools.samt.ls
2+
3+
import tools.samt.common.DiagnosticContext
4+
import tools.samt.common.DiagnosticException
5+
import tools.samt.common.SourceFile
6+
import tools.samt.lexer.Lexer
7+
import tools.samt.lexer.Token
8+
import tools.samt.parser.FileNode
9+
import tools.samt.parser.Parser
10+
11+
class FileInfo(
12+
val diagnosticContext: DiagnosticContext,
13+
val sourceFile: SourceFile,
14+
val tokens: List<Token>,
15+
val fileNode: FileNode? = null
16+
)
17+
18+
fun parseFile(sourceFile: SourceFile): FileInfo {
19+
val diagnosticContext = DiagnosticContext(sourceFile)
20+
21+
val tokens = Lexer.scan(sourceFile.content.reader(), diagnosticContext).toList()
22+
23+
if (diagnosticContext.hasErrors()) {
24+
return FileInfo(diagnosticContext, sourceFile, tokens)
25+
}
26+
27+
val fileNode = try {
28+
Parser.parse(sourceFile, tokens.asSequence(), diagnosticContext)
29+
} catch (e: DiagnosticException) {
30+
// error message is added to the diagnostic console, so it can be ignored here
31+
return FileInfo(diagnosticContext, sourceFile, tokens)
32+
}
33+
34+
return FileInfo(diagnosticContext, sourceFile, tokens, fileNode)
35+
}

0 commit comments

Comments
 (0)