Skip to content

Commit

Permalink
Kotlin script works (at least with K2)
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Jan 21, 2025
1 parent e043b6b commit 2ba2757
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ package de.fraunhofer.aisec.codyze.compliance
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.groups.provideDelegate
import de.fraunhofer.aisec.cpg.codyze.*
import de.fraunhofer.aisec.codyze.*

/** The main `compliance` command. */
class ComplianceCommand : CliktCommand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import de.fraunhofer.aisec.cpg.query.QueryTree
import de.fraunhofer.aisec.cpg.test.analyze
import java.io.File
import kotlin.io.path.Path
import kotlin.script.experimental.api.ResultValue
import kotlin.script.experimental.api.valueOrNull
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
Expand All @@ -46,9 +44,8 @@ class QueryHostTest {
analyze(listOf(topLevel.resolve("simple.py").toFile()), topLevel, true) {
it.registerLanguage<PythonLanguage>()
}
val scriptResult = result.evalQuery(File("src/integrationTest/resources/simple.query.kts"))
val evalResult = (scriptResult.valueOrNull()?.returnValue as? ResultValue.Value)?.value

val evalResult =
result.evalQuery(File("src/integrationTest/resources/simple.query.kts"), "statement1")
val queryTree = evalResult as? QueryTree<*>
assertNotNull(queryTree)
assertEquals(true, queryTree.value)
Expand Down
10 changes: 7 additions & 3 deletions codyze-core/src/integrationTest/resources/simple.query.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
* \______/ \__| \______/
*
*/
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.TranslationResult
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.query.QueryTree
import de.fraunhofer.aisec.cpg.query.allExtended

val queryResult = result.allExtended<FunctionDeclaration>(mustSatisfy = { QueryTree(it.name.localName) eq "foo" })
queryResult
fun statement1(tr: TranslationResult): QueryTree<Boolean> {
val result = tr.allExtended<FunctionDeclaration>(mustSatisfy = { QueryTree(it.name.localName) eq "foo" })
return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* \______/ \__| \______/
*
*/
package de.fraunhofer.aisec.cpg.codyze
package de.fraunhofer.aisec.codyze

import com.github.ajalt.clikt.parameters.groups.OptionGroup
import com.github.ajalt.clikt.parameters.options.default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,37 @@
package de.fraunhofer.aisec.codyze

import de.fraunhofer.aisec.cpg.TranslationResult
import de.fraunhofer.aisec.cpg.helpers.Benchmark
import java.io.File
import kotlin.reflect.full.functions
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate

fun TranslationResult.evalQuery(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
fun TranslationResult.evalQuery(scriptFile: File, queryFunc: String): Any? {
val evalCtx = QueryScriptContext(this)

var b = Benchmark(TranslationResult::class.java, "Compiling query script $scriptFile")
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<QueryScript>()
val evaluationConfiguration =
createJvmEvaluationConfigurationFromTemplate<QueryScript> { implicitReceivers(evalCtx) }

val scriptResult =
BasicJvmScriptingHost()
.eval(scriptFile.toScriptSource(), compilationConfiguration, evaluationConfiguration)

println(scriptResult)
val value = scriptResult.valueOrThrow()
val klass = value.returnValue.scriptClass
val func = klass?.functions?.firstOrNull { it.name == queryFunc }
if (func == null) {
throw IllegalArgumentException("Query function $queryFunc not found in script")

Check warning on line 54 in codyze-core/src/main/kotlin/de/fraunhofer/aisec/codyze/QueryHost.kt

View check run for this annotation

Codecov / codecov/patch

codyze-core/src/main/kotlin/de/fraunhofer/aisec/codyze/QueryHost.kt#L54

Added line #L54 was not covered by tests
}
b.stop()

return scriptResult
b = Benchmark(TranslationResult::class.java, "Executing query function $queryFunc")
val ret = func.call(value.returnValue.scriptInstance, this)
b.stop()
return ret
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ package de.fraunhofer.aisec.codyze
import de.fraunhofer.aisec.cpg.TranslationResult
import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvm.updateClasspath
import kotlin.script.experimental.jvm.util.classpathFromClassloader
import kotlin.script.templates.ScriptTemplateDefinition

@ScriptTemplateDefinition(scriptFilePattern = ".*\\.query\\.kts")
@KotlinScript(
// File extension for the script type
fileExtension = "query.kts",
Expand All @@ -44,7 +47,13 @@ open class QueryScriptContext(val result: TranslationResult)
object QueryScriptConfiguration :
ScriptCompilationConfiguration({
baseClass(QueryScript::class)
jvm { dependenciesFromCurrentContext(wholeClasspath = true) }
jvm {
val libraries =
setOf("codyze-core", "cpg-core", "cpg-analysis", "kotlin-stdlib", "kotlin-reflect")
val cp = classpathFromClassloader(QueryScript::class.java.classLoader)
checkNotNull(cp) { "Could not read classpath" }
updateClasspath(cp.filter { element -> libraries.any { it in element.toString() } })
}
implicitReceivers(QueryScriptContext::class)
compilerOptions("-Xcontext-receivers", "-jvm-target=17")
defaultImports.append(
Expand Down

0 comments on commit 2ba2757

Please sign in to comment.