From 949b59c83e006f387836395dd923fc30bc914b37 Mon Sep 17 00:00:00 2001
From: SeeBasTStick <sebastian.stock@hhu.de>
Date: Thu, 13 Aug 2020 16:31:40 +0200
Subject: [PATCH] added prob2 java kernel dependencies

---
 build.gradle.kts                              |  7 ++
 .../b/language/server/BDocumentService.kt     |  8 +-
 src/main/kotlin/b/language/server/Util.kt     |  1 +
 .../server/dataStorage/ProBSettings.kt        |  3 +
 .../b/language/server/dataStorage/Settings.kt |  2 +-
 .../proBMangement/prob2/MyWarningListener.kt  | 18 ++++
 .../server/proBMangement/prob2/ProBKernel.kt  | 90 +++++++++++++++++++
 .../proBMangement/prob2/ProBKernelManager.kt  | 40 +++++++++
 .../proBMangement/prob2/ProBKernelModule.kt   | 10 +++
 .../server/proBMangement/prob2/Util.kt        | 36 ++++++++
 .../b/language/server/ProBCommandLineTest.kt  |  2 +-
 11 files changed, 211 insertions(+), 6 deletions(-)
 create mode 100644 src/main/kotlin/b/language/server/dataStorage/ProBSettings.kt
 create mode 100644 src/main/kotlin/b/language/server/proBMangement/prob2/MyWarningListener.kt
 create mode 100644 src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernel.kt
 create mode 100644 src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelManager.kt
 create mode 100644 src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelModule.kt
 create mode 100644 src/main/kotlin/b/language/server/proBMangement/prob2/Util.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 4f7097f..265b97a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -19,6 +19,9 @@ plugins {
 repositories {
     // Use jcenter for resolving dependencies.
     jcenter()
+
+    maven("https://oss.sonatype.org/content/repositories/snapshots")
+
 }
 
 dependencies {
@@ -41,6 +44,10 @@ dependencies {
     // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api
     testImplementation("org.junit.jupiter","junit-jupiter-engine" ,  "5.7.0-M1")
 
+    implementation("de.hhu.stups:de.prob2.kernel:4.0.0-SNAPSHOT")
+
+    implementation( "com.google.guava", "guava", "28.2-jre")
+
 
 }
 
diff --git a/src/main/kotlin/b/language/server/BDocumentService.kt b/src/main/kotlin/b/language/server/BDocumentService.kt
index 490e7e1..f13ee1a 100644
--- a/src/main/kotlin/b/language/server/BDocumentService.kt
+++ b/src/main/kotlin/b/language/server/BDocumentService.kt
@@ -1,9 +1,9 @@
 package b.language.server
 
 import b.language.server.communication.CommunicatorInterface
-import b.language.server.proBMangement.CommandCouldNotBeExecutedException
-import b.language.server.proBMangement.PathCouldNotBeCreatedException
-import b.language.server.proBMangement.ProBCommandLineAccess
+import b.language.server.proBMangement.probCli.CommandCouldNotBeExecutedException
+import b.language.server.proBMangement.probCli.PathCouldNotBeCreatedException
+import b.language.server.proBMangement.probCli.ProBCommandLineAccess
 import b.language.server.proBMangement.ProBInterface
 import org.eclipse.lsp4j.*
 import org.eclipse.lsp4j.services.TextDocumentService
@@ -64,7 +64,7 @@ class BDocumentService(private val server: Server, private val communicator: Com
                 invalidFiles.forEach{uri -> communicator.publishDiagnostics(PublishDiagnosticsParams(uri, listOf()))}
                 communicator.sendDebugMessage("invalidating old files $invalidFiles", MessageType.Info)
                 issueTracker[currentUri] = filesWithProblems.toSet()
-            }catch (e : PathCouldNotBeCreatedException ){
+            }catch (e : PathCouldNotBeCreatedException){
                 communicator.sendDebugMessage("error path could not be created", MessageType.Info)
                 communicator.showMessage(e.message!!, MessageType.Error)
             }catch (e : CommandCouldNotBeExecutedException){
diff --git a/src/main/kotlin/b/language/server/Util.kt b/src/main/kotlin/b/language/server/Util.kt
index d1d0d31..9ba3755 100644
--- a/src/main/kotlin/b/language/server/Util.kt
+++ b/src/main/kotlin/b/language/server/Util.kt
@@ -19,4 +19,5 @@ fun castJsonToSetting(json : JsonObject) : Settings {
             Gson().fromJson(json.get("performanceHints"), Boolean::class.java),
             File(Gson().fromJson(json.get("probHome"), String::class.java)),
             Gson().fromJson(json.get("debugMode"), Boolean::class.java))
+
 }
diff --git a/src/main/kotlin/b/language/server/dataStorage/ProBSettings.kt b/src/main/kotlin/b/language/server/dataStorage/ProBSettings.kt
new file mode 100644
index 0000000..21828a5
--- /dev/null
+++ b/src/main/kotlin/b/language/server/dataStorage/ProBSettings.kt
@@ -0,0 +1,3 @@
+package b.language.server.dataStorage
+
+data class ProBSettings(val wdChecks : Boolean, val strictChecks : Boolean, val performanceHints : Boolean)
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/dataStorage/Settings.kt b/src/main/kotlin/b/language/server/dataStorage/Settings.kt
index 0cc9534..895add0 100644
--- a/src/main/kotlin/b/language/server/dataStorage/Settings.kt
+++ b/src/main/kotlin/b/language/server/dataStorage/Settings.kt
@@ -3,5 +3,5 @@ package b.language.server.dataStorage
 import java.io.File
 
 data class Settings(val maxNumberOfProblem : Int = 1000, val strictChecks : Boolean = true,  val wdChecks : Boolean = true,
-                    val performanceHints : Boolean = true , val probHome : File = File("~/prob_prolog/probcli.sh"),
+                    val performanceHints : Boolean = true , val probHome : File = File("DEFAULT"),
                     val debugMode : Boolean = true)
diff --git a/src/main/kotlin/b/language/server/proBMangement/prob2/MyWarningListener.kt b/src/main/kotlin/b/language/server/proBMangement/prob2/MyWarningListener.kt
new file mode 100644
index 0000000..2418807
--- /dev/null
+++ b/src/main/kotlin/b/language/server/proBMangement/prob2/MyWarningListener.kt
@@ -0,0 +1,18 @@
+package b.language.server.proBMangement.prob2
+
+import de.prob.animator.IWarningListener
+import de.prob.animator.domainobjects.ErrorItem
+import org.eclipse.lsp4j.Diagnostic
+import org.eclipse.lsp4j.DiagnosticSeverity
+
+
+class MyWarningListener : IWarningListener {
+    private val warningList : ArrayList<ErrorItem> = arrayListOf()
+    override fun warningsOccurred(warnings: MutableList<ErrorItem>?) {
+        warningList.addAll(warnings!!.toList())
+    }
+
+    fun getWarnings() : List<Diagnostic>{
+        return convertErrorItems(warningList, DiagnosticSeverity.Warning)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernel.kt b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernel.kt
new file mode 100644
index 0000000..7b87aba
--- /dev/null
+++ b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernel.kt
@@ -0,0 +1,90 @@
+
+import b.language.server.dataStorage.ProBSettings
+import b.language.server.proBMangement.prob2.MyWarningListener
+import b.language.server.proBMangement.prob2.convertErrorItems
+import com.google.inject.Inject
+import com.google.inject.Injector
+import de.prob.animator.ReusableAnimator
+import de.prob.animator.command.CheckWellDefinednessCommand
+import de.prob.exception.ProBError
+import de.prob.scripting.ClassicalBFactory
+import de.prob.scripting.FactoryProvider
+import de.prob.scripting.ModelTranslationError
+import de.prob.statespace.AnimationSelector
+import de.prob.statespace.StateSpace
+import de.prob.statespace.Trace
+import org.eclipse.lsp4j.Diagnostic
+import org.eclipse.lsp4j.DiagnosticSeverity
+import java.io.IOException
+import java.nio.file.Paths
+
+
+class ProBKernel @Inject constructor(private val injector : Injector, val classicalBFactory : ClassicalBFactory,
+                                     private val animationSelector: AnimationSelector, private val animator : ReusableAnimator) {
+
+
+    private fun loadMachine(newTraceCreator :java.util.function.Function<StateSpace, Trace>, settings: ProBSettings){
+        val newStateSpace = animator.createStateSpace()
+        try {
+            animationSelector.changeCurrentAnimation(newTraceCreator.apply(newStateSpace))
+            executeAdditionalOptions(settings)
+        } catch (e: RuntimeException) {
+            newStateSpace.kill()
+            throw e
+        }
+    }
+
+    private fun executeAdditionalOptions(settings : ProBSettings){
+        val newStateSpace = animator.createStateSpace()
+        if(settings.wdChecks){
+            animator.execute(CheckWellDefinednessCommand())
+        }
+
+    }
+
+    private fun unloadMachine() {
+        val oldTrace = animationSelector.currentTrace
+        if (oldTrace != null) {
+            assert(oldTrace.stateSpace === animator.currentStateSpace)
+            animationSelector.changeCurrentAnimation(null)
+            oldTrace.stateSpace.kill()
+        }
+    }
+
+    fun check(path : String, settings : ProBSettings) : List<Diagnostic>{
+        unloadMachine()
+        val factory = injector.getInstance(FactoryProvider.factoryClassFromExtension(path.substringAfterLast(".")))
+        val warningListener = MyWarningListener()
+        animator.addWarningListener(warningListener)
+        val parseErrors = mutableListOf<Diagnostic>()
+        loadMachine(
+                java.util.function.Function { stateSpace : StateSpace ->
+                    try {
+                        factory.extract(path).load(prepareAdditionalSettings(settings))
+                        loadIntoStateSpace(stateSpace)
+                    } catch (e: IOException) {
+                        throw RuntimeException(e)
+                    } catch (e: ModelTranslationError) {
+                        throw RuntimeException(e)
+                    }catch (e : ProBError){
+                        parseErrors.addAll(convertErrorItems(e.errors))
+                    }
+                    Trace(stateSpace)
+                }, settings)
+        return listOf(warningListener.getWarnings(), parseErrors).flatten()
+    }
+
+    fun prepareAdditionalSettings(proBSettings: ProBSettings): MutableMap<String, String> {
+        val settings = mutableMapOf<String, String>()
+        if(proBSettings.performanceHints) {
+            settings["STRICT_CLASH_CHECKING"] = "TRUE"
+            settings["TYPE_CHECK_DEFINITIONS"] = "TRUE"
+        }
+        if (proBSettings.strictChecks) {
+            settings["PERFORMANCE_INFO"] = "TRUE"
+        }
+        return settings
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelManager.kt b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelManager.kt
new file mode 100644
index 0000000..4da6661
--- /dev/null
+++ b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelManager.kt
@@ -0,0 +1,40 @@
+package b.language.server.proBMangement.prob2
+
+import ProBKernel
+import b.language.server.dataStorage.ProBSettings
+import b.language.server.dataStorage.Settings
+import b.language.server.proBMangement.ProBInterface
+import com.google.inject.Guice
+import com.google.inject.Stage
+import org.eclipse.lsp4j.Diagnostic
+
+/**
+ * Setup a connection to ProB2 Kernel
+ */
+class ProBKernelManager : ProBInterface{
+
+    private lateinit var kernel : ProBKernel
+
+     /**
+     * Checks the given document with the help of ProB
+     * @param uri the source to check
+     * @return a list of all problems found
+     */
+    override fun checkDocument(uri: String, settings: Settings): List<Diagnostic> {
+        val proBSettings = ProBSettings(settings.wdChecks, settings.strictChecks, settings.performanceHints)
+        val probHome = settings.probHome.absolutePath
+
+        if(probHome != "DEFAULT" && !this::kernel.isInitialized)
+        {
+            if(probHome != "DEFAULT"){
+                System.setProperty("prob.home", probHome)
+            }
+            val injector = Guice.createInjector(Stage.PRODUCTION, ProBKernelModule())
+            kernel = injector.getInstance(ProBKernel::class.java)
+        }
+
+        return kernel.check(uri, proBSettings)
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelModule.kt b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelModule.kt
new file mode 100644
index 0000000..66af5f2
--- /dev/null
+++ b/src/main/kotlin/b/language/server/proBMangement/prob2/ProBKernelModule.kt
@@ -0,0 +1,10 @@
+package b.language.server.proBMangement.prob2
+
+import com.google.inject.AbstractModule
+import de.prob.MainModule
+
+class ProBKernelModule : AbstractModule() {
+    override fun configure() {
+        install(MainModule())
+    }
+}
diff --git a/src/main/kotlin/b/language/server/proBMangement/prob2/Util.kt b/src/main/kotlin/b/language/server/proBMangement/prob2/Util.kt
new file mode 100644
index 0000000..96d7e8b
--- /dev/null
+++ b/src/main/kotlin/b/language/server/proBMangement/prob2/Util.kt
@@ -0,0 +1,36 @@
+package b.language.server.proBMangement.prob2
+
+import de.prob.animator.domainobjects.ErrorItem
+import org.eclipse.lsp4j.Diagnostic
+import org.eclipse.lsp4j.DiagnosticSeverity
+import org.eclipse.lsp4j.Position
+import org.eclipse.lsp4j.Range
+
+fun convertErrorItems(errorItems : List<ErrorItem>) : List<Diagnostic>{
+    return errorItems.toList().map { errorItem ->
+        errorItem.locations.map { location ->
+            Diagnostic(Range(Position(location.startLine, location.startColumn), Position(location.endLine, location.endColumn)),
+                    errorItem.message,
+                    getErrorItemType(errorItem),
+                    location.filename)
+        }
+    }.flatten()
+}
+
+fun getErrorItemType(errorItem : ErrorItem) : DiagnosticSeverity{
+    return when(errorItem.type){
+        ErrorItem.Type.ERROR -> {
+            DiagnosticSeverity.Error
+        }
+        ErrorItem.Type.WARNING -> {
+            DiagnosticSeverity.Warning
+        }
+        ErrorItem.Type.INTERNAL_ERROR -> {
+            DiagnosticSeverity.Error
+        }
+        else -> {
+            DiagnosticSeverity.Error
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/kotlin/b/language/server/ProBCommandLineTest.kt b/src/test/kotlin/b/language/server/ProBCommandLineTest.kt
index 79e90d6..2f9a74f 100644
--- a/src/test/kotlin/b/language/server/ProBCommandLineTest.kt
+++ b/src/test/kotlin/b/language/server/ProBCommandLineTest.kt
@@ -3,7 +3,7 @@ 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 b.language.server.proBMangement.probCli.ProBCommandLineAccess
 import com.google.gson.Gson
 import org.eclipse.lsp4j.Diagnostic
 import org.eclipse.lsp4j.DiagnosticSeverity
-- 
GitLab