Skip to content

Commit

Permalink
Implement ets loading with dot dump
Browse files Browse the repository at this point in the history
  • Loading branch information
rudolf101 committed Aug 5, 2024
1 parent 4164b3c commit 6e24eda
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 149 deletions.
41 changes: 41 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/Dot.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2022 UnitTestBot contributors (utbot.org)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jacodb.ets.utils

import mu.KotlinLogging
import java.io.File
import kotlin.time.Duration.Companion.seconds

private val logger = KotlinLogging.logger {}

fun render(path: String, dump: (File) -> Unit) {
val dotFile = File(path)
dump(dotFile)
logger.info { "Generated DOT file: ${dotFile.absolutePath}" }
for (format in listOf("pdf")) {
val formatFile = dotFile.resolveSibling(dotFile.nameWithoutExtension + ".$format")
val cmd: List<String> = listOf(
"dot",
"-T$format",
"$dotFile",
"-o",
"$formatFile"
)
runProcess(cmd, 60.seconds)
logger.info { "Generated ${format.uppercase()} file: ${formatFile.absolutePath}" }
}
}
32 changes: 32 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/EtsFileDtoToDot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.jacodb.ets.dto.MethodDto
import org.jacodb.ets.dto.NopStmtDto
import org.jacodb.ets.dto.StmtDto
import org.jacodb.ets.dto.SwitchStmtDto
import java.io.BufferedWriter
import java.io.File
import java.nio.file.Path
import kotlin.io.path.writeText
Expand Down Expand Up @@ -182,6 +183,37 @@ fun EtsFileDto.toDot(useLR: Boolean = false): String {
return lines.joinToString("\n")
}

fun EtsFileDto.dumpHuimpleTo(output: BufferedWriter) {
output.writeln("EtsFileDto '${name}':")
classes.forEach { clazz ->
output.writeln("= CLASS '${clazz.signature}':")
output.writeln(" superClass = '${clazz.superClassName}'")
output.writeln(" typeParameters = ${clazz.typeParameters}")
output.writeln(" modifiers = ${clazz.modifiers}")
output.writeln(" fields: ${clazz.fields.size}")
clazz.fields.forEach { field ->
output.writeln(" - FIELD '${field.signature}'")
output.writeln(" typeParameters = ${field.typeParameters}")
output.writeln(" modifiers = ${field.modifiers}")
output.writeln(" isOptional = ${field.isOptional}")
output.writeln(" isDefinitelyAssigned = ${field.isDefinitelyAssigned}")
}
output.writeln(" methods: ${clazz.methods.size}")
clazz.methods.forEach { method ->
output.writeln(" - METHOD '${method.signature}':")
output.writeln(" locals = ${method.body.locals}")
output.writeln(" typeParameters = ${method.typeParameters}")
output.writeln(" blocks: ${method.body.cfg.blocks.size}")
method.body.cfg.blocks.forEach { block ->
output.writeln(" - BLOCK ${block.id} with ${block.stmts.size} statements:")
block.stmts.forEachIndexed { i, inst ->
output.writeln(" ${i + 1}. $inst")
}
}
}
}
}

fun EtsFileDto.dumpDot(file: File) {
file.writeText(toDot())
}
Expand Down
27 changes: 27 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/EtsFileToDot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.jacodb.ets.base.EtsStmt
import org.jacodb.ets.model.EtsClass
import org.jacodb.ets.model.EtsFile
import org.jacodb.ets.model.EtsMethod
import java.io.BufferedWriter
import java.io.File
import java.nio.file.Path
import kotlin.io.path.writeText
Expand Down Expand Up @@ -146,6 +147,32 @@ fun EtsFile.toDot(useLR: Boolean = false): String {
return lines.joinToString("\n")
}

fun EtsFile.dumpHuimpleTo(output: BufferedWriter) {
output.writeln("EtsFile '${name}':")
classes.forEach { clazz ->
output.writeln("= CLASS '${clazz.signature}':")
output.writeln(" superClass = '${clazz.superClass}'")
output.writeln(" fields: ${clazz.fields.size}")
clazz.fields.forEach { field ->
output.writeln(" - FIELD '${field.signature}'")
}
output.writeln(" constructor = '${clazz.ctor.signature}'")
output.writeln(" stmts: ${clazz.ctor.cfg.stmts.size}")
clazz.ctor.cfg.stmts.forEachIndexed { i, stmt ->
output.writeln(" ${i + 1}. $stmt")
}
output.writeln(" methods: ${clazz.methods.size}")
clazz.methods.forEach { method ->
output.writeln(" - METHOD '${method.signature}':")
output.writeln(" locals = ${method.localsCount}")
output.writeln(" stmts: ${method.cfg.stmts.size}")
method.cfg.stmts.forEachIndexed { i, stmt ->
output.writeln(" ${i + 1}. $stmt")
}
}
}
}

fun EtsFile.dumpDot(file: File) {
file.writeText(toDot())
}
Expand Down
46 changes: 26 additions & 20 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/LoadEtsFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import org.jacodb.ets.dto.convertToEtsFile
import org.jacodb.ets.model.EtsFile
import java.io.File
import java.io.FileNotFoundException
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import kotlin.io.path.exists
import kotlin.io.path.inputStream
import kotlin.io.path.notExists
import kotlin.io.path.pathString
import kotlin.time.Duration.Companion.seconds

