Compare commits
4 commits
1120374505
...
2fd68e991f
Author | SHA1 | Date | |
---|---|---|---|
2fd68e991f | |||
3b9bb4df88 | |||
8402dc68b9 | |||
dfc9815e83 |
6 changed files with 94 additions and 25 deletions
|
@ -4,7 +4,7 @@
|
|||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
31
qodana.yaml
Normal file
31
qodana.yaml
Normal file
|
@ -0,0 +1,31 @@
|
|||
#-------------------------------------------------------------------------------#
|
||||
# Qodana analysis is configured by qodana.yaml file #
|
||||
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
||||
#-------------------------------------------------------------------------------#
|
||||
version: "1.0"
|
||||
|
||||
#Specify inspection profile for code analysis
|
||||
profile:
|
||||
name: qodana.starter
|
||||
|
||||
#Enable inspections
|
||||
#include:
|
||||
# - name: <SomeEnabledInspectionId>
|
||||
|
||||
#Disable inspections
|
||||
#exclude:
|
||||
# - name: <SomeDisabledInspectionId>
|
||||
# paths:
|
||||
# - <path/where/not/run/inspection>
|
||||
|
||||
projectJDK: 23 #(Applied in CI/CD pipeline)
|
||||
|
||||
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||
#bootstrap: sh ./prepare-qodana.sh
|
||||
|
||||
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
||||
#plugins:
|
||||
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||
|
||||
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||
linter: jetbrains/qodana-jvm:latest
|
|
@ -173,7 +173,7 @@ fun App() {
|
|||
traceTree = traceTreeStr.toString()
|
||||
|
||||
funcTraceTree =
|
||||
getInvokeTraceTreeString(sf,relations)
|
||||
getInvokeTraceTreeString(sf)
|
||||
|
||||
ttGraph = generateGraph(relations)
|
||||
ivGraph = sf.functions.getInvokeGraph()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package core
|
||||
|
||||
import java.io.File
|
||||
|
@ -11,6 +9,15 @@ class SourceFile {
|
|||
companion object {
|
||||
val function_define_regex = """\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)\s*\{""".toRegex() // main(){ 匹配函数名
|
||||
|
||||
/**
|
||||
* C文件预处理器
|
||||
* 处理内容:
|
||||
* 删除注释;
|
||||
* 处理 #define;
|
||||
* 处理连续创建变量;
|
||||
* 格式化代码
|
||||
* @return 处理好的C源代码
|
||||
*/
|
||||
fun formatSource(src: String): String {
|
||||
// 去掉注释
|
||||
val noComment = src.lines()
|
||||
|
@ -21,7 +28,7 @@ class SourceFile {
|
|||
}
|
||||
|
||||
// 处理 DEFINE, 支持如下
|
||||
// #define SOMETHING ANOTHERTHING 这样的
|
||||
// #define SOMETHING ANOTHER 这样的
|
||||
// #define ADD(a, b) a + b
|
||||
val noFuncInDefine = StringBuilder()
|
||||
// 获取 define 的内容
|
||||
|
@ -30,7 +37,7 @@ class SourceFile {
|
|||
if (line.trim().startsWith("#define")) {
|
||||
val args = line.trim().split(" ")
|
||||
if (args.size >= 3) {
|
||||
if (args[1].contains("(")){ // Define Function
|
||||
if (args[1].contains("(")) { // Define Function
|
||||
val defFuncName = args[1].split('(').first().trim()
|
||||
val defineFuncArgs = args[1]
|
||||
.split('(').last()
|
||||
|
@ -44,31 +51,31 @@ class SourceFile {
|
|||
val prev = line.split("$defFuncName(") // 应该是调用之前的内容
|
||||
val later = prev.last().split(')') // 应该是调用之后的内容
|
||||
val callArgs = later.first().split(',').map { it.trim() } // 和上面一样的
|
||||
if (callArgs.size <= defineFuncArgs.size){
|
||||
if (callArgs.size <= defineFuncArgs.size) {
|
||||
var newFunction = defineFunc
|
||||
for (i in callArgs.indices){ // 参数不够不管了
|
||||
newFunction = newFunction.replace(defineFuncArgs[i],callArgs[i])
|
||||
for (i in callArgs.indices) { // 参数不够不管了
|
||||
newFunction = newFunction.replace(defineFuncArgs[i], callArgs[i])
|
||||
}
|
||||
//改回去
|
||||
noFuncInDefine.append(prev.first() + newFunction + later.last())
|
||||
noFuncInDefine.append('\n')
|
||||
}else{ // 参数多了我有啥办法
|
||||
} else { // 参数多了我有啥办法
|
||||
noFuncInDefine.append(line)
|
||||
noFuncInDefine.append('\n')
|
||||
}
|
||||
}else if (!line.startsWith('#')) {
|
||||
} else if (!line.startsWith('#')) {
|
||||
noFuncInDefine.append(line)
|
||||
noFuncInDefine.append('\n')
|
||||
}
|
||||
}
|
||||
}else { // #define SOMETHING ANOTHER 这样的
|
||||
} else { // #define SOMETHING ANOTHER 这样的
|
||||
simpleDefineList[args[1]] = args[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 可能上面代码因为没define没执行,这里保证下
|
||||
if (noFuncInDefine.isEmpty()){
|
||||
if (noFuncInDefine.isEmpty()) {
|
||||
noFuncInDefine.append(noComment)
|
||||
}
|
||||
|
||||
|
@ -84,7 +91,7 @@ class SourceFile {
|
|||
noDefine.append('\n')
|
||||
}
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
noDefine.append(noFuncInDefine)
|
||||
}
|
||||
|
||||
|
@ -142,10 +149,14 @@ class SourceFile {
|
|||
}
|
||||
|
||||
constructor(content: String) {
|
||||
this.content = formatSource(content.trim())
|
||||
this.content = formatSource(content)
|
||||
}
|
||||
|
||||
fun parseFunction(): List<CFunction> { // 找所有的函数定义
|
||||
/**
|
||||
* 找所有的函数定义
|
||||
* @return 所有定义的函数
|
||||
*/
|
||||
fun parseFunction(): List<CFunction> {
|
||||
val result = mutableListOf<CFunction>()
|
||||
function_define_regex.findAll(content).forEach {
|
||||
if (it.groups.size >= 2 && it.groups[1] != null) {
|
||||
|
@ -156,7 +167,12 @@ class SourceFile {
|
|||
return result
|
||||
}
|
||||
|
||||
fun getDef(): Map<String, List<String>> { // 获取所有的定义
|
||||
/**
|
||||
* 找所有的变量定义
|
||||
* @return Map of<函数名称 to List<定义的变量>>
|
||||
* @see utils.getDefineList
|
||||
*/
|
||||
fun getDef(): Map<String, List<String>> {
|
||||
val result = mutableMapOf<String, List<String>>()
|
||||
functions.forEach {
|
||||
result[it.name] = it.cParser.defineList
|
||||
|
@ -164,6 +180,11 @@ class SourceFile {
|
|||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务1:获取使用的值的情况
|
||||
* @return Map of<函数 to List<使用值的情况>>
|
||||
* @see utils.getUseList 获取要求的格式
|
||||
*/
|
||||
fun getUse(): Map<String, List<String>> {
|
||||
val globalResult = mutableMapOf<String, List<String>>()
|
||||
functions.forEach {
|
||||
|
@ -201,7 +222,7 @@ class SourceFile {
|
|||
useCache.append("${sentence.left}-def")
|
||||
}
|
||||
|
||||
DEFINE_VALUE_PARAM, CHANGE_VALUE_PARAM -> {
|
||||
DEFINE_VALUE_PARAM, CHANGE_VALUE_PARAM -> { // 作为参数出现的
|
||||
useCache.append(";${sentence.right}-use")
|
||||
}
|
||||
|
||||
|
@ -217,17 +238,17 @@ class SourceFile {
|
|||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
fun main() { // 测试用, NoGUI
|
||||
val sourceFile = SourceFile(File("src/main/CTests/test.c"))
|
||||
val funcs = sourceFile.parseFunction()
|
||||
val functions = sourceFile.parseFunction()
|
||||
val relations = mutableMapOf<String, List<Relation>>()
|
||||
funcs.forEach {
|
||||
functions.forEach {
|
||||
relations.putAll(parseRelation(it.name, it.getTraceTree().getStringRepr()))
|
||||
}
|
||||
for (function in funcs) {
|
||||
println(funcs.getInvokeTree(function.name).getFuncRepr(function.name))
|
||||
for (function in functions) {
|
||||
println(functions.getInvokeTree(function.name).getFuncRepr(function.name))
|
||||
}
|
||||
|
||||
println(generateGraph(relations))
|
||||
println(funcs.getInvokeGraph())
|
||||
println(functions.getInvokeGraph())
|
||||
}
|
|
@ -1,6 +1,13 @@
|
|||
package utils
|
||||
|
||||
/**
|
||||
* UI页面的默认代码
|
||||
*/
|
||||
@Suppress("EqualsOrHashCode")
|
||||
object DefaultCode {
|
||||
/**
|
||||
* @return 默认代码
|
||||
*/
|
||||
override fun toString(): String {
|
||||
return """
|
||||
int main(){
|
||||
|
@ -19,7 +26,17 @@ object DefaultCode {
|
|||
""".trimIndent()
|
||||
}
|
||||
|
||||
/**
|
||||
* 我们借来测试行数
|
||||
* @return 默认代码行数
|
||||
*/
|
||||
override fun hashCode(): Int {
|
||||
return this.toString().count { it == '\n' } + 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix:
|
||||
* Qodana `Reports classes that override equals() but do not override hashCode(), or vice versa.`
|
||||
*/
|
||||
override fun equals(other: Any?) = false
|
||||
}
|
|
@ -31,7 +31,7 @@ fun getTraceTreeString(traceTreeStr: String, funcName: String): String {
|
|||
return sb.toString()
|
||||
}
|
||||
|
||||
fun getInvokeTraceTreeString(sourceFile: SourceFile, relations: Map<String, List<Relation>>): String {
|
||||
fun getInvokeTraceTreeString(sourceFile: SourceFile): String {
|
||||
val tree = StringBuilder()
|
||||
for (function in sourceFile.functions) {
|
||||
val chain = sourceFile.functions.getInvokeTree(function.name).getFuncRepr(function.name)
|
||||
|
|
Loading…
Reference in a new issue