diff --git a/build.gradle.kts b/build.gradle.kts index e87b3b6c174c848b59ffb3add5ddf86966b25aac..3d3abeb58ba6f9bab9b718cbc930a51ccea31b1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ + /* * This file was generated by the Gradle 'init' task. * @@ -31,12 +32,21 @@ dependencies { // json converter implementation("com.google.code.gson" ,"gson" ,"2.8.6") - // Use the Kotlin test library. - testImplementation("org.jetbrains.kotlin:kotlin-test") - // Use the Kotlin JUnit integration. - testImplementation("org.jetbrains.kotlin:kotlin-test-junit") + // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-test-junit5 + testImplementation(kotlin("test-junit5")) + + // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api + testImplementation("org.junit.jupiter","junit-jupiter-engine" , "5.7.0-M1") + + } + +tasks.test { + useJUnitPlatform() +} + + application { // Define the main class for the application. mainClassName = "b.language.server.AppKt" diff --git a/src/main/kotlin/b/language/server/App.kt b/src/main/kotlin/b/language/server/App.kt index b88299a03240f5c7b9b69da9c3663aeaadc94ea0..75b38eab50ef0fd2cc5085067083c92d9958d914 100644 --- a/src/main/kotlin/b/language/server/App.kt +++ b/src/main/kotlin/b/language/server/App.kt @@ -1,6 +1,3 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ package b.language.server import org.eclipse.lsp4j.jsonrpc.Launcher @@ -11,23 +8,14 @@ import java.io.OutputStream import java.util.concurrent.Future -class App { - val greeting: String - get() { - return "Hello world." - } -} - -fun main(args: Array<String>) { - startServer(System.`in`, System.out); - +fun main() { + startServer(System.`in`, System.out) } fun startServer(inputStream: InputStream, outputStream: OutputStream){ - val server : Server = Server() + val server = Server() val launcher : Launcher<LanguageClient> = LSPLauncher.createServerLauncher(server, inputStream, outputStream) val startListing : Future<*> = launcher.startListening() server.setRemoteProxy(launcher.remoteProxy) startListing.get() - } diff --git a/src/main/kotlin/b/language/server/BDocumentService.kt b/src/main/kotlin/b/language/server/BDocumentService.kt index 57534bc7263571726e44c0e90d8c48a36e0f26ab..cf0d28cd5a6c1b5964e99dde62519b23eea372f4 100644 --- a/src/main/kotlin/b/language/server/BDocumentService.kt +++ b/src/main/kotlin/b/language/server/BDocumentService.kt @@ -1,16 +1,17 @@ package b.language.server -import b.language.server.dataStorage.Problem +import b.language.server.proBMangement.CommandCouldNotBeExecutedException +import b.language.server.proBMangement.PathCouldNotBeCreatedException +import b.language.server.proBMangement.ProBCommandLineAccess +import b.language.server.proBMangement.ProBInterface import org.eclipse.lsp4j.* import org.eclipse.lsp4j.services.TextDocumentService -import java.io.File -import java.net.URI import java.util.concurrent.ConcurrentHashMap class BDocumentService(private val server: Server) : TextDocumentService { private val documents = ConcurrentHashMap<String, String>() - private val issueTracker : ConcurrentHashMap<String, ArrayList<String>> = ConcurrentHashMap() + private val issueTracker : ConcurrentHashMap<String, Set<String>> = ConcurrentHashMap() /** * The document open notification is sent from the client to the server to @@ -32,29 +33,35 @@ class BDocumentService(private val server: Server) : TextDocumentService { */ override fun didSave(params: DidSaveTextDocumentParams?) { - - val uri = URI(params!!.textDocument.uri) - - val path = File(uri.path) - - val errorPath = File(path.parent + "/tmp/_error.json") - val errorDict = File(path.parent + "/tmp") - - val clientSettings = server.getDocumentSettings(params.textDocument.uri) - - clientSettings.thenAccept{ setting -> - val probInterface = ProBInterface(setting.probHome, path, errorDict, errorPath, server = server) - probInterface.createFolder() - probInterface.performActionOnDocument() - - val problemHandler = ProblemHandler() - - val problemList: List<Problem> = problemHandler.readProblems(errorPath.absolutePath) - val diagnostics: List<Diagnostic> = problemHandler.transformProblems(problemList) - - server.languageClient.publishDiagnostics(PublishDiagnosticsParams(params.textDocument.uri, diagnostics)) + val currentUri = params!!.textDocument.uri + val clientSettings = server.getDocumentSettings(currentUri) + + clientSettings.thenAccept{ settings -> + val prob : ProBInterface = ProBCommandLineAccess() + + try{ + val diagnostics: List<Diagnostic> = prob.checkDocument(currentUri, settings) + server.languageClient.publishDiagnostics(PublishDiagnosticsParams(currentUri, diagnostics)) + val filesWithProblems = diagnostics.map { diagnostic -> diagnostic.source } + calculateToInvalidate(currentUri, filesWithProblems) + .forEach{uri -> server.languageClient.publishDiagnostics(PublishDiagnosticsParams(uri, listOf()))} + issueTracker[currentUri] = filesWithProblems.toSet() + }catch (e : PathCouldNotBeCreatedException ){ + server.languageClient.showMessage(MessageParams(MessageType.Error, e.message)) + }catch (e : CommandCouldNotBeExecutedException){ + server.languageClient.showMessage(MessageParams(MessageType.Error, e.message)) + } } + } + /** + * Gets all uris that are no longer contain problems + * @param currentUri the uri of the current main file + * @param filesWithProblems uris of files containing problems + */ + fun calculateToInvalidate(currentUri : String, filesWithProblems : List<String>) : List<String>{ + val currentlyDisplayed = issueTracker[currentUri].orEmpty() + return currentlyDisplayed.subtract(filesWithProblems).toList() } /** @@ -79,13 +86,4 @@ class BDocumentService(private val server: Server) : TextDocumentService { //Nothing } - - - - - - - - - } \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/ProBInterface.kt b/src/main/kotlin/b/language/server/ProBInterface.kt deleted file mode 100644 index 745f17673d400510bf7428fe5b9c6214727ebfba..0000000000000000000000000000000000000000 --- a/src/main/kotlin/b/language/server/ProBInterface.kt +++ /dev/null @@ -1,82 +0,0 @@ -package b.language.server - -import org.eclipse.lsp4j.MessageParams -import org.eclipse.lsp4j.MessageType -import java.io.File -import java.io.FileWriter -import java.io.InputStream - -/** - * Interacts with ProB via Commandline - * @param probHome the target ProbCli - * @param fileToCheck the main machine to start evaluating - * @param errorDict the path to store errors - * @param wdActive is wd checks enabled? - * @param strictActive is strict enabled? - * @param performanceHintsActive are performance hints activated? - * @param server the server used to connect with - */ -class ProBInterface(probHome : File, - fileToCheck : File, - val errorDict : File, - val errorPath : File, - wdActive : Boolean = false, - strictActive : Boolean = false, - performanceHintsActive : Boolean = false, - private val server : Server){ - - - private val configuration : String = " -p MAX_INITIALISATIONS 0 -version " - private val ndjson : String = " -p NDJSON_ERROR_LOG_FILE " - private val wd : String = if(wdActive){ - " -wd-check -release_java_parser " - }else{ - " " - } - private val strict : String = if(strictActive){ - " -p STRICT_CLASH_CHECKING TRUE -p TYPE_CHECK_DEFINITIONS TRUE -lint " - }else{ - " " - } - private val performanceHints : String = if(performanceHintsActive){ - " -p PERFORMANCE_INFO TRUE " - }else{ - " " - } - - private val command : String - - init { - command = probHome.path + - configuration + - performanceHints + - strict + - wd + - fileToCheck.absoluteFile + - ndjson + - errorPath.absoluteFile - } - - - fun createFolder() : Boolean{ - errorDict.mkdirs() - FileWriter(errorPath, false).close() - return errorDict.mkdirs() - } - - /** - * Executes the command and returns and sends an error message if something fails - */ - fun performActionOnDocument() { - val process : Process = Runtime.getRuntime().exec(command) - val output : InputStream = process.inputStream - - process.waitFor() //we must wait here to ensure correct behavior when reading an error - - val outputAsString = String(output.readAllBytes()) - if(!outputAsString.contains("ProB Command Line Interface")){ - server.languageClient.showMessage( - MessageParams(MessageType.Error, "Something went wrong when calling probcli $command")) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/ProblemHandler.kt b/src/main/kotlin/b/language/server/ProblemHandler.kt deleted file mode 100644 index da05b457db95d3da0555373c1faa15a164c9e517..0000000000000000000000000000000000000000 --- a/src/main/kotlin/b/language/server/ProblemHandler.kt +++ /dev/null @@ -1,82 +0,0 @@ -package b.language.server - -import b.language.server.dataStorage.Problem -import com.google.gson.Gson -import org.eclipse.lsp4j.Diagnostic -import org.eclipse.lsp4j.DiagnosticSeverity -import org.eclipse.lsp4j.Position -import org.eclipse.lsp4j.Range -import java.io.* - - - -/** - * Responsible for reading Errors from the corresponding JSON File and sending transforming them into a object - */ -class ProblemHandler { - - /** - * Reads the errors and transforms them to java objects - * @param path the path to the error document - * @return the list of read errors - */ - fun readProblems(path : String): List<Problem> { - val jsonStrings : ArrayList<String> = ArrayList() - BufferedReader(FileReader(path)).use { br -> - var line: String? - while (br.readLine().also { line = it } != null) { - jsonStrings.add(line!!) - } - } - - - return jsonStrings.toList().map { string -> Gson().fromJson(string, Problem::class.java) } - } - - /** - * Transforms errors to error messages - * @param problems the list of errors to transform - * @return the transformed errors - */ - fun transformProblems(problems : List<Problem>): List<Diagnostic> { - return problems. - /** - * Some errors from prob_cli have negative values when there is no exact error location - we set them - * to the first line - */ - map{ problem -> - if (problem.start.line == -1 && problem.start.character == -1 && - problem.end.line == -1 && problem.end.character == -1) - { - Problem(problem.type, - problem.message, - problem.reason, - problem.file, - Position(1, 0), - Position(1, Integer.MAX_VALUE), - problem.version) - } - else{ - problem - } - } - .map { problem -> Diagnostic(Range(problem.start, problem.end), problem.message, - when (problem.type) { - "error" -> { - DiagnosticSeverity.Error - } - "warning" -> { - DiagnosticSeverity.Warning - } - "information" -> { - DiagnosticSeverity.Information - } - else -> { - DiagnosticSeverity.Hint - } - }, - problem.file, - "probcli v.${problem.version}")} - } - -} \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/Server.kt b/src/main/kotlin/b/language/server/Server.kt index eab11966a738a43bf82e22329180103a63e2a533..241dfc84deecdcb746b47e83e40767d12a0d0d71 100644 --- a/src/main/kotlin/b/language/server/Server.kt +++ b/src/main/kotlin/b/language/server/Server.kt @@ -19,7 +19,7 @@ class Server : LanguageServer { lateinit var languageClient : LanguageClient var globalSettings : Settings = Settings() val documentSettings : HashMap<String, CompletableFuture<Settings>> = HashMap() - var configurationAbility : Boolean = true; + var configurationAbility : Boolean = true init { textDocumentService = BDocumentService(this) @@ -101,8 +101,6 @@ class Server : LanguageServer { * @return settings of the document requested */ fun getDocumentSettings(uri : String) : CompletableFuture<Settings> { - this.languageClient.showMessage( - MessageParams(MessageType.Log, "uri $uri " )) if(!configurationAbility){ val returnValue = CompletableFuture<Settings>() returnValue.complete(globalSettings) diff --git a/src/main/kotlin/b/language/server/Util.kt b/src/main/kotlin/b/language/server/Util.kt index 9687ebd2f6a97bb166c2d60ef9eb05e3393c0032..4c6f406cc72f900f4a6c1aa6e0c55fe7f8a101c7 100644 --- a/src/main/kotlin/b/language/server/Util.kt +++ b/src/main/kotlin/b/language/server/Util.kt @@ -1,14 +1,25 @@ package b.language.server +import b.language.server.dataStorage.Problem import b.language.server.dataStorage.Settings import com.google.gson.Gson import com.google.gson.JsonObject +import org.eclipse.lsp4j.Diagnostic +import org.eclipse.lsp4j.DiagnosticSeverity +import org.eclipse.lsp4j.Position +import org.eclipse.lsp4j.Range import java.io.File + +/** + * Takes a json and tries to cast it into a settings objects + * @param json the json object + * @return the settings object + */ fun castJsonToSetting(json : JsonObject) : Settings { return Settings(Gson().fromJson(json.get("maxNumberOfProblems"), Int::class.java), Gson().fromJson(json.get("wdChecks"), Boolean::class.java), Gson().fromJson(json.get("strictChecks"), Boolean::class.java), Gson().fromJson(json.get("performanceHints"), Boolean::class.java), File(Gson().fromJson(json.get("probHome"), String::class.java))) -} \ No newline at end of file +} diff --git a/src/main/kotlin/b/language/server/dataStorage/Position.kt b/src/main/kotlin/b/language/server/dataStorage/Position.kt new file mode 100644 index 0000000000000000000000000000000000000000..14e00846910be7754a8e37eaef51b9d21f26d946 --- /dev/null +++ b/src/main/kotlin/b/language/server/dataStorage/Position.kt @@ -0,0 +1,4 @@ +package b.language.server.dataStorage + + +class Position(var line : Int, var col : Int) \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/dataStorage/Problem.kt b/src/main/kotlin/b/language/server/dataStorage/Problem.kt index 631fd69ee24ee25abb3c3b77c7a083479c7130db..75648c672771ab97bb1f3ca6423b704172cc2f89 100644 --- a/src/main/kotlin/b/language/server/dataStorage/Problem.kt +++ b/src/main/kotlin/b/language/server/dataStorage/Problem.kt @@ -1,6 +1,5 @@ package b.language.server.dataStorage -import org.eclipse.lsp4j.Position /** * kotlin representation of prob ndjson problems diff --git a/src/main/kotlin/b/language/server/proBMangement/CommandCouldNotBeExecutedException.kt b/src/main/kotlin/b/language/server/proBMangement/CommandCouldNotBeExecutedException.kt new file mode 100644 index 0000000000000000000000000000000000000000..01c9b006b379f66fbaffa656aeff0f81da69c1f2 --- /dev/null +++ b/src/main/kotlin/b/language/server/proBMangement/CommandCouldNotBeExecutedException.kt @@ -0,0 +1,3 @@ +package b.language.server.proBMangement + +class CommandCouldNotBeExecutedException(message: String?) : Exception(message) \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/proBMangement/PathCouldNotBeCreatedException.kt b/src/main/kotlin/b/language/server/proBMangement/PathCouldNotBeCreatedException.kt new file mode 100644 index 0000000000000000000000000000000000000000..57f2ddefbe8df4fb3dbdf319dd6b5cd9d71fdc24 --- /dev/null +++ b/src/main/kotlin/b/language/server/proBMangement/PathCouldNotBeCreatedException.kt @@ -0,0 +1,3 @@ +package b.language.server.proBMangement + +class PathCouldNotBeCreatedException(message: String?) : Exception(message) \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/proBMangement/ProBCommandLineAccess.kt b/src/main/kotlin/b/language/server/proBMangement/ProBCommandLineAccess.kt new file mode 100644 index 0000000000000000000000000000000000000000..4daf213f471f435fe39da5d4f72d6e9db22c888d --- /dev/null +++ b/src/main/kotlin/b/language/server/proBMangement/ProBCommandLineAccess.kt @@ -0,0 +1,185 @@ +package b.language.server.proBMangement + +import b.language.server.dataStorage.Problem +import b.language.server.dataStorage.Settings +import com.google.gson.Gson +import org.eclipse.lsp4j.* +import java.io.* +import java.net.URI + + +/** + * Access ProB via command line + */ +class ProBCommandLineAccess : ProBInterface{ + /** + * Checks the given document with the help of ProB; Will setup all needed steps to ensure a clean process + * @param uri the source to check + * @return a list of all problems found + */ + override fun checkDocument(uri : String, settings: Settings): List<Diagnostic> { + val realUri = URI(uri) + val path = File(realUri.path) + val errorPath = File(path.parent + "/tmp/_error.json") + val errorDict = File(path.parent + "/tmp") + + val result = createFolder(errorDict, errorPath) + if(!result){ + throw PathCouldNotBeCreatedException("The Path leading to $errorPath could has not been created due some issue.") + } + val command = buildCommand(settings, path, errorPath) + + performActionOnDocument(command) + + val problems = readProblems(errorPath.path) + + return transformProblems(problems) + } + + + /** + * Constructs the commandline call to proB depending on the given settings + * @param settings the settings for the document + * @param fileToCheck the current documents address + * @param errorPath the path to dump the ndjson message + * @return the execution ready command + */ + fun buildCommand(settings : Settings, fileToCheck : File, errorPath : File) : String{ + val configuration = " -p MAX_INITIALISATIONS 0 -version " + val ndjson = " -p NDJSON_ERROR_LOG_FILE " + val wd : String = if(settings.wdChecks){ + " -wd-check -release_java_parser " + }else{ + " " + } + val strict : String = if(settings.strictChecks){ + " -p STRICT_CLASH_CHECKING TRUE -p TYPE_CHECK_DEFINITIONS TRUE -lint " + }else{ + " " + } + val performanceHints : String = if(settings.performanceHints){ + " -p PERFORMANCE_INFO TRUE " + }else{ + " " + } + + val probHome = settings.probHome + + return probHome.path + + configuration + + performanceHints + + strict + + wd + + fileToCheck.absoluteFile + + ndjson + + errorPath.absoluteFile + + } + + + /** + * Creates the tmp folder and an empty ndjson file; will recreate an empty ndjson file to ensure clean messages + * @param errorDict the path of the tmp dict + * @param errorPath the path to the error file + * @return success of the action + */ + fun createFolder(errorDict : File, errorPath: File) : Boolean{ + errorDict.mkdirs() + FileWriter(errorPath, false).close() + return errorDict.exists() && errorPath.exists() + } + + /** + * Executes the given command + * @param command to execute + * @throws CommandCouldNotBeExecutedException the command failed to reach probcli + */ + fun performActionOnDocument(command : String) { + val process : Process = Runtime.getRuntime().exec(command) + val output : InputStream = process.inputStream + + process.waitFor() //we must wait here to ensure correct behavior when reading an error + + val outputAsString = String(output.readAllBytes()) + if(!outputAsString.contains("ProB Command Line Interface")){ + throw CommandCouldNotBeExecutedException("Error when trying to call probcli with command $command") + } + } + + + /** + * Reads the errors and transforms them to java objects + * @param path the path to the error document + * @return the list of read errors + */ + fun readProblems(path : String): List<Problem> { + val jsonStrings : ArrayList<String> = ArrayList() + BufferedReader(FileReader(path)).use { br -> + var line: String? + while (br.readLine().also { line = it } != null) { + jsonStrings.add(line!!) + } + } + + val strings = jsonStrings.toList().map { string -> Gson().fromJson(string, Problem::class.java) } + return strings + + } + + /** + * Transforms errors to error messages + * @param problems the list of errors to transform + * @return the transformed errors + */ + fun transformProblems(problems : List<Problem>): List<Diagnostic> { + return problems. + /** + * Some errors from prob_cli have negative values when there is no exact error location - we set them + * to the first line + */ + map{ problem -> + if (problem.start.line == -1 && problem.start.col == -1 && + problem.end.line == -1 && problem.end.col == -1) + { + print(Integer.MAX_VALUE) + Problem(problem.type, + problem.message, + problem.reason, + problem.file, + b.language.server.dataStorage.Position(1,0), + b.language.server.dataStorage.Position(1, Integer.MAX_VALUE), + problem.version) + } + else{ + /** + * Lines are off by one when they get out of vscode + */ + problem.start.line = problem.start.line - 1 + problem.end.line = problem.end.line - 1 + + problem + } + } + .map { problem -> Diagnostic( + Range( + Position(problem.start.line, problem.start.col), + Position(problem.end.line, problem.end.col)), problem.message, + when (problem.type) { + "error" -> { + DiagnosticSeverity.Error + } + "warning" -> { + DiagnosticSeverity.Warning + } + "information" -> { + DiagnosticSeverity.Information + } + else -> { + DiagnosticSeverity.Hint + } + }, + problem.file, + " probcli v.${problem.version}") + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/b/language/server/proBMangement/ProBInterface.kt b/src/main/kotlin/b/language/server/proBMangement/ProBInterface.kt new file mode 100644 index 0000000000000000000000000000000000000000..8c16106da28290fc85b37587012407f21af2db07 --- /dev/null +++ b/src/main/kotlin/b/language/server/proBMangement/ProBInterface.kt @@ -0,0 +1,15 @@ +package b.language.server.proBMangement + +import b.language.server.dataStorage.Settings +import org.eclipse.lsp4j.Diagnostic + +interface ProBInterface { + + /** + * Checks the given document with the help of ProB + * @param uri the source to check + * @return a list of all problems found + */ + abstract fun checkDocument(uri : String, settings: Settings) : List<Diagnostic> + +} \ No newline at end of file diff --git a/src/test/kotlin/b/language/server/AppTest.kt b/src/test/kotlin/b/language/server/AppTest.kt deleted file mode 100644 index 898b91cb22e908c9325dcb997e8f150623f48a9c..0000000000000000000000000000000000000000 --- a/src/test/kotlin/b/language/server/AppTest.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package b.language.server - -import kotlin.test.Test -import kotlin.test.assertNotNull - -class AppTest { - @Test fun testAppHasAGreeting() { - val classUnderTest = App() - assertNotNull(classUnderTest.greeting, "app should have a greeting") - } -} diff --git a/src/test/kotlin/b/language/server/ProBCommandLineTest.kt b/src/test/kotlin/b/language/server/ProBCommandLineTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..16e3b123d1d3a4186d3ba62843db14b728768deb --- /dev/null +++ b/src/test/kotlin/b/language/server/ProBCommandLineTest.kt @@ -0,0 +1,185 @@ +package b.language.server + +import b.language.server.dataStorage.Position +import b.language.server.dataStorage.Problem +import b.language.server.dataStorage.Settings +import b.language.server.proBMangement.ProBCommandLineAccess +import com.google.gson.Gson +import org.eclipse.lsp4j.Diagnostic +import org.eclipse.lsp4j.DiagnosticSeverity +import org.eclipse.lsp4j.Range +import kotlin.test.Test +import org.junit.jupiter.api.io.TempDir +import java.io.File +import kotlin.test.assertEquals + +class ProBCommandLineTest{ + + @Test + fun test_readProblems(@TempDir tempPath : File = File("tmp")) + { + val file = File(tempPath.path+"/tmp.txt") + val problemToWrite = Problem(message = "Test", file = "test.mch", reason = "test reason", version = "test", + start = Position(1,1), end = Position(1,1), type = "test") + file.writeText(Gson().toJson(problemToWrite)) + + val problems = ProBCommandLineAccess().readProblems(file.path) + + val problem = problems.first() + + assertEquals(problemToWrite.version, problem.version) + assertEquals(problemToWrite.end.col, problem.end.col) + assertEquals(problemToWrite.end.line, problemToWrite.end.line) + assertEquals(problemToWrite.start.col, problem.start.col) + assertEquals(problemToWrite.start.line, problemToWrite.start.line) + assertEquals(problemToWrite.file, problem.file) + assertEquals(problemToWrite.message, problem.message) + assertEquals(problemToWrite.reason, problem.reason) + + } + + @Test + fun test_buildCommand_everything_activated(@TempDir tempPath : File = File("tmp")){ + val testSettings = Settings() + val tempFile = File(tempPath.path+"/m.mch") + val command = ProBCommandLineAccess().buildCommand(testSettings, tempFile, tempPath) + assertEquals("~/prob_prolog/probcli.sh -p MAX_INITIALISATIONS 0 " + + "-version " + + "-p PERFORMANCE_INFO TRUE " + + "-p STRICT_CLASH_CHECKING TRUE " + + "-p TYPE_CHECK_DEFINITIONS TRUE -lint " + + "-wd-check -release_java_parser ${tempFile.path} " + + "-p NDJSON_ERROR_LOG_FILE $tempPath", command) + } + + @Test + fun test_buildCommand_everything_not_strict(@TempDir tempPath : File = File("tmp")){ + val testSettings = Settings(strictChecks = false) + val tempFile = File(tempPath.path+"/m.mch") + val command = ProBCommandLineAccess().buildCommand(testSettings, tempFile, tempPath) + assertEquals("~/prob_prolog/probcli.sh -p MAX_INITIALISATIONS 0 " + + "-version " + + "-p PERFORMANCE_INFO TRUE " + + "-wd-check -release_java_parser ${tempFile.path} " + + "-p NDJSON_ERROR_LOG_FILE $tempPath", command) + } + + + @Test + fun test_buildCommand_everything_not_wd(@TempDir tempPath : File = File("tmp")){ + val testSettings = Settings(wdChecks = false) + val tempFile = File(tempPath.path+"/m.mch") + val command = ProBCommandLineAccess().buildCommand(testSettings, tempFile, tempPath) + assertEquals("~/prob_prolog/probcli.sh -p MAX_INITIALISATIONS 0 " + + "-version " + + "-p PERFORMANCE_INFO TRUE " + + "-p STRICT_CLASH_CHECKING TRUE " + + "-p TYPE_CHECK_DEFINITIONS TRUE -lint " + + "${tempFile.path} " + + "-p NDJSON_ERROR_LOG_FILE $tempPath", command) + } + + + @Test + fun test_buildCommand_everything_not_performanceHints(@TempDir tempPath : File = File("tmp")){ + val testSettings = Settings(performanceHints = false) + val tempFile = File(tempPath.path+"/m.mch") + val command = ProBCommandLineAccess().buildCommand(testSettings, tempFile, tempPath) + assertEquals("~/prob_prolog/probcli.sh -p MAX_INITIALISATIONS 0 " + + "-version " + + "-p STRICT_CLASH_CHECKING TRUE " + + "-p TYPE_CHECK_DEFINITIONS TRUE -lint " + + "-wd-check -release_java_parser ${tempFile.path} " + + "-p NDJSON_ERROR_LOG_FILE $tempPath", command) + } + + + @Test + fun test_transformProblems_negative_range(){ + val problemFile = "test.mch" + val message = "Test" + val version = "test" + val testProblem = Problem(message = message, file = problemFile, reason = "test reason", version = version, + start = Position(-1,-1), end = Position(-1,-1), type = "error") + + val transformedProblem = ProBCommandLineAccess().transformProblems(listOf(testProblem)).first() + + val diagnostic = Diagnostic(Range( + org.eclipse.lsp4j.Position(1,0), + org.eclipse.lsp4j.Position(1, Integer.MAX_VALUE)), message, DiagnosticSeverity.Error, problemFile, " probcli v.$version" ) + assertEquals(diagnostic, transformedProblem) + + } + + + @Test + fun test_transformProblems_error(){ + val problemFile = "test.mch" + val message = "Test" + val version = "test" + val testProblem = Problem(message = message, file = problemFile, reason = "test reason", version = version, + start = Position(32,54), end = Position(54,65), type = "error") + + val transformedProblem = ProBCommandLineAccess().transformProblems(listOf(testProblem)).first() + + val diagnostic = Diagnostic(Range( + org.eclipse.lsp4j.Position(31,54), + org.eclipse.lsp4j.Position(53, 65)), message, DiagnosticSeverity.Error, problemFile, " probcli v.$version" ) + assertEquals(diagnostic, transformedProblem) + + } + + + @Test + fun test_transformProblems_warning(){ + val problemFile = "test.mch" + val message = "Test" + val version = "test" + val testProblem = Problem(message = message, file = problemFile, reason = "test reason", version = version, + start = Position(32,54), end = Position(54,65), type = "warning") + + val transformedProblem = ProBCommandLineAccess().transformProblems(listOf(testProblem)).first() + + val diagnostic = Diagnostic(Range( + org.eclipse.lsp4j.Position(31,54), + org.eclipse.lsp4j.Position(53, 65)), message, DiagnosticSeverity.Warning, problemFile, " probcli v.$version" ) + assertEquals(diagnostic, transformedProblem) + + } + + @Test + fun test_transformProblems_information(){ + val problemFile = "test.mch" + val message = "Test" + val version = "test" + val testProblem = Problem(message = message, file = problemFile, reason = "test reason", version = version, + start = Position(32,54), end = Position(54,65), type = "information") + + val transformedProblem = ProBCommandLineAccess().transformProblems(listOf(testProblem)).first() + + val diagnostic = Diagnostic(Range( + org.eclipse.lsp4j.Position(31,54), + org.eclipse.lsp4j.Position(53, 65)), message, DiagnosticSeverity.Information, problemFile, " probcli v.$version" ) + assertEquals(diagnostic, transformedProblem) + + } + + + @Test + fun test_transformProblems_hint(){ + val problemFile = "test.mch" + val message = "Test" + val version = "test" + val testProblem = Problem(message = message, file = problemFile, reason = "test reason", version = version, + start = Position(32,54), end = Position(54,65), type = "something else") + + val transformedProblem = ProBCommandLineAccess().transformProblems(listOf(testProblem)).first() + + val diagnostic = Diagnostic(Range( + org.eclipse.lsp4j.Position(31,54), + org.eclipse.lsp4j.Position(53, 65)), message, DiagnosticSeverity.Hint, problemFile, " probcli v.$version" ) + assertEquals(diagnostic, transformedProblem) + + } + +} \ No newline at end of file