private val logger = KotlinLogging.logger {}

Expand All @@ -40,7 +40,7 @@ private const val DEFAULT_SERIALIZE_SCRIPT_PATH = "out/src/save/serializeArkIR.j
private const val ENV_VAR_NODE_EXECUTABLE = "NODE_EXECUTABLE"
private const val DEFAULT_NODE_EXECUTABLE = "node"

fun loadEtsFileAutoConvert(tsPath: String): EtsFile {
fun generateEtsFileIR(tsPath: String): Path {
val arkAnalyzerDir = Paths.get(System.getenv(ENV_VAR_ARK_ANALYZER_DIR) ?: DEFAULT_ARK_ANALYZER_DIR)
if (!arkAnalyzerDir.exists()) {
throw FileNotFoundException("ArkAnalyzer directory does not exist: '$arkAnalyzerDir'. Did you forget to set the '$ENV_VAR_ARK_ANALYZER_DIR' environment variable? Current value is '${System.getenv(ENV_VAR_ARK_ANALYZER_DIR)}', current dir is '${Paths.get("").toAbsolutePath()}'.")
Expand All @@ -60,26 +60,32 @@ fun loadEtsFileAutoConvert(tsPath: String): EtsFile {
tsPath,
output.pathString,
)
logger.info { "Running: '${cmd.joinToString(" ")}'" }
val process = ProcessBuilder(cmd).start()
val ok = process.waitFor(1, TimeUnit.MINUTES)

val stdout = process.inputStream.bufferedReader().readText().trim()
if (stdout.isNotBlank()) {
logger.info { "STDOUT:\n$stdout" }
}
val stderr = process.errorStream.bufferedReader().readText().trim()
if (stderr.isNotBlank()) {
logger.info { "STDERR:\n$stderr" }
}
runProcess(cmd, 60.seconds)
return output
}

if (!ok) {
logger.info { "Timeout!" }
process.destroy()
fun loadEtsFileAutoConvert(tsPath: String): EtsFile {
val irFilePath = generateEtsFileIR(tsPath)
irFilePath.inputStream().use { stream ->
val etsFileDto = EtsFileDto.loadFromJson(stream)
val etsFile = convertToEtsFile(etsFileDto)
return etsFile
}
}

output.inputStream().use { stream ->
fun loadEtsFileAutoConvertWithDot(tsPath: String, dotDir: String): EtsFile {
val irFilePath = generateEtsFileIR(tsPath)
irFilePath.inputStream().use { stream ->
val etsFileDto = EtsFileDto.loadFromJson(stream)
return convertToEtsFile(etsFileDto)
val etsFile = convertToEtsFile(etsFileDto)
val etsFileDtoDotFileName = "$dotDir/${tsPath.substringAfterLast("/")}".replace(".ts", "Dto.dot")
val etsFileDotFileName = "$dotDir/${tsPath.substringAfterLast("/")}".replace(".ts", ".dot")
render(etsFileDtoDotFileName) { file ->
etsFileDto.dumpDot(file)
}
render(etsFileDotFileName) { file ->
etsFile.dumpDot(file)
}
return etsFile
}
}
54 changes: 54 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/Utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2022 UnitTestBot contributors (utbot.org)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jacodb.ets.utils

import mu.KotlinLogging
import java.io.BufferedWriter
import java.util.concurrent.TimeUnit
import kotlin.time.Duration

private val logger = KotlinLogging.logger {}

internal fun BufferedWriter.writeln(s: String) {
write(s)
newLine()
}

internal fun runProcess(cmd: List<String>, timeout: Duration? = null) {
logger.info { "Running: '${cmd.joinToString(" ")}'" }
val process = ProcessBuilder(cmd).start()
val ok = if (timeout == null) {
process.waitFor()
true
} else {
process.waitFor(timeout.inWholeNanoseconds, TimeUnit.NANOSECONDS)
}

val stdout = process.inputStream.bufferedReader().readText().trim()
if (stdout.isNotBlank()) {
logger.info { "STDOUT:\n$stdout" }
}
val stderr = process.errorStream.bufferedReader().readText().trim()
if (stderr.isNotBlank()) {
logger.info { "STDERR:\n$stderr" }
}

if (!ok) {
logger.info { "Timeout!" }
process.destroy()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import org.jacodb.ets.dto.convertToEtsMethod
import org.jacodb.ets.model.EtsClassSignature
import org.jacodb.ets.model.EtsMethodSignature
import org.jacodb.ets.test.utils.loadEtsFileDtoFromResource
import org.jacodb.ets.utils.loadEtsFileAutoConvert
import org.jacodb.ets.utils.loadEtsFileAutoConvertWithDot
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

Expand Down Expand Up @@ -72,10 +72,10 @@ class EtsFromJsonTest {

@Test
fun testLoadEtsFileAutoConvert() {
val path = "source/example.ts"
val res = this::class.java.getResource("/$path")
val path = "/source/example.ts"
val res = this::class.java.getResource(path)
?: error("Resource not found: $path")
val etsFile = loadEtsFileAutoConvert(res.path)
val etsFile = loadEtsFileAutoConvertWithDot(res.path.drop(1), res.path.drop(1).substringBeforeLast("/"))
println("etsFile = $etsFile")
}

Expand Down
Loading

0 comments on commit 6e24eda

Please sign in to comment.