This commit is contained in:
Kagura 2024-10-29 23:03:45 +08:00
parent c7f8a7c30b
commit fa9ff80214
11 changed files with 552 additions and 84 deletions

124
.idea/uiDesigner.xml Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View file

@ -28,7 +28,7 @@ compose.desktop {
mainClass = "MainKt" mainClass = "MainKt"
nativeDistributions { nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) targetFormats(TargetFormat.Dmg, TargetFormat.Exe, TargetFormat.Deb)
packageName = "VariableRelation" packageName = "VariableRelation"
packageVersion = "1.0.0" packageVersion = "1.0.0"
} }

View file

@ -1,89 +1,183 @@
import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.material.*
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.*
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.ButtonColors
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.Window import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application import androidx.compose.ui.window.application
import core.SourceFile import core.*
import ui.TextfieldWithLineNumber
import utils.*
@OptIn(ExperimentalTextApi::class)
@Composable @Composable
@Preview @Preview
fun App() { fun App() {
var text by remember { mutableStateOf("") }
var isReady by remember { mutableStateOf(false) }
var source: SourceFile? = null var source: SourceFile? = null
val showResult = remember { mutableStateOf(false) }
var defineList by remember { mutableStateOf("") }
var useList by remember { mutableStateOf("") }
var traceTree by remember { mutableStateOf("") }
var funcTraceTree by remember { mutableStateOf("") }
var page by remember { mutableStateOf(0) }
var ttGraph by remember { mutableStateOf("") }
var ivGraph by remember { mutableStateOf("") }
MaterialTheme { MaterialTheme {
Column( when {
modifier = Modifier.fillMaxSize() showResult.value -> {
.padding(horizontal = 10.dp, vertical = 5.dp), Dialog(onDismissRequest = {
horizontalAlignment = Alignment.Start, showResult.value = false
verticalArrangement = Arrangement.Center page = 0
) { }) {
Text("请输入您的代码") AlertDialog(
title = {
TextField( Text(
value = text, text = when (page) {
onValueChange = { text = it }, 0 -> "函数定义的变量"
modifier = Modifier.fillMaxWidth(0.95f) 1 -> "函数内每条语句的定义和使用"
.weight(1f), 2 -> "函数内每个变量 def-use 链"
textStyle = TextStyle.Default.copy(fontFamily = FontFamily("monospace")) 3 -> "函数间每个变量 def-use 链"
) else -> "出错了"
},
Row( color = Color.Black,
modifier = Modifier.fillMaxWidth(0.9f) fontWeight = FontWeight.Bold,
.padding(vertical = 5.dp), fontSize = 24.sp,
horizontalArrangement = Arrangement.SpaceEvenly, textAlign = TextAlign.Center
verticalAlignment = Alignment.CenterVertically )
) { },
Button( text = {
modifier = Modifier.padding(vertical = 10.dp), Text(
onClick = { text = when (page) {
val s = SourceFile(text.toString()) 0 -> defineList
text = s.content 1 -> useList
source = s 2 -> traceTree
}, 3 -> funcTraceTree
) { else -> "出错了(ง •̀_•́)ง"
Text("格式化") },
} modifier = Modifier
.fillMaxSize()
Button( .wrapContentHeight(),
modifier = Modifier.padding(vertical = 10.dp), textAlign = TextAlign.Start,
onClick = { color = Color.Black
source = SourceFile(text.toString()) )
isReady = true },
}, onDismissRequest = {
enabled = !isReady showResult.value = false
) { },
Text("分析") confirmButton = {
TextButton(
onClick = {
page = (page + 1) % 4
}
) {
Text("下一个")
}
},
dismissButton = {
TextButton(
onClick = {
if (page < 2){
showResult.value = false
}else{
if (page == 2){
openGraph(ttGraph)
}else if (page == 3){
openGraph(ivGraph)
}
}
}
) {
Text(
if (page < 2){
"关闭"
}else{
"查看图像(在线)"
}
)
}
},
modifier = Modifier
.padding(5.dp)
.wrapContentSize(),
shape = RoundedCornerShape(20.dp),
backgroundColor = Color(0xffFAF0E6)
)
} }
} }
} }
Surface(
modifier = Modifier.fillMaxSize()
.background(color = Color(0xFFFBFBFB))
) {
Column(
modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp, vertical = 5.dp),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Center
) {
Text("请输入您的代码")
TextfieldWithLineNumber(
modifier = Modifier.weight(1f).fillMaxWidth(),
) {
if (it.isEmpty()) {
return@TextfieldWithLineNumber
}
val sf = SourceFile(it)
source = sf
try {
sf.parseFunction()
} catch (e: Exception) {
// 分析失败
defineList = e.printStackTrace().toString()
return@TextfieldWithLineNumber
}
defineList =
try {
val def = getDefineList(sf.getDef())
def.ifEmpty {
"分析失败:可能输入有错误!"
}
} catch (e: Exception) {
e.printStackTrace().toString()
}
useList = try {
getUseList(sf.getUse())
} catch (e: Exception) {
e.printStackTrace().toString()
}
val relations = mutableMapOf<String, List<Relation>>()
val traceTreeStr = StringBuilder()
sf.functions.forEach { func ->
traceTreeStr.append(getTraceTreeString(func.getTraceTree().getStringRepr(),func.name))
relations.putAll(parseRelation(func.name,func.getTraceTree().getStringRepr()))
}
traceTree = traceTreeStr.toString()
funcTraceTree =
getInvokeTraceTreeString("main",sf,relations)
ttGraph = generateGraph(relations)
ivGraph = sf.functions.getInvokeGraph("main")
showResult.value = true
}
}
}
} }
} }
fun main() = application { fun main() = application {
Window(onCloseRequest = ::exitApplication) { Window(onCloseRequest = ::exitApplication) {
App() App()

View file

@ -127,16 +127,14 @@ fun List<CFunction>.find(name: String): CFunction? {
* @param name: 从哪个函数开始查找 * @param name: 从哪个函数开始查找
* @return 特制的 TraceTree * @return 特制的 TraceTree
*/ */
fun List<CFunction>.getInvokeTree(name: String): List<TraceTree> { fun List<CFunction>.getInvokeTree(name: String): Map<String,List<TraceTree>> {
// 先找到开始的函数 // 先找到开始的函数
val func = this.find(name) val func = this.find(name) ?: return emptyMap()
if (func == null) {
return emptyList()
}
val invokeTrees = mutableListOf<TraceTree>() val invokeTrees = mutableListOf<TraceTree>()
val args = mutableListOf<String>() val args = mutableListOf<String>()
var funcName = "" var funcName = ""
val resultMap = mutableMapOf<String,List<TraceTree>>()
func.cParser.sentenceList.forEach { sentence -> func.cParser.sentenceList.forEach { sentence ->
// 🌰: // 🌰:
@ -153,9 +151,12 @@ fun List<CFunction>.getInvokeTree(name: String): List<TraceTree> {
val tt = function.getTraceTree(info) val tt = function.getTraceTree(info)
invokeTrees.addAll(tt) invokeTrees.addAll(tt)
} }
args.clear() if (funcName != "") {
funcName = "" resultMap[funcName] = invokeTrees
args.clear()
funcName = ""
}
} }
} }
return invokeTrees return resultMap
} }

View file

@ -24,8 +24,8 @@ fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<
// 处理跨函数 // 处理跨函数
for (path in crossLabelPaths) { for (path in crossLabelPaths) {
val parts = path.split(":") val parts = path.split(":")
if (parts.size == 2) { if (parts.size == 3) {
val subPath = parts[1].split("->") // 栗子: main:z->a->m val subPath = parts[2].split("->") // 栗子: A:main:z->a->m
if (subPath.size >= 2) { if (subPath.size >= 2) {
val fromNode = subPath[0] // 这里就是z val fromNode = subPath[0] // 这里就是z
val toNode = subPath[1] // 下一个就是 val toNode = subPath[1] // 下一个就是

View file

@ -4,6 +4,8 @@ package core
import java.io.File import java.io.File
import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.OPERATION.*
import utils.getDefineList
import utils.getUseList
class SourceFile { class SourceFile {
companion object { companion object {
@ -20,7 +22,7 @@ class SourceFile {
} }
val content: String val content: String
private var functions: List<CFunction> = emptyList() var functions: List<CFunction> = emptyList()
constructor(file: File) { constructor(file: File) {
if (!file.isFile) { if (!file.isFile) {
@ -52,8 +54,8 @@ class SourceFile {
return result return result
} }
fun getUse(): List<List<String>> { fun getUse(): Map<String,List<String>> {
val globalResult = mutableListOf<List<String>>() val globalResult = mutableMapOf<String,List<String>>()
functions.forEach { functions.forEach {
val funcResult = mutableListOf<String>() val funcResult = mutableListOf<String>()
@ -97,7 +99,7 @@ class SourceFile {
if (useCache.isNotEmpty()) { if (useCache.isNotEmpty()) {
funcResult.add(useCache.toString()) funcResult.add(useCache.toString())
} }
globalResult.add(funcResult) globalResult[it.name] = funcResult
} }
return globalResult return globalResult
} }
@ -120,4 +122,7 @@ fun main() {
println(sourceFile.getUse()) println(sourceFile.getUse())
println(generateGraph(relations)) println(generateGraph(relations))
println(funcs.getInvokeGraph("main")) println(funcs.getInvokeGraph("main"))
println(getDefineList(sourceFile.getDef()))
println(getUseList(sourceFile.getUse()))
} }

View file

@ -47,7 +47,12 @@ fun List<TraceTree>.getStringRepr(): String {
return result.toString() return result.toString()
} }
fun List<TraceTree>.getFuncRepr(func: String): String { fun Map<String, List<TraceTree>>.getFuncRepr(func: String): String {
val strs = this.getStringRepr() val result = StringBuilder()
return strs.split('\n').filter { it.startsWith(func) }.joinToString("\n") this.forEach { (name, list) ->
result.append("$name:")
val listRepr = list.getStringRepr()
result.append(listRepr.split('\n').filter { it.startsWith(func) }.joinToString("\n"))
}
return result.toString()
} }

View file

@ -0,0 +1,154 @@
package ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Card
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import core.SourceFile
import utils.DefaultCode
@OptIn(ExperimentalTextApi::class)
@Composable
fun TextfieldWithLineNumber(
modifier: Modifier = Modifier,
onSubmit: (String) -> Unit
) {
var linesText by remember { mutableIntStateOf(DefaultCode.hashCode()) }
var text by remember { mutableStateOf(DefaultCode.toString()) }
val showFinishFormatDialog = remember { mutableStateOf(false) }
when {
showFinishFormatDialog.value -> {
FinishFormatDialog {
showFinishFormatDialog.value = false
}
}
}
val monospaceTextStyle = TextStyle.Default.copy( // 左右都是等宽字体
fontFamily = FontFamily("monospace"),
fontSize = 16.sp
)
// 同步左右滚动进度
val linesTextScroll = rememberScrollState()
val scriptTextScroll = rememberScrollState()
LaunchedEffect(linesTextScroll.value) {
scriptTextScroll.scrollTo(linesTextScroll.value)
}
LaunchedEffect(scriptTextScroll.value) {
linesTextScroll.scrollTo(scriptTextScroll.value)
}
Column(modifier = modifier) {
Row(
modifier = Modifier.fillMaxWidth()
.weight(1f)
.background(color = Color(0xFFfafafa))
) {
// 左边是行号
BasicTextField(
modifier = Modifier
.fillMaxHeight()
.width(12.dp * linesText.toString().length)
.verticalScroll(linesTextScroll),
value = IntRange(1, linesText).joinToString(separator = "\n"),
readOnly = true, // 不能去编辑行号那里
textStyle = monospaceTextStyle.copy(
textAlign = TextAlign.End,
color = Color(0xff69b0c5)
),
onValueChange = {})
Spacer(modifier = Modifier.width(10.dp))
// 输入内容的地方
BasicTextField(
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.verticalScroll(scriptTextScroll),
value = text,
textStyle = monospaceTextStyle,
onValueChange = { textFieldValue ->
val nbLines = textFieldValue.count { it == '\n' } + 1
if (nbLines != linesText) linesText = nbLines
text = textFieldValue.replace("\t"," ") // \t 显示不了
},
)
}
}
Row(
modifier = Modifier.fillMaxWidth(0.9f)
.padding(vertical = 5.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Button(
modifier = Modifier.padding(vertical = 10.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFC6E7FF)),
onClick = {
val s = SourceFile(text)
text = s.content
showFinishFormatDialog.value = true
},
) {
Text("格式化")
}
Button(
modifier = Modifier.padding(vertical = 10.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFD4F6FF)),
onClick = { onSubmit(text) },
) {
Text("分析")
}
}
}
@Composable
fun FinishFormatDialog(onDismissRequest: () -> Unit) {
Dialog(onDismissRequest = { onDismissRequest() }) {
Card(
modifier = Modifier
.height(130.dp)
.padding(16.dp),
shape = RoundedCornerShape(20.dp),
backgroundColor = Color(0xffFFE3E3)
) {
Text(
text = "格式化成功",
modifier = Modifier
.fillMaxSize()
.wrapContentSize(Alignment.Center),
textAlign = TextAlign.Center,
)
}
}
}

View file

@ -0,0 +1,25 @@
package utils
object DefaultCode {
override fun toString(): String {
return """
int main(){
int x=0,y =0;
int z =1;
printf("%d\n",z);//用户输入
x= A(z);
y= x;
printf("%d\n",y);//main函数尾部
}
int A(int a){
int m = a;
return m;
}
""".trimIndent()
}
override fun hashCode(): Int {
return this.toString().count { it == '\n' } + 1
}
}

View file

@ -0,0 +1,23 @@
package utils
import java.awt.Desktop
import java.net.URI
import java.util.*
fun openBrowser(uri: URI) {
val osName by lazy(LazyThreadSafetyMode.NONE) { System.getProperty("os.name").lowercase(Locale.getDefault()) }
val desktop = Desktop.getDesktop()
when {
Desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.BROWSE) -> desktop.browse(uri)
"mac" in osName -> Runtime.getRuntime().exec("open $uri")
"nix" in osName || "nux" in osName -> Runtime.getRuntime().exec("xdg-open $uri")
else -> desktop.browse(uri)
}
}
fun openGraph(graph: String){
val site = "https://dreampuf.github.io/GraphvizOnline/#"
val data = java.net.URLEncoder.encode(graph,"utf-8")
.replace("+","%20")
openBrowser(URI.create(site+data))
}

View file

@ -0,0 +1,37 @@
package utils
import core.*
fun getDefineList(defList: Map<String, List<String>>): String =
// Example:
// {main=[x, y, z], A=[a, m]}
defList.toString()
.replace("{", "")
.replace("}", "") // 解决左右括号
.replace("=", ":def")
fun getUseList(useList: Map<String, List<String>>): String =
// Example:
// {main=[void, x-def, y-def, z-def, z-use, x-def;z-use, y-def;x-use, y-use], A=[a-def, m-def;a-use, m-use]}
useList.toString()
.replace("{}", "") // 如果是空就直接删了
.replace("{", "") // 右括号留着
.replace("=", ":{") // 换掉
.replace("], ", "]}\n") // 保证不是最后一个
.replace(", ", "],[") // 逗号后面有空格
.replace(";", "")
fun getTraceTreeString(traceTreeStr: String, funcName: String): String {
val sb = StringBuilder("$funcName:\n")
traceTreeStr.split('\n').forEach {
sb.append(" ${it.trim()}\n")
}
return sb.toString()
}
fun getInvokeTraceTreeString(funcName: String, sourceFile: SourceFile, relations: Map<String, List<Relation>>): String {
val func = sourceFile.functions.find(funcName) ?: return "未找到 $funcName 函数"
val originPart = getTraceTreeString(func.getTraceTree().getStringRepr(), func.name)
val invokeTree = sourceFile.functions.getInvokeTree(funcName).getFuncRepr(funcName)
return originPart + "\n" + invokeTree
}