diff --git a/athena-all/README.md b/athena-all/README.md index 8c6c2713e..9bc918068 100644 --- a/athena-all/README.md +++ b/athena-all/README.md @@ -1,4 +1,31 @@ -+ jdk version:jdk17 +## startup config ++ build.gradle.kts + + 添加Maven repository ++ ResourceUtils + + ULTRAMAN_URL_PREFIX + + 修改域名为真实域名 + + Const.BOT_URL + + 修改域名为真实域名 + + Const.CONF_DASH_URL + + 修改IP为真实IP + + Const.CONF_AI_PROXY_URL + + 修改IP为真实IP + + Const.CONF_M78_URL + + 修改域名为真实域名 ++ UltramanWindowFactory + + 修改nginxChatUrl为真实url ++ WsClient + + 修改ws url为真实url ++ GuideService + + HttpClient.post修改为真实url ++ BotService + + 修改BOT_URL为真实的BOT调用的url ++ OpenImageConsumer + + imgUrl修改 ++ plugin.xml + + vendor里的url改为真实url + +## change log + 2023年12月25日 + 1.代码注释 comment_side_car + 2.代码建议 code_suggest_sidecar @@ -8,14 +35,42 @@ + 3.屏蔽一些功能+部署到外网 + 4.单元测试 + 5.查找bug + + 6.单元测试 test_code + 2023年12月26日 + 搭一个外网版本 + 2023年12月27日 + 简化ide中生成代码的流程 + 2024年01月01日 + 尽量不再使用静态方法,而是使用ioc和aop ++ 2024年01月29日 + + 优化了单元测试代码 + + 优化了引入po + 最后的版本这是效能组所有中间件+效能工具+平台的决策大脑(给用户测的) + 方法重命名 rename_method ++ 函数参数重命名 rename_method_param_name + translation 选中翻译 -+ suggest_sidecar 方法review(建议) \ No newline at end of file ++ suggest_sidecar 方法review(建议) ++ 2024年02月19日 + + 方法补全:biz_completion + + 生成代码:biz_sidecar + + 都统一叫生成代码 + + 添加的代码注释支持多语言切换 + + prompt支持了函数能力 + + 代码补全也能自动分析代码作用范围(开启代码分析) ++ 2024年02月21日 + + 优化调试模式 (用来测试的prompt:24414:test_prompt) ++ 2024年03月02日(以后很长时间内都不在做新功能了,只优化现有的4个功能 生成代码 补全代码 智能命名 单元测试) + + 解决了生成单元测试的一个bug(service里的代码在server创建测试方法的时候,不能列出老的方法) + + 如果生成局部代码的时候,所处的位置是一个注释行,则在下一行开始生成代码 + + 给参数重命名 ++ 2024年04月22日 + + 支持生成完整的测试类 test_class_code ++ 2024年06月02日 + + 所有prompt替换为bot(以后bot是第一元素) + + 代码通过Inlay生成(100294) + + 方法名重命名(rename_method->) + + 添加注释(comment_2->) + + 单元测试(test_code->) + + 生成代码(biz_sidecar->) + + 问题修复(bug_fix->) \ No newline at end of file diff --git a/athena-all/build.gradle.kts b/athena-all/build.gradle.kts index ceaf8e9ee..7d6f08527 100644 --- a/athena-all/build.gradle.kts +++ b/athena-all/build.gradle.kts @@ -1,3 +1,5 @@ +import java.util.* + plugins { id("java") id("org.jetbrains.kotlin.jvm") version "1.7.20" @@ -5,11 +7,20 @@ plugins { } group = "run.mone" -version = "2024.01.16.1" + +// Load properties from src/main/resources/athena.properties +val athenaProperties = Properties().apply { + file("src/main/resources/athena.properties").inputStream().use { load(it) } +} +// Access the property +val pluginVersion = athenaProperties.getProperty("pluginVersion") + +version = pluginVersion repositories { mavenLocal() + maven(uri("https://maven.aliyun.com/repository/public/")) mavenCentral() } @@ -19,7 +30,7 @@ repositories { intellij { version.set("2023.1.2") type.set("IC") // Target IDE Platform - plugins.set(listOf("com.intellij.java"/* Plugin Dependencies */)) + plugins.set(listOf("com.intellij.java","JUnit","org.jetbrains.plugins.terminal"/* Plugin Dependencies */)) } tasks { @@ -53,26 +64,148 @@ tasks { } dependencies { + + implementation("org.slf4j:slf4j-api:2.0.13") + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("com.ibeetl:beetl:3.15.4.RELEASE") + implementation("org.antlr:antlr4-runtime:4.7.2") implementation("io.netty:netty-all:4.1.36.Final") implementation("com.google.code.gson:gson:2.8.9") implementation("run.mone:openai:1.4-SNAPSHOT") implementation("com.google.guava:guava:32.0.1-jre") - implementation("com.squareup.okhttp3:okhttp:4.11.0") - implementation("com.squareup.okhttp3:okhttp-sse:4.11.0") + implementation("com.squareup.okhttp3:okhttp:4.10.0") + implementation("com.squareup.okhttp3:okhttp-sse:4.10.0") implementation("org.apache.commons:commons-lang3:3.13.0") implementation("com.github.javaparser:javaparser-core:3.25.6") implementation("org.nutz:nutz:1.r.69.20210929") implementation("mysql:mysql-connector-java:8.0.28") implementation("org.apache.commons:commons-lang3:3.14.0") - + implementation("run.mone:codegen:1.5-SNAPSHOT") compileOnly("org.projectlombok:lombok:1.18.26") annotationProcessor("org.projectlombok:lombok:1.18.26") testCompileOnly("org.projectlombok:lombok:1.18.26") testAnnotationProcessor("org.projectlombok:lombok:1.18.26") -} \ No newline at end of file +} + +buildscript { + repositories { + mavenLocal() + maven(uri("https://maven.aliyun.com/repository/public/")) + mavenCentral() + } + dependencies { + classpath("com.guardsquare:proguard-gradle:7.5.0") + } +} + +tasks.register("proguard") { + verbose() +// keepdirectories()// By default, directory entries are removed. + ignorewarnings() + target("17") + + // Alternatively put your config in a separate file +// configuration("config.pro") + + // Use the jar task output as a input jar. This will automatically add the necessary task dependency. + injars(tasks.named("instrumentedJar")) +// injars("build/libs/*.jar") + +// outjars("build/${rootProject.name}-obfuscated.jar") +// injars("Athena-2024.06.03.2.jar") + outjars("build/instrumented-${rootProject.name}-obfuscated.jar") + val javaHome = System.getProperty("java.home") + // Automatically handle the Java version of this build, don't support JBR + // As of Java 9, the runtime classes are packaged in modular jmod files. +// libraryjars( +// // filters must be specified first, as a map +// mapOf("jarfilter" to "!**.jar", +// "filter" to "!module-info.class"), +// "$javaHome/jmods/java.base.jmod" +// ) + + // Add all JDK deps +// if( ! properties("skipProguard").toBoolean()) { + File("$javaHome/jmods/").listFiles()!!.forEach { libraryjars(it.absolutePath) } +// } + +// libraryjars(configurations.runtimeClasspath.get().files) +// val ideaPath = getIDEAPath() + + // Add all java plugins to classpath +// File("$ideaPath/plugins/java/lib").listFiles()!!.forEach { libraryjars(it.absolutePath) } + // Add all IDEA libs to classpath +// File("$ideaPath/lib").listFiles()!!.forEach { libraryjars(it.absolutePath) } + + libraryjars(configurations.compileClasspath.get()) + + dontshrink() + dontoptimize() + //useuniqueclassmembernames() + +// allowaccessmodification() //you probably shouldn't use this option when processing code that is to be used as a library, since classes and class members that weren't designed to be public in the API may become public + + adaptclassstrings("**.xml") + adaptresourcefilecontents("**.xml")// or adaptresourcefilecontents() + + // Allow methods with the same signature, except for the return type, + // to get the same obfuscation name. + //overloadaggressively() + // Put all obfuscated classes into the nameless root package. +// repackageclasses("") + + printmapping("build/proguard-mapping.txt") + + adaptresourcefilenames() + optimizationpasses(9) + allowaccessmodification() +// mergeinterfacesaggressively() + renamesourcefileattribute("SourceDir") + keepattributes("Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod") + + obfuscationdictionary("dic.txt") + + // 保留除指定包路径外的所有类不被混淆 + keep(""" + class !com.xiaomi.youpin.tesla.ip.common.**, + !com.xiaomi.youpin.tesla.ip.service.**, + !run.mone.ultraman.common.**, + !run.mone.ultraman.service.** { + *; + } + """.trimIndent()) + + // 允许特定包路径下的类被混淆 +// keep(""" +// class com.xiaomi.youpin.tesla.ip.common.** { *; } +// class com.xiaomi.youpin.tesla.ip.service.** { *; } +// class run.mone.ultraman.common.** { *; } +// """.trimIndent()) + +} + + +//tasks { +// prepareSandbox { +// dependsOn("proguard") +// doFirst { +// println("${rootProject.name}-${rootProject.version}") +// val original = File("build/libs/instrumented-${rootProject.name}-${rootProject.version}.jar") +// println(original.absolutePath) +// val obfuscated = File("build/instrumented-${rootProject.name}-obfuscated.jar") +// println(obfuscated.absolutePath) +// if (original.exists() && obfuscated.exists()) { +// original.delete() +// obfuscated.renameTo(original) +// println("info: plugin file obfuscated") +// } else { +// println("error: some file does not exist, plugin file not obfuscated") +// } +// } +// } +//} \ No newline at end of file diff --git a/athena-all/dic.txt b/athena-all/dic.txt new file mode 100644 index 000000000..7f3198a02 --- /dev/null +++ b/athena-all/dic.txt @@ -0,0 +1,4586 @@ +0000O000000o +000O00000Oo +000O00000o0 +000O00000o +000O00000oO +000O00000oo +000O0000O0o +000O0000OOo +000O0000Oo0 +000O0000Oo +000O0000OoO +00O0000Ooo +00O0000o00 +00O0000o0 +00O0000o0O +00O0000o0o +00O0000o +00O0000oO0 +00O0000oO +00O0000oOO +000O0000oOo +00O0000oo0 +00O0000oo +00O0000ooO +00O0000ooo +00O00oOooO +00O00oOooo +00O000O00o +00O000O0OO +00O000O0Oo +000O00oOoOo +00O000O0o0 +00O000O0o +00O000O0oO +00O000O0oo +00O000OO00 +00O000OO0o +00O000OO +00O000OOOo +00O000OOo0 +000O000OOo +00O000OOoO +00O000OOoo +00O000Oo00 +00O000Oo0 +00O000Oo0O +00O000Oo0o +00O000OoO0 +00O00O0Oo +00O000OoO +000O000OoOO +00O000OoOo +00O000Ooo0 +00O000Ooo +00O000OooO +00O000Oooo +00O000o000 +00O000o00 +00O000o00O +00O000o00o +000O000o0 +00O000o0O0 +00O000o0O +00O000o0OO +00O000o0Oo +00O000o0o0 +00O000o0o +00O000o0oo +00O000o +00O000oO00 +000O000oO0 +00O000oO0O +00O000oO0o +00O000oO +00O000oOO0 +00O000oOO +00O000oOOO +00O000oOOo +00O000oOo0 +00O000oOo +000O000oOoO +00O000oOoo +00O000oo0 +00O000oo0O +00O000oo0o +00O000oo +00O000ooO0 +00O000ooO +00O000ooOO +00O000ooOo +000O000ooo0 +00O000ooo +00O000oooO +00O000oooo +00oooOoO +00O00oOOoo +00O00O000o +00O00O00Oo +00O00O00o0 +00O00O00o +000O00O00oO +00O00O00oo +00O00O0O0o +00O00O0OO +00O00O0OOo +00O00O0Oo0 +00O00O0OoO +00O00O0Ooo +00O00O0o00 +00O00O0o0 +00O00O0o0O +0O00O0o0o +0O00O0o +0O00O0oO0 +0O00O0oOO +0O00O0oOo +0O00O0oo0 +0O00O0oo +0O00O0ooO +0O00O0ooo +00O00OO0O +0O00OO0o +0O00OOOo +0O00OOo0 +0O00OOo +0O00OOoO +0O00OOoo +0O00Oo00 +0O00Oo00o +0O00Oo0 +00O00Oo0OO +0O00Oo0Oo +0O00Oo0o0 +0O00Oo0o +0O00Oo0oO +0O00OooOO +0O00Oo0oo +0O00Oo +0O00OoO0 +0O00OoO0o +00O00OoO0O +0O00Ooo +0O00OoO +0O00OoOO0 +0O00OoOO +0O00OoOo0 +0O00OoOo +0O00OoOoO +0O00OoOoo +0O00Ooo00 +00O00Ooo0 +0O00Ooo0O +0O00Ooo0o +0O00OooO0 +0O00OooO +0O00OooOo +0O00Oooo0 +0O00Oooo +0O00Ooooo +0O00OoooO +00O00o0000 +0O00o000 +0O00o000O +0O00o000o +0O00o00 +0O00o00O0 +0O00o00O +0O00o00OO +0O00o00Oo +0O00o00o0 +00O00o00o +0O00o00oO +0O00o00oo +0O00o0 +0O00o0O00 +0O00o0O0 +0O00oo000 +0O00o0O0O +0O00o0O0o +0O00o0O +00O00o0OO0 +0O00o0OO +0O00o0OOO +0O00o0OOo +0O00o0Oo0 +0O00o0Oo +0O00o0OoO +0O00o0Ooo +0O00o0o00 +0O00o0o0 +00O00o0o0O +0O00o0o0o +0O00o0o +0O00o0oO0 +0O00o0oO +0O00o0oOO +0O00o0oOo +0O00o0oo0 +0O00o0oo +0O00o0ooO +000O00o0ooo +00O00o +00O00oO0O0 +00O00oO000 +00O00oO00 +00O00oO00O +00O00oO0OO +00O00oO00o +00O00oO0 +00O00oO0O +00O00ooO00 +0O00oO0Oo +0O00oO0o0 +0O00oO0o +0O00oO0oO +0O00oO0oo +0O00oO +0O00oOO0o +0O00oOO00 +0O00oOO0 +00O00oOO0O +0O00oOo +0O00oOO +0O00oOOO0 +0O00oOOO +0O00oOOOO +0O00oOOOo +0O00oOOo0 +0O00oOOo +0O00oOOoO +00O00oOo00 +0O00oOo0 +0O00oOo0O +0O00oOo0o +0O00oOoO +0O00oOoOO +0O00oOoo0 +0O00oOoo +0O00oo00 +0O00oo00O +00O00oo00o +0O00oo0 +0O00oo0O0 +0O00oo0O +0O00oo0OO +0O00oo0Oo +0O00oo0o0 +0O00oo0o +0O00oo0oo +0O00oo +00O00ooO0 +0O00ooO0O +0O00ooO0o +0O00ooO +0O00ooOo0 +0O00ooOO0 +0O00ooOO +0O00ooOOO +0O00ooOOo +0O00ooOo +00O00ooOoO +0O00ooOoo +0O00ooo00 +0O00ooo0 +0O00ooo0o +0O00ooo +0O00oooO0 +0O00oooO +0O00oooOO +0O00oooOo +00O00oooo0 +0O00oooo +0O00ooooo +0ooooooo +0O0O00oO +0O0O000o +0O0O00OO +0O0O00Oo +0O0O00o0 +0O0O00o +00O0O0O0o +0O0O0O +0O0O0OO0 +0O0O0OO +0O0O0OOO +0O0O0OOo +0O0O0Oo0 +0O0O0OoO +0O0O0Ooo +0O0O0o00 +00O0O0o0 +0O0O0o0O +0O0O0o0o +0O0O0o +0O0O0oO0 +0O0O0oO +0O0O0oOO +0O0O0oOo +0O0O0oo0 +0O0O0oo +000O0O0ooO +00O0O0ooo +00O0OoOo +00O0OoOO +00O0OO00O +00O0OO00o +00O0OO0O +00O0Oo0o0 +00O0OO0Oo +00O0OO0o0 +00O0OO0oO +0O0OO0oo +0O0OOO00 +0O0OOoo +0O0OOoO +0O0OOO0 +0O0OOO0O +0O0OOO0o +0OO0oO +0O0OOOO +00O0OOOOO +0O0OOOOo +0O0OOOo0 +0O0OOOo +0O0OOOoO +0O0OOOoo +0O0OOo00 +0O0OOo0O +0O0OOo0o +0O0OOo +00O0OOoO0 +0O0OOoOO +0O0OOoOo +0O0OOoo0 +0O0OOooO +0O0OOooo +0O0Oo000 +0O0Oo00 +0O0Oo00O +0O0Oo00o +00O0Oo0 +0O0Oo0O0 +0O0Oooo +0O0Oo0O +0O0Oo0OO +0O0Oo0Oo +0O0Oo0o +0O0Oo0oO +0O0Oo0oo +0o00o00O +00O0Oo +0O0OoO00 +0O0OoO0 +0O0OoO0O +0OooOO +0OoO0o +0O0OoO +0O0OoOO0 +0O0OoOOO +0O0OoOOo +00O0OoOo0 +0O0OoOoO +0O0OoOoo +0O0Ooo00 +0O0Ooo0 +0O0Ooo0O +0O0Ooo0o +0O0Ooo +0O0OooO0 +0O0OooO +00O0OooOO +0O0OooOo +0O0Oooo0 +0O0OoooO +0O0Ooooo +0O0o0000 +0O0o000 +0O0o000O +0O0o000o +0O0o00 +00O0o00O0 +0O0o00O +0O0o00OO +0O0o00Oo +0O0o00o0 +0O0o00o +0O0o00oO +0O0o00oo +0O0o0 +0O0o0O00 +00O0o0O0 +0O0o0O0O +0O0o0O0o +0O0o0O +0O0o0OO0 +0O0oo0o +0O0o0OO +0O0o0OOO +0O0o0OOo +0O0o0Oo0 +000O0o0Oo +00O0o0OoO +00O0o0Ooo +00O0o0o00 +00O0o0o0 +00O0o0o0O +00O0o0o0o +00O0o0oO0 +00O0o0oO +00O0o0oOO +00O0o0oOo +0O0o0oo +0O0o0ooO +0oOOoOO +0O0o +0O0oO000 +0O0oO00 +0O0oO0oO +0O0oO00O +0O0oO00o +00O0oO0 +0O0oO0O0 +0O0oO0O +0O0oO0OO +0O0oO0Oo +0O0oO0o0 +0O0oO0o +0O0oO0oo +0o0Oo0o0 +0O0oO +00O0oOO00 +0O0oOO0 +0o00O00O0 +0O0oOO0O +0O0oOO0o +0O0oOO +0O0oOOO0 +0O0oOOOo +0O0oOOo0 +0Oo0OOo +00O0oOOo +0O0oOOoO +0O0oOOoo +0O0oOo00 +0O0oOo0 +0ooO0Ooo +0O0oOo0O +0O0oOo0o +0O0oOo +0O0oOoO0 +00O0oOoO +0O0oOoOO +0O0oOoOo +0OOoOoo +0O0oOoo0 +0O0oOoo +0O0oOooO +0O0oOooo +0O0oo000 +0O0oo00 +00O0oo00O +0O0oo00o +0O0oo0 +0O0oo0O0 +0O0oo0O +0O0oo0OO +0O0oo0Oo +0O0oo0o0 +0O0oo0oO +0O0oo0oo +00O0oo +0O0ooO00 +0O0ooOo +0O0oooo +0O0oooO +0O0ooO0 +0O0oooOo +0O0ooO0O +0O0ooO0o +0O0ooO +00O0ooOO0 +0O0ooOO +0O0ooOOO +0O0ooOOo +0O0ooOo0 +0O0ooOoO +0O0ooOoo +0O0ooo00 +0O0ooo0 +0O0ooo0O +00O0ooo0o +0O0ooo +0O0oooO0 +0O0oooOO +0O0oooo0 +0O0ooooO +0O0ooooo +0OO0000 +0OO0000o +0OoOOO +000OO000OO +00OO000Oo +00OO000o0 +00OO000o +00OO000oO +00OO000oo +00OO00OO +00OO00O0 +00OO00O0o +00OO00O +00OO00OOO +0OO00OOo +0OO00Oo0 +0OO0ooO +0OO00Oo +0OO00OoO +0OO00Ooo +0OO00o00 +0OO00o0O +0OO00o0o +00OO00oO0 +0OO00oO +0OO00oOO +0OO00oOo +0OO00oo0 +0OO00oo +0OO00ooO +0OO00ooo +0OO0O00o +0OO0O0O +00OO0O0OO +0OO0O0Oo +0OO0O0o0 +0OO0oOo +0OO0oOO +0OO0O0o +0OO0O0oO +0OO0O0oo +0oOo00 +0OO0OO0o +00OOo00 +0OO0OO +0OO0OOO +0OO0OOOO +0OO0OOOo +0OO0OOo0 +0OO0OOo +0OO0OOoO +0OO0OOoo +0OO0Oo00 +00OO0Oo0 +0OO0Oo0O +0OO0Oo0o +0Oo0Oo0O +0OO0OoO0 +0OO0OoO +0OO0OoOO +0Oo0Ooo0 +0OO0OoOo +0OO0Ooo0 +00OO0Ooo +0OO0OooO +0OO0Oooo +0OO0o000 +0OO0o00 +0OO0o00O +0OO0o00o +0OO0o0 +0OO0o0O0 +0OO0o0OO +00OO0o0Oo +0OO0o0o0 +0OO0o0o +0OO0o0oO +0OO0o0oo +0OO0o +0OO0oO00 +0OO0oO0 +0OO0oO0O +0OO0oO0o +00OO0oOO0 +0OoOOoOo +0OO0oOOO +0OO0oOOo +0OO0oOo0 +0OO0oOoO +0OO0oOoo +0OO0oo00 +0OO0oo0 +0OO0oo0O +00OO0oo0o +0OO0oo +0OO0ooO0 +0OO0ooOO +0OO0ooOo +0OO0ooo0 +0OO0ooo +0OO0oooO +0OO0oooo +0OOO000o +000OOO00 +00OOO00O0 +00OOO00Oo +00OOO00o0 +00OOO00o +00OOO00oO +00OOO00oo +00OOO0O0O +00OOO0O0o +00OOO0O +00o00OOOOO +0OOO0OO0 +0OOO0OOO +0OOO0OOo +0OOO0Oo0 +0OOO0oO +0OOO0Oo +0OOO0OoO +0OOO0Ooo +0OOO0o00 +00OOO0o0 +0OOO0o0O +0OOO0o0o +0OOO0o +0OOO0oO0 +0OOO0oOO +0OOO0oOo +0OOO0oo0 +0OOO0oo +0OOO0ooO +00OOO0ooo +0OOO +0OOOO00O +0OOOO00o +0OOOO0 +0OOOOoO +0OOOOo0 +0OOOOoo +0OOOO0O +0OOOO0OO +00OOOO0Oo +0OOOO0o0 +0OOOO0oO +0OOOO0oo +0OOOOO00 +0OOOOO0 +0OOOOO0o +0OOOOO +0OOOOOO +0OOOOOOO +00OOOOOOo +0OOOOOo0 +0OOooOo +0OOoooo +0OOOOOo +0OOOOOoO +0OOOOOoo +0OOOOo00 +0OOOOo0O +0OOOOo0o +00OOOOo +0OOOOoO0 +0OOOOoOO +0OOOOoOo +0OOOOoo0 +0OOOOooO +0OOOOooo +0OOOo000 +0OOo000 +0OOOo00 +00OOOo00O +0OOOo00o +0OOOo0 +0ooOOo00 +0OOOo0O0 +0OOOo0O +0OOOo0OO +0OOOo0Oo +0OOOo0o0 +0OOOo0o +00OOOo0oO +0OOOo0oo +0OOOo +0OOOoO00 +0OOOoO0 +0OOOoO0O +0o0ooo0OO +0OOOoO0o +0OOOoO +0OOOoOO0 +00OOOoOO +0OOOoOOO +0OOOoOOo +0OOOoOo0 +0OOOoOo +0OOOoOoO +0OOOoOoo +0ooO00O0 +0OOOoo00 +0OOOoo0 +000o00O0oO0 +00OOOoo0O +00OOOoo0o +00OOOoo +00OOOooO0 +00OOOooO +00o0OOoOoo +00OOOooOO +00OOOooOo +00OOOooo0 +00OOOooo +0OOOoooO +0OOOoooo +0OOo0000 +0OOo000O +0OOo000o +0OOo00O0 +0OOo00O +0OOo00OO +0OOo00Oo +00OOo00o0 +0OOo00o +0OOo00oO +0OOo00oo +0ooOo +0OOo0 +0OOo0O00 +0OOo0OO +0OOo0Oo +0OOoo00 +00OOo0O0 +0OOo0O0O +0OOo0O0o +0OOoOOoO +0OOo0OO0 +0OOo0OOO +0OOo0OOo +0OOo0Oo0 +0OOo0OoO +0OOo0Ooo +00OOo0o00 +0OOo0o0 +0OOo0o0O +0OOo0o0o +0OOo0o +0OOo0oO0 +0OOo0oO +0OOo0oOO +0OOo0oOo +0OOo0oo0 +00OOo0oo +0OOo0ooO +0OOo0ooo +0OOoO000 +0OOoO00 +0OOoO00O +0OOoO00o +0OOoO0 +0OOoO0O0 +0OOoO0o +00OOoO0O +0OOoO0OO +0OOoO0Oo +0OOoO0o0 +0OOoO0oO +0OOoO0oo +0OOoO +0OOoOO00 +0OOoOO0O +0OOoOO0o +00OOoOO +0OOoOOO0 +0OOoOOO +0OOoOOOO +0OOoOOOo +0OOoOOo0 +0OOoOOo +0OOoOOoo +0OOoOo00 +0OOoOo0 +00OOoOo0O +0OOoOo0o +0OOoOo +0OOoOoO0 +0oO0OO0 +0OOoOoO +0OOoOoOO +0OOoOoOo +0OOoOoo0 +0OOoOooO +00OOoOooo +0OOoo000 +0OOoo00O +0OOoo00o +0OOoo0 +0OOoo0O0 +0OOoo0O +0OOoo0OO +0OOoo0Oo +0OOoo0o0 +000OOoo0o +00OOoo0oO +00OOoo0oo +00OOoo +00OOooO00 +00OOooO0 +00OOooO0O +00OOooO0o +00OOooO +00OOooOO0 +00OOooOO +0OOooOOO +0OOooOOo +0OOooOo0 +0OOooOoO +0OOooOoo +0OOooo00 +0OOooo0 +0OOooo0O +0OOooo0o +00OOooo +0OOoooO0 +0OOoooO +0OOoooOO +0OOoooOo +0OOoooo0 +0OOooooO +0OOooooo +0Oo00000 +0Oo0000O +00Oo0000o +0Oo000 +0Oo000O0 +0Oo000O +0Oo000OO +0Oo000Oo +0Oo000o0 +0Oo000o +0Oo000oO +0Oo000oo +00Oo00 +0Oo00O00 +0Oo00O0 +0Oo0o0Oo +0Oo00O0O +0Oo00O0o +0Oo00O +0Oo00OO0 +0Oo0o0o +0Oo00Oo +00Oo00OO +0Oo00OOO +0Oo00OOo +0Oo00Oo0 +0Oo0o0O0 +0Oo00OoO +0Oo00Ooo +0Oo00o00 +0Oo00o0 +0Oo00o0O +00Oo00o0o +0Oo00o +0Oo00oO0 +0Oo00oOO +0Oo00oo0 +0Oo00oo +0Oo00ooO +0Oo00ooo +0Oo0 +0Oo0O000 +00Oo0O00 +0Oo0O00O +0Oo0O00o +0Oo0O0 +0Oo0O0O0 +0Oo0O0O +0Oo0O0OO +0Oo0O0Oo +0Oo0O0o0 +0Oo0O0o +00Oo0O0oO +0Oo0O0oo +0o00oO00 +0o00OO00 +0Oo0O +0Oo0OO00 +0Oo0OO0 +0Oo0OO0O +0Oo0OO0o +0Oo0OO +00Oo0OOO0 +0Oo0OOOO +0Oo0OOOo +0Oo0OOo0 +0Oo0OOoO +0Oo0OOoo +0Oo0Oo00 +0Oo0Oo0 +0Oo0Oo0o +0Oo0Oo +000Oo0OoO0 +00Oo0OoO +00Oo0OoOo +00Oo0Ooo +00Oo0OooO +00Oo0Oooo +00Oo0o000 +00Oo0o00 +00Oo0o00O +00Oo0o00o +00Oo0o0 +0Oo0o0O +0Oo0o0o0 +0Oo0o0oO +0Oo0o0oo +0Oo0o +0Oo0oO00 +0Oo0ooO +0Oo0oOO +0Oo0oo0 +00Oo0ooo +0Oo0oO0 +0Oo0oO0O +0Oo0oO0o +0Oo0oO +0Oo0oOO0 +0Oo0oOOO +0Oo0oOOo +0Oo0oOo0 +0Oo0oOo +00Oo0oOoO +0Oo0oOoo +0Oo0oo00 +0Oo0oo0O +0Oo0oo0o +0Oo0oo +0Oo0ooO0 +0Oo0ooOO +0Oo0ooOo +0Oo0ooo0 +00Oo0oooO +0Oo0oooo +0Oo +0OoO0000 +0OoO000 +0OoO000O +0OoO000o +0OoO00O0 +0OoO00O +0OoO00OO +00OoO00Oo +0OoO00o0 +0OoO00o +0OoO00oO +0OoO00oo +0OoO0 +0OoO0O00 +0OoO0Oo +0OoO0O0 +0OoO0O0O +00OoO0O0o +0OoO0O +0OoO0OO0 +0OoO0OO +0OoO0OOO +0OoOo00O +0OoO0OOo +0OoO0Oo0 +0OoO0OoO +0OoO0Ooo +00OoO0o00 +0OoO0o0 +0OoO0o0O +0OoO0o0o +0OoO0oO0 +0OoO0oo +0OoO0oO +0OoO0oOO +0OoO0oOo +0OoO0oo0 +00OoO0ooO +0OoO0ooo +0OoO +0OoOO000 +0OoOOo0 +0OoOOOO +0OoOO0O +0OoOOoo +0OoOOoO +0OoOOO0 +00OoOOOo +0OoOoOo +0OoOoOO +0OoOO00 +0OoOO00O +0OoOO00o +0OoOO0 +0OoOO0O0 +0OoOO0OO +0OoOO0Oo +000OoOO0o0 +00OoOO0o +00OoOO0oO +00OoOO0oo +00OoOo +00OoOO +00OoOOO0O +00OoOOO0o +00OoOOOO0 +00OoOOOOO +00OoOOOOo +0OoOOOo0 +0OoOOOoO +0OoOOOoo +0OoOOo00 +0OoOOo0O +0OoOOo0o +0OoOOo +0OoOOoO0 +0OoOOoOO +00OoOOoo0 +0OoOOooO +0OoOOooo +0OoOo000 +0OoOooo +0OoOoo0 +0OoOo00 +0OoOo00o +0OoOo0 +0OoOo0O0 +00OoOo0o +0OoOo0O +0OoOo0OO +0OoOo0Oo +0OoOo0o0 +0OoOo0oO +0OoOo0oo +0OoOoO00 +0OoOoO0 +0OoOoO0O +00OoOoO0o +0OoOoO +0OoOoOO0 +0OoOoOOO +0OoOoOOo +0OoOoOo0 +0OoOoOoO +0OoOoOoo +0OoOoo00 +0OoOoo0O +00OoOoo0o +0OoOoo +0OoOooO0 +0OoOooO +0OoOooOO +0OoOooOo +0OoOooo0 +0OoOoooO +0OoOoooo +0Ooo0000 +00Ooo000 +0Ooo000O +0Ooo000o +0Ooo00 +0Ooo00O0 +0Ooo00O +0Ooo00OO +0Ooo00Oo +0Ooo00o0 +0Ooo00o +00Ooo00oO +0o00oo00o +0Ooo00oo +0Ooo0 +0Ooo0O00 +0Ooo0O0 +0Ooo0O0O +0Ooo0O0o +0Ooo0O +0Ooo0OO0 +00Oooo00 +0Ooo0oO +0Ooo0Oo +0Ooo0OO +0o000O0OO +0o000oO0O +0Ooo0OOO +0Ooo0OOo +0Ooo0OoO +0Ooo0Ooo +00Ooo0o00 +0Ooo0o0 +0Ooo0o0o +0Ooo0o +0Ooo0oO0 +0Ooo0oOO +0Ooo0oOo +0Ooo0oo0 +0Ooo0oo +0Ooo0ooO +00Ooo0ooo +0o0oo +0Ooo +0OooO000 +0OooO0O +0Ooooo0 +0OooooO +0OoooOO +0OoooOo +0OooO00 +0OooO00O +OooO00o +OooO0O0 +OooO0OO +OooO0Oo +OooO0o0 +OooO0o +OooO0oO +OooO0oo +OooO +0OooOO00 +OooOO0 +OooOO0O +OooOO0o +OooOOO0 +OooOOO +OooOOOO +OooOOOo +OooOOo0 +OooOOo +0OooOOoO +OooOOoo +OooOo00 +OooOo0 +OooOo0O +OooOo0o +OooOo +OooOoO0 +OooOoO +OooOoOO +0OooOoOo +OooOoo0 +OooOoo +OooOooO +OooOooo +Oooo000 +Oooo00O +Oooo00o +Oooo0 +Oooo0O0 +0Oooo0O +Oooo0OO +Oooo0o0 +Oooo0o +Oooo0oO +Oooo0oo +Oooo +OoooO00 +OoooO0 +OoooO0O +0OoooO0o +OoooO +OoooOO0 +o000oOoO +OoooOOO +OoooOOo +OoooOo0 +OoooOoO +OoooOoo +Ooooo00 +0Ooooo0O +Ooooo0o +OooooO0 +OooooOO +OooooOo +Oooooo0 +Oooooo +OoooooO +Ooooooo +o0OoOo0 +0o0OoO0O +ooOO +o00O0O +o00Oo0 +o00Ooo +o00o0O +o00ooo +oo000o +o00oO0o +o00oO0O +0o0oo000 +o0ooOO0 +o0ooOOo +o0ooOoO +o0OOO0o +o0Oo0oo +o0OO00O +oo0o0Oo +o0O0O00 +o000OOo +00oo0oOoO +0ooo0Ooo +0ooOo00O +0o0OoOO0 +0o0O00oo +0o0ooo00 +0o000OOoo +0o000OOOo +0o000OOOO +0o000OOO0 +0o0000000 +o000000 +o000000O +o000000o +o00000 +o00000O0 +o00000O +o00000OO +o00000Oo +o00000o0 +0o00000o +o0000Ooo +o00000oO +o00000oo +o0000 +o0000O00 +o0000oo +o0000oO +o0000O0 +o0000O0O +0o0000O0o +o000OO +o0000O +o0000OO0 +o0000OO +o0000OOO +o0000OOo +o0000Oo0 +o0000Oo +o0000OoO +0o0000o00 +o0000o0 +o0000o0O +o0000o0o +o0000o +o0000oO0 +o0000oOO +o0000oOo +o0000oo0 +o0000ooO +0o0000ooo +o000 +o000O000 +o000OoO +o000O0o +o000Ooo +o000O0O +o000Oo0 +o000O00 +o000O00O +0o000O00o +o000O0 +o000O0Oo +o000OO0O +o000O0O0 +o000O0o0 +o000O0oO +o000O0oo +o000O +o000OO00 +0o000OO0 +o0OoO0o +o000OO0o +o000OOO +o000OOo0 +o000OOoO +o000Oo00 +o000Oo0O +o000Oo0o +o000Oo +0o000OoO0 +o000OoOO +o000OoOo +o000Ooo0 +o000OooO +o000Oooo +o000o000 +o000o00 +o000o00O +o000o00o +0o000o0 +oooo00o +o000o0O0 +o000o0O +o000o0OO +o000o0Oo +o000o0o0 +o000o0o +o000o0oO +o000o0oo +00o000o +0o000oO00 +0o000oO0 +0o000oO0o +0o000oO +0o000oOO0 +0o000oOO +0o000oOOO +0o000oOOo +0o000oOo0 +0o000oOo +o000oOoo +o000oo00 +o000oo0 +o000oo0O +o000oo0o +o000oo +o000ooO0 +o000ooO +o000ooOO +0o000ooOo +o000ooo0 +o000ooo +o000oooO +o000oooo +o00 +o00O0000 +o0O0ooO +o00oOoo +o00O000 +0o00O000O +o00O000o +o00O00 +o00O00O +oOO00O +o00O00OO +o00O00Oo +o00O00o0 +o00O00o +o00O00oO +0o00O00oo +oo00o +o00O0 +o00O0O00 +o00O0O0 +o00O0O0O +o00O0O0o +o00O0OO0 +oo0o0O0 +o00O0OO +0o00Oo00O +o00O0OOO +o00O0OOo +o00O0Oo0 +oo0oOO0 +o00O0Oo +o00O0OoO +o00O0Ooo +o00O0o00 +o00oOOo +0o00oOOO +o00O0o0 +o00O0o0O +o00O0o0o +o00O0o +o00O0oO +o00O0oOO +o00O0oOo +o00O0oo0 +o00O0oo +0o00O0ooO +o00O0ooo +o00O +o00OO000 +o00OO00O +o00OO00o +o00OO0 +o00OO0O0 +o00OO0O +o00OO0OO +0o00OO0Oo +o00OO0o0 +o00OO0o +o00OO0oO +o00OO0oo +oo0O +o00OO +o00OOO00 +o00OOO0 +o00OOO0O +0o00OOO0o +o0o0Oo +o00OOO +o00OOOO0 +o00OOOO +o00OOOOo +oOooo0o +o00OOOo0 +o00OOOo +o00OOOoO +00o00OOOoo +0o00OOo00 +0o00OOo0 +0o00OOo0O +0o00OOo0o +0o00OOo +0o00OOoO0 +0o00OOoO +0o00OOoOO +0o00OOoOo +0o00OOoo0 +o00OOoo +o00OOooO +o00OOooo +o00OoOoO +o00Oo000 +o00Oo00 +o00Oo00o +o00Oo0O0 +o00Oo0O +0o00Oo0OO +o00Oo0Oo +o00Oo0o0 +o00Oo0o +o00Oo0oO +o00Oo0oo +o0oOO +o00Oo +o00OoO00 +o00OoO0 +0o00OoO0O +o00OoO0o +o00OoO +o00OoOO0 +o00OoOO +o00OoOOO +o00OoOOo +o00OoOo0 +o00OoOo +o00OoOoo +0o00Oooo0 +o00Ooo00 +o00Ooo0 +o00Ooo0O +o00Ooo0o +o00OooO0 +o00OooO +o00OooOO +o00OooOo +o0O00o0 +0o00Oooo +o00OoooO +o00Ooooo +o00o0000 +o00o000 +o00o000O +o00o000o +oo00oO +o00o00 +o00o00O0 +0o00o00OO +o00o00Oo +o00o00o0 +o00o00o +o00o00oO +o00o00oo +o00o0 +o00o0O00 +o00o0O0 +o00o0O0O +0o00o0O0o +o00o0OO0 +o00o0OO +o00o0OOO +o00o0OOo +o00o0Oo0 +o00o0Oo +o00o0OoO +o00o0Ooo +o00o0o00 +0o00o0o0 +o00o0o0O +o00o0o0o +o00o0o +o00o0oO0 +o00o0oO +o00o0oOO +o00o0oOo +o00o0oo0 +o00o0oo +0o00o0ooO +o00o0ooo +o00o +o00oo000 +o00oO000 +o00oO00O +o00oO00o +o00oOo +o00oO0 +o00oO0O0 +00o00oO0OO +0o00oO0Oo +0o00oO0o0 +0o00oO0oO +0o00oO0oo +0o00oO +0o00oOOoo +0o00oOO00 +0o00oOO0 +0o00oOO0O +0o00oOO0o +o0oOOo +o0ooOO +o00oOO +o00oOOO0 +o00oOOOO +o00oOOOo +o00oOOo0 +o00oOOoO +o00oOo00 +0o00oOo0 +o00oOooO +o00oOo0O +o00oOo0o +o00oOoO0 +o00oOoO +o00oOoOO +o00oOoOo +o00oOoo0 +o00oOooo +0o00oo00 +o00oo00O +o00oo0 +o00oo0OO +o00oo0O0 +o00oo0O +o00oo0Oo +o00oo0o0 +o00oo0o +o00oo0oO +0o00oo0oo +o0O0o +o00oo +o00ooO00 +o00ooO0 +o00ooO0O +o00ooO0o +o00ooO +o00ooOO0 +o00ooOO +0o00ooOOO +o00ooOOo +o00ooOo0 +o00ooOo +o00ooOoO +o00ooOoo +o00ooo00 +o00ooo0 +o00ooo0O +o00ooo0o +0o00oooO0 +o00oooO +o00oooOO +o00oooOo +o00oooo0 +o00oooo +o00ooooO +o00ooooo +o0 +o0O00000 +0o0O0000 +o0O0000O +o0O0000o +o0O000 +o0O000O +o0OoOoOo +o0O000Oo +o0OoOoOO +o0O000o0 +o0O000o +0o0O000oO +o0ooOoOO +o0O000oo +o0O00 +o0O00O0 +o0OoO00O +o0O00O0o +o0O00O +o0O00OO +o0O00OOO +0o0O00Oo0 +o0O00Oo +o0oO0Ooo +o0O00OoO +o0O00Ooo +o0O00o00 +o0O00o0O +o0O00o0o +o0O00o +o0O00oO0 +00o0O00oO +0o0O00oOO +0o0O00oOo +0o0O00oo0 +0o0Oo0oOO +0o0O00ooO +0o0O00ooo +0o0O0 +0o0ooOOOo +0o0O0O00O +0o0O0O0 +o0O0O0O +o0oO0O0o +o0O0oo0o +o0O0O0Oo +o0O0O0o0 +o0O0O0o +o0O0O0oO +o0O0O0oo +o0ooO +0o0O0O +o0O0OO0 +o0O0OO0O +o0O0OO +o0O0OOO0 +o0O0OOO +o0O0OOOo +o0O0OOo +o0O0OOoO +o0O0OOoo +0o0O0Oo00 +o0OooO0 +o0O0Oo0 +o0O0Oo0O +o0O0Oo0o +o0O0Oo +o0O0Oooo +o0O0OoO0 +oo0OOoo +o0O0OoO +0o0O0OoOO +o0O0OoOo +o0O0Ooo0 +o0O0Ooo +o0O0OooO +o0O0o000 +o0O0o00 +o0O0o00O +o0O0o00o +o0O0o0 +0o0O0o0O0 +o0O0o0O +o0O0o0OO +o0O0o0Oo +o0O0o0o0 +o0O0o0o +o0oOo0O0 +o0O0o0oO +o0O0o0oo +o0O0oo0O +0o0O0oO00 +oooOO0 +o0O0oO0 +o0O0oO0O +o0O0oO0o +o0O0oO +o0O0oOO0 +o0O0oOO +o0O0oo00 +o0O0oOOO +0o0O0oOOo +o0O0oOo0 +oo0oOOo +o0O0oOo +o0O0oOoO +o0O0oOoo +o0O0oo0 +o0O0oo +o0O0ooO0 +o0O0ooOO +0o0O0ooOo +o0O0ooo0 +o0O0ooo +o0O0oooO +o0O0oooo +o0O +o0OO000 +o0OO000o +oo0oO0 +oo0ooO +0o0OO00 +o0OO00OO +o0OO00oo +o0OO00Oo +o0OO00o0 +o0OoOoO +o0OO00o +o0OO0 +o0OO0O0 +o0OO0O0O +00o0OO0O0o +0o0OO0O +0o0OOoOOo +0o0OOoOoO +0o0OO0OO0 +0o0OO0OO +0o0OOoOO0 +0o0OO0OOO +0o0OO0OOo +0o0OO0Oo0 +0o0OO0Oo +o0OO0OoO +o0OOooO0 +o0OO0Ooo +o0OO0o00 +o0OO0o0 +o0OO0o0O +o0OO0o0o +o0OO0o +o0OO0oO0 +0o0OO0oo +o0OO0oO +o0OO0oOO +o0OOoooO +o0OO0oOo +o0OO0oo0 +o0OO0ooO +o0OO0ooo +o0OO +o0OOO00 +0o0OOO00O +o0OOO00o +o0OOO0 +o0OOO0O0 +o0OOO0O +o0OOO0OO +o0OOO0Oo +o0OOO0o0 +o0OOO0oO +o0OOO0oo +0o0OOO +o0OOOOoO +o0OOOO00 +o0OOOO0 +o0OOOO0o +o0OOOO +o0OOOOO0 +o0OOOOO +o0OOOOOO +o0OOOOOo +0o0OOOOo0 +o0OOOOo +o0OOOOoo +o0OOOo00 +o0OOOo0 +o0OOOo0O +o0OOOo0o +o0OOOo +o0OOOoO0 +o0OOOoO +0o0OOOoOO +o0OOOoOo +o0OOOoo0 +o0OOOoo +o0OOOooO +o0OOOooo +o0OOo000 +o0OOo00 +o0OOo00O +o0OOo00o +0o0OOo0 +o0OOo0O0 +o0OooOo +o0OOo0O +o0OOo0OO +o0OOo0Oo +o0OOo0o0 +o0OOo0o +o0OOo0oO +o0OOo0oo +0o0OOo +o0OOoO00 +o0OOoO0 +o0OOoO0O +o0OOoO0o +o0OOoO +o0OOoOO +o0OOoOOO +o0OOoOo0 +o0OOoOo +0o0OOoo00 +o0OOoo0 +o0OOoo0O +o0OOoo0o +o0OOoo +o0OOooO +o0OOooOO +o0OOooOo +o0OOooo0 +o0OOooo +00o0OOoooo +0o0Oo0000 +0o0Oo000 +0o0Oooo0O +0o0Oo00O0 +0o0Oo000O +0o0Oo000o +0o0Oo00 +0o0Oo00OO +0o0Oo00Oo +0o0oooOoo +o0Oo00o0 +o0Oo00o +o0Oo00oO +o0Oo00oo +o0Oo0 +o0ooO0O0 +o0Oo0O00 +o0Oo0O0 +o0Oo0O0O +0o0Oo0O0o +o0Oo0O +o0Oo0OO0 +o0Oo0OO +o0oOooO0 +o0ooOOOO +o0oOo000 +o0Oo0OOO +o0oOo0o0 +o0oOoo00 +0o0oO0OOo +o0Oo0OOo +o0Oo0Oo0 +o0Oo0Oo +o0Oo0OoO +o0Oo0oOo +o0Oo0Ooo +o0Oo0o00 +o0Oo0o0O +o0Oo0o0o +0o0Oo0o +o0Oo0oO0 +o0Oo0oO +o0Oo0oo0 +o0Oo0ooO +o0Oo0ooo +o0Oo +o0OooOoo +o0OoO000 +o0OoO0 +0o0OoO0O0 +o0oO0O00 +o0OoO0OO +o0ooOOO0 +o0OoO0Oo +o0OoO0o0 +o0OoO0oO +o0OoO0oo +o0OoO +o0OoOO00 +0o0OoOO0O +o0OoOO0o +o0OoOO +o0OoOOoO +o0OoOOO0 +o0OoOOO +o0OoOOOO +o0OoOOOo +o0OoOOo0 +o0OoOOo +0o0OoOOoo +o0OoOo00 +o0OoOo0O +o0ooOOoo +o0OoOo0o +o0OoOo +o0OoOoO0 +o0OoOoo0 +o0OoOoo +o0OoOooO +0o0OoOooo +o0Ooo000 +o0Ooo00 +o0Ooo00O +o0oOO0Oo +o0oOoOoo +o0Ooo00o +o0Ooo0 +o0Ooo0O0 +o0Ooo0O +0o0Ooo0OO +o0oOOOoo +o0OoooO0 +o0oOOO0o +o0Ooo0Oo +o0Ooo0o0 +o0Ooo0o +o0Ooo0oO +o0Ooo0oo +o0Ooo +00o0OooO00 +0o0OooO0O +0o0OooO0o +0o0OooO +0o0OooOO0 +0o0OooOO +0o0OooOOO +0o0OooOOo +0o0OooOo0 +0o0OooOoO +0o0Oooo00 +o0Oooo0 +o0Oooo0o +o0Oooo +o0OoooO +o0OoooOO +o0OoooOo +o0Ooooo0 +o0Ooooo +o0OooooO +0o0Oooooo +o0o0000 +o0o0o00O +o0o0000o +o0o000 +o0o000O0 +o0o000O +o0o000OO +o0o000Oo +o0o000o0 +0o0o000o +o0o000oO +o0o000oo +o0o00 +o0o00O00 +o0o00O0 +o0o00O0O +o0o00O0o +o0o00O +o0o00OO0 +0o0o00OO +o0o00OOO +o0o00OOo +o0o00Oo0 +o0o00Oo +o0o00OoO +o0o00Ooo +o0o00o00 +o0o00o0 +o0o00o0O +0o0o00o0o +o0o00o +o0o00oO0 +o0o00oO +o0o00oOO +o0o00oOo +o0o00oo0 +o0o00oo +o0o00ooO +o0o00ooo +0o0o0 +o0o0O000 +o0o0O00 +o0o0O00O +o0o0O00o +o0o0O0 +o0o0O0O0 +o0o0O0O +o0o0Oo00 +o0o0O0OO +0o0o0O0Oo +o0o0O0o0 +o0o0O0o +o0o0O0oO +o0o0O0oo +oO0Oo +oO0OO +o0ooo +o0o0O +o0o0OoO0 +0o0o0OO00 +o0o0OO0 +o0o0OO0O +o0o0OO0o +o0o0OO +o0o0OOO0 +o0o0OOO +o0o0OOOO +o0o0OOOo +o0o0OOo0 +0o0o0OOo +o0o0OOoO +o0o0OOoo +o0o0Oo0 +o0o0Oo0O +o0o0Oo0o +o0o0OoO +o0o0OoOO +o0o0OoOo +o0o0Ooo0 +000o0o0Ooo +00o0o0OooO +00o0o0Oooo +00o0o0o000 +00o0o0o00 +00o0o0o00o +00o0o0o0 +00o0o0o0O0 +00o0o0o0O +00o0o0o0OO +00o0o0o0Oo +0o0o0o0o0 +0o0o0o0o +0o0o0o0oO +0o0o0o0oo +0o0o0o +0o0o0oO00 +0o0o0oO0 +0o0o0oO0O +0o0o0oO0o +00o0oo00 +0o0o0oO +0o0o0oOO0 +0o0o0oOO +0o0o0oOOO +0o0o0oOOo +0o0o0oOo0 +0o0o0oOo +0o0o0oOoO +0o0o0oOoo +00o0o0oo00 +0o0o0oo0 +0o0o0oo0O +0o0o0oo0o +0o0o0oo +0o0o0ooO0 +0o0o0ooO +0o0o0ooOO +0o0o0ooOo +0o0o0ooo0 +00o0o0ooo +0o0o0oooO +0o0o0oooo +0o0o +0o0oO0000 +0ooooooO +0o0oO000 +0o0oO000O +0o0oO000o +0o0oO00 +00o0oO00O0 +0o0oO00O +0o0oO00Oo +0o0oO00OO +0o0oO00o0 +0o0oO00o +0o0oO00oO +0o0oO00oo +0o0oO0 +0o0oO0O0 +00o0oO0O +0o0oO0OO0 +0o0oO0OO +0o0oO0OOO +0o0oO0Oo +0o0oO0OoO +0o0oO0o00 +0o0oO0o0 +0o0oO0o0o +0o0oO0o0O +00o0oO0o +0o0oO0oO0 +0o0oO0oO +0o0oO0oOO +0o0oO0oo0 +0o0oO0oo +0o0oO0ooO +0o0oO0ooo +0o0oO +0o0oOO000 +00o0oOO00 +0o0oOO00O +0o0oOO00o +0o0oOO0 +0o0oOO0O0 +0o0oOO0O +0o0oOo0oO +0o0oOo0oo +0o0oOO0OO +0o0oOO0o0 +00o0oOO0o +0o0oOO0oO +0o0oOO0oo +0o0oOOO00 +0o0oOOO0 +0o0oOOO0O +0o0oOOO +0o0oOOOO0 +0o0oOOOO +0o0oOOOOO +00o0oOOOOo +0o0oOOOo0 +0o0oOOOo +0o0oOOOoO +0o0oOOo00 +0o0oOOo0 +0o0oOOo0O +0o0oOOo0o +0o0oOOoO0 +0o0oOOoO +0o0oOoO00 +o0oOOoOO +o0oOooOO +o0oOOoOo +o0oOOoo0 +o0oOOoo +o0oOOooO +o0oOOooo +o0oOo00 +o0oOo00O +0o0oOo00o +o0oOo0 +o0oOo0O +o0oOo0OO +o0oOo0Oo +o0oOo0o +o0oOo +o0oOoO0 +o0oOoO0o +o0oOoOo0 +0o0oOoO0O +o0oOoO +o0oOoOO0 +o0oOoOO +o0oOoOOO +o0oOoOOo +o0oOoOo +o0oOoOoO +o0oOoo0 +o0oOoo0O +0o0oOoo0o +o0oOoo +o0oOooO +o0oOooOo +o0oOooo0 +o0oOooo +o0oOoooO +o0oOoooo +o0oo0000 +o0oo000O +0o0oo000o +o0oo00O0 +o0oo00O +o0oo00OO +o0oo00Oo +o0oo00o0 +o0oo00o +o0oo00oO +o0oo00oo +o0oo0 +0o0oo0O00 +o0oo0O0 +o0oo0O0O +o0oo0O0o +o0oo0o +o0oo0O +o0oo0OO0 +o0oo0OO +o0oo0OOO +o0oo0OOo +0o0oo0Oo0 +o0oo0Oo +o0oo0OoO +o0oo0Ooo +o0oo0o00 +o0oo0o0 +o0oo0o0O +o0oo0o0o +o0oo0oO0 +o0oo0oO +0o0oo0oOO +o0oo0oOo +o0oo0oo0 +o0oo0oo +o0oo0ooO +o0oo0ooo +o0ooO000 +o0ooO00 +o0ooO00O +o0ooO00o +0o0ooO0 +o0ooO0O +o0ooO0OO +o0ooO0Oo +o0ooO0o0 +o0ooO0o +o0ooO0oO +o0ooO0oo +o0ooOO0O +o0ooOO0o +00o0ooOOO +0o0ooOOoO +0o0ooOo00 +0o0ooOo0 +0o0ooOo0o +0o0ooOo0O +0o0ooOo +0o0ooOooO +0o0ooOoO0 +0o0ooOoOo +0o0ooOoo0 +o0ooOoo +o0ooOooo +o0ooo000 +o0ooo00O +o0ooo00o +o0ooo0 +o0ooo0O +o0ooo0o0 +o0ooo0o +0o0ooo0oO +o0ooo0oo +o0oooO00 +o0oooO0 +o0oooO0o +o0oooO0O +o0oooO +o0oooOO0 +o0oooOO +o0oooOOo +0o0oooOOO +o0oooOo0 +o0oooOo +o0oooOoO +o0oooo00 +o0oooo0 +o0oooo0O +o0oooo0o +o0oooo +o0ooooO0 +0o0ooooO +o0ooooOo +o0ooooo0 +ooo0Oo0 +o0ooooo +o0oooooO +o0oooooo +o +oO00000 +oO00000o +0oO0000 +oO0000O +oO0000Oo +oO0000o0 +oO0000o +oO0000oO +oO0000oo +oO000 +oO000O0 +oO000O0O +0oO0Ooo00 +oO0Ooooo +oO000O0o +oO0o0o +oO000O +oO0OoOO0 +oO0OOooo +oO0OoOOO +oO0OOoO0 +oO0Oo0oo +0oO000OOO +oO0OO0oo +oO0OOooO +oO000OOo +oO0OoOoO +ooOOOOoo +oO0OOo0o +oO000Oo0 +oO000Oo +oO0OO0OO +0oO0OoOoo +oO0OOoo0 +oO000OoO +oO0OOo0O +oO000Ooo +oO000o00 +oO000o0 +ooOOOOOo +oO000o0o +oO000o +0oO0Oo0OO +oO000oO0 +oO000oO +oO0Ooo0O +oO000oOO +oO0Ooo0o +oO000oOo +oO000oo0 +oO000oo +oO0Oo0Oo +00oO000ooO +0oO0Oo0O0 +0oO000ooo +0oO00 +0oO00O00 +0oO0O0o0o +0ooOOoooO +0oO00O00o +0oO00O0 +0oO00O0O +0oO00O0Oo +oO0O0OoO +ooOOooOo +oO00O0o0 +oO00O0o +oOo00OO0 +oO00O0oO +oO0O0OOo +oO00O0oo +oO00O +0oO00OO0 +ooOOoOoO +oO0O0OOO +oO00OO0O +oO00OO +oO00OOO +oO00OOOo +oOo00Oo0 +ooOOoOOo +oO00OOo0 +0oO00OOo +oO0oOOO0 +oO00OOoO +oOOoOoOO +oO00OOoo +oO00Oo00 +oO00Oo0 +oO00Oo0O +oO00Oo0o +oO00Oo +0oO00oOOO +oO00OoO0 +oO00OoO +oOOoOOO0 +oO00OoOO +oO0oOOOo +oO00OoOo +oO00Ooo0 +oO00Ooo +oO00OooO +0oO00Oooo +oO0OOoOo +oO00o000 +oO00o00 +oO0OooOO +oO0OoOo0 +oO0OOO00 +oO00o00O +oO0OOoOO +oO00o00o +0ooOO0O +ooOOo0 +oO00o0 +oO0OOOoo +oO00o0O0 +oO00o0O +oO0OOOOo +oO00o0OO +oO0OOOoO +oO00o0Oo +0oO0OoO0O +oO0OOO0o +oO00o0o0 +oO00o0o +oO0OOOo0 +oO00o0oO +oO0OOO0O +oO00o0oo +oO00o +oO0OO0oO +0oO0OO000 +oOo00o0o +oO00oO00 +oO00oO0 +oO0OoooO +oOo00ooO +oO00oO0O +oO0OooOo +oOo00ooo +oO00oO0o +0oO00oO +oO00oOO0 +oO00oOO +oO0OO00o +oO00oOOo +oOo00oO0 +oO00oOo0 +oO00oOo +oO0OO00O +ooOOOOoO +00oOo00oOO +0oO00oOoO +0oOo00oOo +0oO00oOoo +0oO0OOOOO +0oO00oo00 +0oO00oo0 +0oO0OO0o0 +0oO00oo0O +0oO00oo0o +0oO00oo +oO00ooO0 +oO00ooO +oOo000Oo +oO00ooOO +oO00ooOo +oOo0000O +oO00ooo0 +oO00ooo +oOo000oo +0oO00oooO +oOo000o0 +oO00oooo +oO0 +oO0O000 +oO0Oo00O +ooOOoOo0 +oO0O000o +oO0O00 +oO0O00O +0oO0O00Oo +oO0O00o0 +oO0O00o +oO0O00oO +oO0O00oo +oOoo0 +oO0O0 +oO0O0O00 +oO0O0O0 +ooOOOoO0 +0oO0O0O0O +ooOOOoo0 +oO0O0O0o +oO0O0o +oO0O0O +oO0O0OO +oOo0oooO +ooOOOoOo +oO0O0Oo0 +oO0O0Oo +0oO0O0o0 +oO0O0o0O +oO0O0oO0 +oO0O0oO +oOo0o0oO +ooOOO0Oo +oO0O0oOO +oO0O0oOo +oOo00OOo +oO0O0oo0 +0oO0O0oo +oOo00OOO +ooOOO00O +oO0O0ooO +oO0O0ooo +ooo0o +oO0O +oO0OO00 +oO0OO0O +oO0OO0Oo +0oO0OO0o +oO0OOO0 +oO0OOO +oO0OooO0 +oO0OOOO0 +oO0OOOO +oO0OOOo +oO0OOo0 +oO0OOo +oO0OOoO +0oO0OOoo +oO0Oo00 +oO0Oo0 +oO0Oo0O +oO0Oo0o0 +oO0Oo0o +oO0OoO00 +oO0OoO0 +oO0OoO +oO0OoOO +0oO0OoOo +oO0Ooo0 +oO0Ooo +oO0OooO +oO0Oooo +oO0o0000 +oO0o000 +oO0o000O +ooOOoOoo +oO0o000o +00oO0o00 +0oO0o0oo0 +0oO0o00O0 +0oO0o00O +0oO0o00OO +0oO0o00Oo +0oO0o00o0 +0oO0o00o +0oO0o00oO +0oO0o00oo +0oO0o0 +oO0o0O00 +oO0o0O0 +oO0o0O0O +oO0o0O0o +oO0o0O +oO0o0OO0 +oO0o0OO +oO0o0OOO +oO0o0OOo +0oO0o0Oo0 +oO0o0Oo +oO0o0OoO +oO0o0Ooo +oO0o0o00 +oO0o0o0 +oO0o0o0O +oO0o0o0o +oO0o0oO0 +oO0o0oO +0oO0o0oOO +oO0o0oOo +oO0o0oo +oO0o0ooO +oO0o0ooo +oO0o +oO0oO000 +oO0oO00 +oOo00O0O +ooOOoOO0 +0oO0oO00O +oO0oO00o +oO0oO0 +oO0oO0O0 +oO0oO0O +oO0oO0OO +oOo00OoO +ooOOoOOO +oO0oO0Oo +oO0oO0o0 +0oO0oO0o +oO0oO0oO +oO0oO0oo +oOooo +oO0oO +oO0oOoOO +oO0oOO00 +oO0oOO0 +oO0oOO0O +oO0oOO0o +0oO0oOO +oO0oOOO +oO0oOOOO +oO0oOOo0 +oO0oOOo +oO0oOOoO +oO0oOOoo +oO0oOo00 +oO0oOo0 +oO0oOo0O +0oO0oOo0o +oO0oOo +oO0oOoO0 +oO0oOoO +oO0oOooo +oO0oOoOo +oO0oOoo0 +oO0oOoo +oO0oOooO +oO0oo000 +0oO0oo00 +oO0oo00O +oO0oo00o +oO0oo0 +oO0oo0O0 +oO0oo0O +oO0oo0OO +oO0oo0Oo +oO0oo0o0 +oO0oo0o +0oO0oo0oO +oO0oo0oo +oO0oo +oO0ooO00 +oO0ooO0 +oO0ooO0O +oO0ooO0o +oO0ooO +oO0ooOO0 +oO0ooOO +00oO0ooOOO +0oO0ooOOo +0oO0ooOo0 +0oO0ooOo +0oO0ooOoO +0oO0ooOoo +0oO0ooo00 +0oO0ooo0 +0oO0ooo0O +0oO0ooo0o +0oO0ooo +oOo00o0O +oO0oooO0 +oO0oooO +oO0oooOO +oOo00oo0 +oO0oooOo +oOo000OO +oO0oooo0 +oO0oooo +0oO0ooooO +oOo00o00 +oO0ooooo +oO +oOO00000 +oOO0000 +oOO0000O +oOO0000o +oOO000 +oOO000O0 +0oOO000O +oOO000OO +oOO000Oo +oOO000o0 +oOO000o +oOO000oO +oOO000oo +oOO00 +oOO00O00 +oOO00O0 +0ooooOO00 +oOO00O0O +oOO00O0o +oOO00OO0 +oOO00OO +oOO00OOO +oOO00OOo +oOO00Oo0 +oOO00Oo +ooooO000 +0oOO00OoO +ooooOoOo +oOO00Ooo +oOO00o00 +oOO00o0 +oOO00ooo +oOO00o0O +oOO00o0o +oOO00o +oOO00oO0 +0oOO00oO +ooooOOo0 +ooooO0oo +oOO00oOO +oOO00oOo +oOO00oo +oOO00ooO +oOO0 +ooooOoOO +oOO0O000 +0oOO0O00 +oOO0O00O +oOO0O00o +oOO0O0 +oOO0O0O0 +oOO0O0O +oOO0O0OO +oOO0O0Oo +oOO0O0o0 +oOO0O0o +0oOO0O0oO +oOO0O0oo +oOO0O +oOO0OO0 +oOO0OO0O +oOO0OO0o +oOO0OO +oOO0OOO +oOO0OOOO +oOO0OOOo +0oOO0OOo0 +oOO0OOo +oOO0OOoO +oOO0OOoo +oOO0Oo00 +oOO0Oo0 +oOO0Oo0O +oOO0Oo0o +oOO0Oo +oOO0OoO0 +00oOO0OoO +0oOO0OoOO +0oOO0OoOo +0oOO0Ooo0 +0oOO0Ooo +0oOO0OooO +0oOO0Oooo +0oOO0o00 +0ooooOOoo +0oOO0o00o +0oOO0o0 +oOO0o0O0 +oOO0o0O +oOO0o0OO +oOO0o0Oo +ooooO0O0 +oOO0o0o0 +oOO0o0o +oOO0o0oO +oOO0o0oo +0oOO0o +oOO0oO00 +oOO0oO0 +oOO0oO0O +oOO0oO0o +oOO0oO +oOO0oOO0 +oOO0oOO +oOO0oOOO +oOO0oOOo +0oOO0oOo0 +oOO0oOo +oOO0oOoO +oOO0oOoo +oOO0oo00 +oOO0oo0 +oOO0oo0O +oOO0oo0o +oOO0oo +oOO0ooO0 +0oOO0ooO +oOO0ooOO +oOO0ooOo +oOO0ooo0 +oOO0ooo +oOO0oooO +oOO0oooo +oOO +oOOO000 +oOOO000o +0oOOO0O +oOOOoO +oOOO00 +oOOO00O +oOOO00Oo +oOOO00o0 +oOOO00o +oOOO00oO +oOOO00oo +oOOO0 +0oOOO0oOO +oOOO0O0 +oOOO0O0o +oOOO0OO0 +oOOO0OO +oOOO0OOO +oOOO0OOo +oOOO0Oo +oOOO0OoO +oOOO0Ooo +0oOOO0o00 +oOOO0o0 +oOOO0o0O +oOOO0o0o +oOOOOO +oOOO0o +oOOO0oO0 +oOOO0oO +oOOO0ooo +oOOO0ooO +0oOOO0oOo +oOOO0oo0 +oOOO0oo +oOOO +oOOOO0OO +oOOOO000 +oOOOO00 +oOOOoo00 +oOOOO00O +oOOOO00o +0oOOOO0 +oOOOO0O0 +oOOOO0O +oOOOO0Oo +oOOOO0o0 +oOOOO0o +oOOOO0oO +oOOOO0oo +oOo0o +oOOOO +00oOOOOO00 +0oOOOOO0 +0oOOOOO0O +0oOOOOO0o +0oOOOOOO0 +0oOOOOOO +0oOOOOOOO +0oOOOOOOo +0oOOOOOo0 +0oOOOOOo +0oOOOOOoO +oOOOOOoo +oOOOOo00 +oOOOOo0 +oOOOOo0O +oOOOOo0o +oOOOOo +oOOOOoO0 +oOOOOoO +oOOOOoOO +0oOOOOoOo +oOOOOoo0 +oOOOOoo +oOOOOooO +oOOOOooo +oOOOo000 +oOOOo00 +oOOOo00O +oOOOo00o +oOOOo0 +0oOOOo0O0 +oOOOo0O +oOOOo0OO +oOOOo0Oo +oOOOo0o0 +oOOOo0o +oOOOo0oO +oOOOo0oo +oOOOo +oOOOoO00 +0oOOOoO0 +oOOOoO0O +oOOOoO0o +oOOOoOO0 +oOOOoOO +oOOOoOOO +oOOOoOOo +oOOOoOo0 +oOOOoOo +oOOOoOoO +0oOOOoOoo +oOOOoo0 +oOOOoo0O +oOOOoo0o +oOOOoo +oOOOooO0 +oOOOooO +oOOOooOO +oOOOooOo +oOOOooo0 +0oOOOooo +oOOOoooO +oOOOoooo +oOOo0000 +oOOo000 +oOOo000O +oOOo000o +oOOo00 +oOOo00O0 +oOOo00O +0oOOo00OO +oOOo00Oo +oOOo00o0 +oOOo00o +oOOo00oO +oOOo00oo +oOOo0 +oOOo0O00 +oOOo0O0 +oOOo0O0O +0oOOo0O0o +oOOo0O +oOOo0OO0 +oOOo0OO +oOOo0OOO +oOOo0OOo +oOOo0Oo0 +oOOo0Oo +oOOo0OoO +oOOo0Ooo +0oOOo0o00 +oOOo0o0 +oOOo0o0O +oOOo0o0o +oOOo0o +oOOo0oO0 +oOOo0oO +oOOo0oOO +oOOo0oOo +oOOo0oo0 +00oOOo0oo +0oOOo0ooO +0oOOo0ooo +0oOOo +0oOOoO000 +0oOOoO00 +0oOOoO00O +0oOOoO00o +0oOOoO0 +0oooO0oOO +0oOOoO0O0 +oOOoO0O +oOOoO0OO +oOOoO0Oo +oOOoO0o +oOOoO0oO +oOOoO0oo +oOOoO +oOOoOO0o +oOOoOO00 +0oOOoOO0 +oOOoOO0O +oOOoOOO +oOOoOOOO +oOOoOOOo +oOOoOOo0 +oOOoOOo +oOOoOOoO +oOOoOOoo +oOOoOo00 +0oOOoOo0 +oOOoOo0O +oOOoOo0o +oOOoOo +oOOoOoO0 +oOOoOoO +oOOoOoOo +oOOoOoo0 +oOOoOoo +oOOoOooO +0oOOoOooo +oOOoo000 +oOOoo00 +oOOoo00O +oOOoo00o +oOOoo0 +oOOoo0O0 +oOOoo0O +oOOoo0OO +oOOoo0Oo +0oOOoo0o0 +oOOoo0o +oOOoo0oO +oOOoo0oo +oOOoo +oOOooO00 +oOOooO0 +oOOooO0O +oOOooO0o +oOOooO +0oOOooOO0 +oOOooOO +oOOooOOO +oOOooOOo +oOOooOo0 +oOOooOo +oOOooOoO +oOOooOoo +oOOooo00 +oOOooo0 +0oOOooo0O +oOOooo0o +oOOooo +oOOoooO0 +oOOoooO +oOOoooOO +oOOoooOo +oOOoooo0 +oOOoooo +oOOooooO +0oOOooooo +oOo0000 +oOo000 +oOo000O +oOo000o +oOo00O0 +oOo00O +oOo00OO +oOo0o00 +oOo00Oo +0oOo00o0 +oOo00o +oOo00oO +oOo00oo +oOo0 +oOo0O000 +oOo0O00 +oOo0O00O +oOo0oO0o +oOo0O00o +000oOo0oo +00oOo0O0 +00oOo0O0O0 +00oOo0O0O +00oOo0O0OO +00oOo0O0Oo +00oOo0O0o0 +00oOo0O0o +00oOo0O0oO +00oOo0O0oo +00oOo0O +0oOo0OO00 +0oOoo00o +0oOo0OO0 +0oOo0OO0O +0oOo0OO0o +0oOo0OO +0oOo0OOO0 +0oOo0OOO +0oOo0OOOO +00oOo0OOOo +0oOo0OOo0 +0oOo0OOo +0oOo0OOoO +0oOo0OOoo +0oOo0Oo00 +0oOo0Oo0 +0oOo0Oo0O +0oOo0Oo0o +0oOo0Oo +00oOo0OoO0 +0oOo0OoO +0oOo0OoOO +0oOo0OoOo +0oOo0Ooo0 +0oOo0Ooo +0oOo0OooO +0oOo0Oooo +0oOo0o000 +0oOo0o00O +00oOo0o00o +0oOo0o0 +0oOo0o0O +0oOo0o0OO +0oOo0o0Oo +0oOo0o0o0 +0oOo0o0o +0oOo0oO00 +0oOo0oO0 +0oOo0oO0O +00oOo0oO +0oOo0oOO0 +0oOo0oOO +0oOo0oOOO +0oOo0oOOo +0oOo0oOo0 +0oOo0oOo +0oOo0oOoO +0oOo0oOoo +0oOo0oo00 +00oOo0oo0 +0oOo0oo0O +0oOo0ooO0 +0oOo0ooO +0oOo0ooOO +0oOo0ooOo +0oOo0ooo0 +0oOo0ooo +0oOo +0oOooOOoO +00oOoO0000 +0oOoO000 +0oOoO000O +0oOoO000o +0oOoO00 +0oOoO00O0 +0oOoO00O +0oOoO00OO +0oOoO00Oo +0oOoO00o0 +00oOoO00o +0oOoO00oO +0oOoO00oo +0oOoO0 +0oOooOo0O +0oOoO0O00 +0oOoO0O0 +0oOoO0O0O +0oOoO0O0o +0oOoO0o +00oOoO0O +0oOoO0OO0 +0oOoO0OO +0oOoO0OOO +0oOoO0OOo +0oOoO0Oo0 +0oOoO0Oo +0oOoO0OoO +0oOoO0Ooo +0oOooOo00 +00oOoO0o00 +0oOoO0o0 +0oOoO0o0O +0oOoOoOOO +0oOoO0o0o +0oOoO0oO0 +0oOoO0oO +0oOoO0oOO +0oOoO0oOo +0oOooOo0o +0oOoO0oo0 +oOoO0oo +oOoO0ooO +oOoO0ooo +oOoO +oOoOO000 +oOoOO00 +oOoOO00O +oOoOO00o +oOoOO0 +0oOoOO0O0 +oOoOO0O +oOoOOo0O +oOoOO0OO +oOoOO0Oo +oOoOO0o0 +oOoOO0o +oOoOO0oO +oOooOOOO +oOoOO0oo +0oOoOO +oOoOOO00 +oOoOOO0 +oOoOOO0O +oOoOOO0o +oOoOOO +oOoOOOO0 +oOoOOOO +oOoOOOOO +oOoOOOOo +0oOoOOOo0 +oOoOOOo +oOoOOOoO +oOooOooO +oOoOOOoo +oOoOOo00 +oOoOOo0 +oOoOOo0o +oOoOOo +oOoOOoO0 +0oOoOOoO +oOoOOoOO +oOoOOoOo +oOoOOoo0 +oOoOOoo +oOoOOooO +oOoOOooo +oOoOo000 +oOoOo00 +oOoOo00O +0oOoOo00o +oOoOo0 +oOoOoo0O +oOoOo0O0 +oOoOo0O +ooOOO0oo +oOooo0Oo +oOooo0oo +oOoOo0OO +ooOOO0o0 +0oOoOo0Oo +oOoOo0o0 +oOoOo0o +oOoOo0oO +oOoOo0oo +oOoOo +ooOOOooo +oOoOoO00 +oOoOoO0 +oOoOoO0O +0ooOOOooO +oOooooOO +oOoOoO0o +oOoOoO +oOoOoOO0 +oOoOoOO +oOoOoOOo +oOoOoOo0 +oOoOoOo +oOooOOoo +0oOoOoOoO +oOoOoOoo +ooOOO0oO +oOooo0oO +oOoOoo00 +oOoOoo0 +ooOOO0O0 +oOooo0O0 +oOoOoo0o +oOoOoo +00ooOOOo0o +0oOoooooo +0oOoOooO0 +0oOoOooO +0oOoOooOO +0ooOOOo0O +0oOoooooO +0oOoOooOo +0oOoOooo0 +0oOoOooo +0ooOOOo00 +oOooooo0 +oOoOoooO +oOoOoooo +oOoo0000 +oOoo000 +oOoo000O +oOoo000o +oOoo00 +oOoo00O0 +0oOoo00O +oOoo00OO +oOoo00Oo +oOoo00o0 +oOoo00oO +oOoo00oo +oOoo0Oo0 +oOoo0O00 +oOoo0O0 +oOoo0O0O +0oOoo0O0o +oOoo0O +oOoo0OO0 +oOoo0oO +oOooo00 +oOoo0OO +oOoo0OOO +oOoo0OOo +oOoo0Oo +oOoo0OoO +0oOoo0Ooo +oOoo0o00 +oOoo0o0 +oOoo0o0O +oOoo0o0o +oOoo0o +oOoo0oO0 +oOoo0oOO +oOoo0oOo +oOoo0oo0 +0oOoo0oo +oOoo0ooO +oOoo0ooo +oOoo +oOooO000 +oOooO00 +oOooO00O +oOooO00o +oOooO0 +oOooO0O0 +0oOooO0O +oOooO0OO +oOooO0Oo +oOooO0o0 +oOooO0o +oOooO0oO +oOooO0oo +oOooO +oOooOO00 +oOooOO0 +0oOooOOo0 +oOooOO0O +oOooOO0o +oOooOO +oOooOOO0 +oOooOOO +oOooOOOo +oOooOOo +oOooOo0 +oOooOo +0oOooOoO0 +oOooOoO +oOooOoOO +oOooOoOo +oOooOoo0 +oOooOoo +oOooOooo +oOooo000 +oOooo00O +oOooo00o +0oOoooO +oOooo0 +oOooo0O +oOooo0OO +oOooo0o0 +oOoooO00 +oOoooO0 +oOoooO0O +oOoooO0o +oOoooOO0 +00oOoooOO +0oOoooOOO +0oOoooOOo +0oOoooOo0 +0oOoooOo +0oOoooOoO +0oOoooOoo +0oOoooo00 +0oOoooo0 +0oOoooo0O +0oOoooo0o +oOoooo +oOooooO0 +oOooooO +oOooooOo +oOooooo +oo000000 +oo00000 +oo00000O +oo00000o +0oo0000 +oo0000O0 +oo0000O +oo0000OO +oo0000Oo +oo0000o0 +oo0000o +oo0000oO +oo0000oo +oo000 +0oo000O00 +oo000O0 +oo000O0O +oo000O0o +oo000O +oo000OO0 +oo0OOOO +oo000OO +oo000OOO +oo000OOo +0oo000Oo0 +oo000Oo +oo000OoO +oo000Ooo +oo000o00 +oo000o0 +oo000o0O +oo000o0o +oo000oO0 +oo000oO +0oo000oOO +oo000oOo +oo000oo0 +oo000oo +oo000ooO +oo00 +oo00O00o +oo00O000 +oo00O00 +oo00O00O +0oo00O0 +oo00O0O0 +oo00O0O +oo00Oo0O +oo00O0OO +oo00O0Oo +oo00O0o0 +oo00O0o +oo00O0oO +oo00O0oo +0oo00O +oo00OO00 +oo00OO0 +oo00OO0O +oo00OO0o +oo00OO +oo00OOO0 +oo00OOO +oo00OOOO +oo00OOOo +0oo00OOo0 +oo00OOo +oo00OOoO +oo00OOoo +oo00Oo00 +oo00Oo0 +oo00Oo0o +oo00Oo +oo00OoO0 +oo00OoO +0oo00OoOO +oo00OoOo +oo00Ooo0 +oo00Ooo +oo00OooO +oo00Oooo +oo00o000 +oo00o00 +oo00o0o0 +oo00o00O +00oo00o00o +0oo00o0 +0oo00o0oo +0oo00ooOO +0oo00o0O0 +0oo00o0O +0oo00o0OO +0oo00o0Oo +0oo00o0o +0oo00o0oO +0oo00oO00 +oo00oO0 +oo00oO0O +oo00oO0o +oo00oOoO +oo00oOO0 +oo00oOo +oo00oOO +oo00oOOO +oo00oOOo +0oo00oOo0 +oo00oOoo +oo00oo00 +oo00oo0 +oo00oo0O +oo00oo0o +oo00oo +oo00ooO0 +oo00ooO +oo00ooOo +0oo00ooo0 +oo00ooo +oo00oooO +oo00oooo +oo0 +oo0O0000 +oo0O000 +oo0O000O +oo0O000o +oo0O00 +0oo0oOOOO +oo0O00O0 +oo0O00O +oo0O00OO +oo0O00Oo +oo0O00o0 +oo0O00o +oo0O00oO +oo0O00oo +oo0O0 +0oo0O0O00 +oo0O0O0 +oo0O0O0O +oo0O0O0o +oo0O0O +oo0O0OO0 +oo0O0OO +oo0O0OOO +oo0O0OOo +oo0O0Oo0 +0oo0O0Oo +oo0O0OoO +oo0O0Ooo +oo0O0o00 +oo0O0o0 +oo0O0o0O +oo0O0o0o +oo0O0o +oo0O0oO0 +ooo0OoO +0oo0O0oO +oo0oOOoO +oo0O0oOO +oo0O0oOo +oo0O0oo0 +oo0O0oo +oo0O0ooO +oo0O0ooo +oo0OoOO0 +oo0OO00o +0oo0OO00O +oo0OO000 +oo0OO00 +oo0Oo0 +oo0Ooo +oo0OoO +oo0OO0 +oo0OOoOO +oo0OO0Oo +oo0OOo0O +0oo0OOooO +oo0OO0O0 +oo0OO0O +oo0OO0OO +oo0OO0o0 +oo0OO0o +oo0OO0oO +oo0OO0oo +oo0OO +oo0OOO00 +00oo0oOoo +0oo0OOO0 +0oo0OOO0O +0ooo000O0 +0oo0OOO0o +0oo0OOO +0ooo000o0 +0oo0OOOO0 +0oo0OOOOO +0oo0OOOOo +0oo0OOOo0 +oo0OOOo +oo0OOOoO +ooo0000O +ooo00000 +oo0OOOoo +oo0OOo00 +oo0OOo0 +oo0OOo0o +oo0OOo +0oo0OOoO0 +oo0OOoO +oo0OOoOo +oo0OOoo0 +oo0OOooo +oo0Oo000 +oo0Oo00 +oo0Oo00O +oo0Oo00o +oo0Oo0O0 +0oo0Oo0O +oo0Oo0OO +oo0Oo0Oo +oo0Oo0o0 +oo0Oo0o +oo0Oo0oO +oo0Oo0oo +oo0Oo +oo0OoO00 +oo0OoO0 +0oo0OoO0O +oo0OoO0o +oo0OoOO +oo0OoOOO +oo0OoOOo +oo0OoOo0 +oo0OoOo +oo0OoOoO +oo0OoOoo +oo0Ooo00 +0oo0Ooo0 +oo0Ooo0O +oo0Ooo0o +oo0OooO +oo0OooOO +oo0OooOo +oo0Oooo0 +oo0Oooo +oo0OoooO +0oo0Ooooo +oo0o0000 +oo0o000 +oo0o000O +oo0o000o +oo0o00 +oo0o00O0 +oo0o00o +oo0o00O +oo0o00Oo +0oo0o00oO +oo0o00OO +oo0o00o0 +oo0o00oo +oo0o0 +oo0o0O00 +oo0o0O0o +oo0o0o +oo0o0O +oo0o0OO0 +0oo0o0OO +oo0o0OOO +oo0o0OOo +oo0o0Oo0 +oo0o0OoO +oo0o0Ooo +oo0o0o00 +oo0o0o0 +oo0o0o0O +oo0o0o0o +0oo0o0oO0 +oo0o0oO +oo0o0oOO +oo0o0oOo +oo0o0oo0 +oo0o0oo +oo0o0ooO +oo0o0ooo +oo0o +oo0oO000 +00oo0oO00 +0oo0oO0oO +0oo0oO00O +0oo0oO00o +0oo0oO0O0 +0oo0oO0O +0oo0oO0OO +0oo0oO0Oo +0oo0oO0o0 +0oo0oO0o +0oo0oO0oo +oo0oO +oo0oOO00 +oo0oOO0O +oo0oOO0o +oo0oOO +oo0oOOO0 +oo0oOOO +oo0oOOOo +oo0oOOo0 +0oo0oOOoo +oo0oOo00 +oo0oOo0 +oo0oOo0O +oo0oOo0o +oo0oOo +oo0oOoO0 +oo0oOoOO +oo0oOoOo +oo0oOoo0 +0oo0oOooO +oo0oOooo +oo0oo000 +ooo0oOO +oooOooO +oo0oo00 +oo0oo00O +oo0oo00o +oo0oo0 +oo0oo0O0 +0oo0oo0O +oo0oo0OO +oo0oo0Oo +oo0oo0o0 +oo0oo0o +oo0oo0oO +oo0oo0oo +oo0oo +oo0ooO00 +oo0ooO0 +0oo0ooO0O +oo0ooO0o +oo0ooOO0 +oo0ooOO +ooo0O0oo +ooo0oooO +oo0ooOOO +oo0ooOOo +oo0ooOo0 +oo0ooOo +0oo0ooOoO +oo0ooOoo +oo0ooo00 +oo0ooo0 +oo0ooo0o +oo0ooo0O +oo0ooo +oo0oooOO +oo0oooO0 +oo0oooO +0oo0oooOo +oo0oooo0 +oo0oooo +oo0ooooO +oo0ooooo +oo +ooO00000 +oooooOo +ooO0000 +ooO0000O +0ooOooOOO +ooO0000o +ooO0oo +ooO000 +ooO000O0 +ooO000O +ooO000OO +ooO000Oo +ooO000o0 +ooO000o +0ooO000oO +ooO000oo +ooO00 +ooO0OOoo +ooOo000o +ooOo00O0 +ooO00O00 +ooO00O0O +ooO0OOoO +ooO00O0o +00ooO00O +0ooOo00o0 +0ooO00OO0 +0ooO00OO +0ooO0OOOO +0ooO00OOO +0ooO00OOo +0ooO00Oo0 +0ooO00Oo +0ooO00OoO +0ooOo00OO +ooO00Ooo +ooO00o00 +ooO00o0 +ooO00o0O +ooO00o0o +ooO00o +ooO00oO0 +ooO00oO +ooO00oOO +0ooO00oOo +ooO00oo0 +ooO00oo +ooO00ooO +ooO00ooo +ooO0 +ooO0O000 +oooo000 +ooO0O00 +ooO0O00O +0ooO0O00o +ooO0O0 +ooO0O0O0 +ooO0O0O +ooO0O0OO +ooO0O0Oo +ooO0O0o0 +ooO0OOO +ooO0O0o +ooO0O0oO +0ooO0O0oo +ooO0O +ooOo000O +ooO0OO00 +ooO0OO0 +ooO0OO0O +ooO0OO0o +ooO0OO +ooO0OOO0 +ooO0OOOo +0ooO0OOo0 +ooO0OOo +ooO0Oo00 +ooo0oOo +ooO0Oo0 +ooO0Oo0O +ooO0Oo0o +ooO0Oo +ooO0OoO0 +ooO0OoO +0ooO0OoOO +ooO0OoOo +ooO0Ooo0 +ooO0OooO +ooO0Oooo +ooO0o000 +ooO0o00 +ooO0o00O +ooO0o00o +ooO0o0 +0ooO0o0O0 +ooO0o0O +ooO0o0OO +ooO0o0Oo +ooO0o0o0 +ooO0o0o +ooO0o0oO +ooO0o0oo +ooO0o +ooO0oO00 +0ooO0oO0 +ooO0oO0O +ooOo00Oo +ooO0oO0o +ooO0oO +ooO0oOO0 +ooO0oOO +ooO0oOOO +ooO0oOOo +ooO0oOo0 +0ooo0OOo +ooO0oOo +ooO0oOoO +ooO0oOoo +ooO0oo00 +ooO0oo0 +ooO0oo0O +ooO0oo0o +ooO0ooO0 +ooO0ooO +00ooO0ooOO +0ooO0ooOo +0ooO0ooo0 +0ooO0ooo +0ooO0oooO +0ooO0oooo +0ooo +0ooO +0ooOO0000 +0ooOO000 +0ooOO000O +ooOO000o +ooOO00 +ooOO00O0 +ooOO00O +ooOO00OO +ooOO00Oo +ooOO00o0 +ooOO00o +ooOO00oO +0ooOO00oo +ooOO0 +ooOO0O00 +ooOO0O0 +ooOO0O0O +ooOO0O0o +ooOO0OO0 +ooOO0OO +ooOO0OOO +ooOOo0OO +0ooOO0OOo +ooOO0Oo0 +ooOO0Oo +ooOO0OoO +ooOO0Ooo +ooOO0o00 +ooOO0o0 +ooOO0o0O +ooOO0o0o +ooOO0o +0ooOO0oO0 +ooOO0oO +ooOO0oOO +ooOO0oOo +ooOO0oo0 +ooOO0oo +ooOO0ooO +ooOO0ooo +ooOOO00 +ooOOoO +0ooOOO0 +ooOOO0O +ooOOO0o +ooOOO +ooOOOO00 +ooOOOO0 +ooOOOO0O +ooOOOO0o +ooOOOO +ooOOOOO0 +0ooOOOOO +ooOOOOOO +ooOOOOo +ooOOOo0 +ooOOOo +ooOOOoO +ooOOOoo +ooOOo000 +ooOOo00O +ooOOo00o +0ooOOo0O0 +ooOOo0O +ooOOo0Oo +ooOOo0o0 +ooOOo0o +ooOOo0oO +ooOOo0oo +ooOOo +ooOOoO0 +ooOOoO0O +0ooOOoO0o +ooOOoOo +ooOOoo00 +ooOOoo0 +ooOOoo0O +ooOOoo0o +ooOOoo +ooOOooO0 +ooOOooO +ooOOooOO +0ooOOooo0 +ooOOooo +ooOOoooo +ooOo0000 +ooOo000 +ooOo00 +ooOo00oO +ooOo00oo +ooOo0 +ooOo0O00 +00ooOo0o0 +0ooOo0O0 +0ooOo0oOo +0ooOo0O0O +0ooOo0O0o +0ooOo0O +0ooOo0OO0 +0ooOo0OO +0ooOoOo0o +0ooOooOOo +0ooOo0OOO +ooOo0OOo +ooOo0Oo0 +ooOo0Oo +ooOo0OoO +ooOo0Ooo +ooOo0o00 +ooOo0o0O +ooOo0o0o +ooOo0o +0ooOo0oO0 +ooOo0oO +ooOo0oOO +ooOo0oo0 +ooOo0oo +ooOo0ooO +ooOo0ooo +ooOoO000 +ooOoO00 +ooOoO00O +0ooOoO00o +ooOoO0 +ooOoO0O0 +ooOoO0O +ooOoO0OO +ooOoO0Oo +ooOoO0o0 +ooOoO0o +ooOoO0oO +ooOoO0oo +0ooOoO +ooOoOoOO +ooOoOO00 +ooOoOO0 +ooOoOOOo +ooOoOO0O +ooOoOO0o +ooOoOO +ooOoOOO0 +ooOoOOO +0ooOoOOOO +ooOoOOo0 +ooOoOOo +ooOoOOoO +ooOoOOoo +ooOoOo00 +ooOoOo0 +ooOoOo0O +ooOoOo +ooOoOoO0 +0ooOoOoO +ooOoOoOo +ooOoOoo0 +ooOoOoo +ooOoOooO +ooOoOooo +ooOoo000 +ooOoo00 +ooOooo0o +ooOoo00O +0ooOoo00o +ooOoo0 +ooOoo0O0 +ooOoo0O +ooOoo0OO +ooOoo0Oo +ooOoo0o0 +ooOoo0o +ooOoo0oo +ooOoo0oO +0ooooO +ooOoo +ooOooO00 +ooOooO0 +ooOooO0O +ooOooO0o +ooOooo +ooOooO +ooOooOO0 +ooOooOO +0ooOooOo0 +ooOooOo +ooOooOoO +ooOooOoo +ooOooo00 +ooOooo0 +ooOooo0O +ooOoooO0 +ooOoooO +ooOoooOO +000ooOoooOo +00ooOoooo0 +00ooOoooo +00ooOooooO +00ooOooooo +00ooo0000 +00ooo000oo +00ooo0000o +00ooo000 +00ooo000O +00ooo000OO +0ooo000Oo +0ooo000o +0ooo000oO +0ooo00 +0ooo00O00 +0ooo00oO0 +0ooo00O0O +0ooo00O0o +0ooo00O +00ooo00Oo0 +0ooo00OO0 +0ooo00OO +0ooo00OOO +0ooo00OOo +0ooo00Oo +0ooo00OoO +0ooo00Ooo +0ooo00o00 +0ooo00o0 +00ooo00o0O +0ooo00o0o +0ooo00o +0ooo00oO +0ooo00oOO +0ooo00oOo +0ooo00oo0 +0ooo00oo +0ooo00ooO +0ooo00ooo +00ooo0 +0ooo0O000 +0ooo0O00 +0ooo0O00O +0ooo0O00o +0ooo0oo +0ooo0o0 +0ooo0oO +0ooo0O0 +0ooo0O0O0 +00ooo0O0O +0ooo0O0OO +0ooo0O0Oo +0ooo0O0o0 +0ooo0O0o +0ooo0O0oO +0ooo0O +0ooo0OO00 +0ooo0OO0 +0ooo0OO0O +00ooo0OO0o +0ooo0Oo +0ooo0OO +0ooo0OOO0 +0ooo0OOO +0oooo00oo +0ooo0OOoO +0ooo0OOOO +0ooo0OOOo +0ooo0OOo0 +00ooo0OOoo +0ooo0Oo00 +0ooo0Oo0O +0ooo0Oo0o +0ooo0OoO0 +0ooo0OoOO +0ooo0OoOo +0ooo0Ooo0 +0ooo0OooO +0ooo0Oooo +00ooo0o000 +0ooo0o00 +0ooo0o00O +0ooo0o00o +0ooo0o0OO +0ooo0o0O0 +0ooo0o0O +0ooo0o0Oo +0ooo0o0o0 +0ooo0o0o +00ooo0o0oO +0ooo0o0oo +0ooo0oO00 +0ooo0oO0 +0ooo0oO0O +0ooo0oO0o +0ooo0oOO0 +0ooo0oOOO +0ooo0oOOo +0ooo0oOo0 +00ooo0oOoO +0ooo0oOoo +0ooo0oo00 +0ooo0oo0 +0ooo0oo0O +0ooo0oo0o +0ooo0ooO0 +0ooo0ooO +0ooo0ooOO +0ooo0ooOo +0ooo0ooo0 +ooo0oooo +oooO0oo0 +oooO0000 +oooO000 +oooO00o0 +oooO000O +oooO0ooo +oooO000o +ooooo0 +0oooooo +ooooOo +oooO00 +oooO00O0 +oooO00O +oooO00Oo +oooO00OO +oooO00o +ooooOOOo +ooooOOOO +0ooooOo00 +oooO0oO0 +oooO00oO +oooO00oo +oooO0 +oooO0O00 +oooO0O0 +oooO0O0O +oooO0O0o +oooO0O +0oooOOo0O +oooO0OO0 +oooO0OO +oooO0OOO +oooO0OOo +oooO0Oo0 +oooO0Oo +oooO0OoO +oooO0Ooo +oooO0o00 +0oooO0o0 +oooO0o0O +oooO0o0o +oooooO +oooO0o +oooO0oO +oooO0oo +oooO0ooO +oooO +oooOooOO +0oooOO000 +oooOO00 +oooOO0o0 +oooOO00O +oooOO00o +oooOO0O0 +oooOO0O +oooOO0OO +oooOO0Oo +oooOO0o +0oooOO0oO +oooOO0oo +oooOO +oooOOO00 +oooOOO0 +oooOOO0O +oooOOO0o +oooOOO +oooOOOO0 +oooOOOO +0oooOOOOO +oooOOOOo +oooOOOo0 +oooOOOo +oooOOOoO +oooOOOoo +oooOOo00 +oooOOo0 +oooOOo0o +oooOOo +0oooOOoO0 +oooOOoO +oooOOoOO +oooOOoOo +oooOOoo0 +oooOOoo +oooOOooO +oooOOooo +oooOo000 +oooOo00 +00oooOo00O +0oooOo00o +0oooOo0 +0oooOo0oo +0oooOo0O0 +0oooOo0O +0oooOo0OO +0oooOo0Oo +0oooOo0o0 +0oooOo0o +0oooOo0oO +oooOo +oooOoO00 +oooOoO0 +oooOoO0O +oooOoO0o +oooOoOOO +oooOoOO0 +oooOoOO +oooOoOOo +0oooOoOo0 +oooOoOo +oooOoOoO +oooOoOoo +oooOoo00 +oooOoo0 +oooOoo0O +oooOoo0o +oooOooO0 +oooOooOo +0oooOooo0 +oooOooo +oooOoooO +oooOoooo +oooo0000 +oooo000O +oooo000o +oooo00 +oooo00o0 +oooo00O0 +0oooo00O +oooo00OO +oooo00Oo +oooo00oO +oooo0 +oooo0O00 +oooo0O0 +oooo0O0O +oooo0O0o +oooo0O +0oooo0OO0 +oooo0OO +oooo0OOO +oooo0OOo +oooo0Oo0 +oooo0Oo +oooo0OoO +oooo0Ooo +oooo0o00 +oooo0o0 +0oooo0o0O +oooo0o0o +oooo0o +oooo0oO0 +oooo0oO +oooo0oOO +oooo0oOo +oooo0oo0 +oooo0oo +oooo0ooO +0oooo0ooo +oooo +ooooO00 +ooooOOoO +ooooO00O +ooooO00o +ooooO0 +ooooO0O +ooooO0OO +ooooO0Oo +0ooooO0o0 +ooooO0o +ooooO0oO +ooooOO0 +ooooOO0o +ooooOO +ooooOoo0 +ooooOOO0 +ooooOOO +ooooOOo +0ooooOo0 +ooooOo0O +ooooOo0o +ooooOoO0 +ooooOoO +ooooOoo +ooooOooO +ooooOooo +ooooo000 +ooooo00 +00ooooo00O +0ooooo00o +0ooooo0O0 +0ooooo0O +0ooooo0OO +0ooooo0Oo +0ooooo0o0 +0ooooo0o +0ooooo0oO +0ooooo0oo +0ooooo +oooooO00 +oooooO0 +oooooOo0 +oooooO0O +oooooO0o +oooooOO0 +oooooOO +oooooOOO +oooooOOo +0oooooOoO +oooooOoo +oooooo00 +oooooo0 +oooooo0O +oooooo0o +ooooooO0 +ooooooOO +ooooooOo +ooooooo0 +0oooooooO +oooooooo +O +O0 +O00 +O000 +O0000 +O00000 +O000000 +O0000000 +O000000O +O00000O +O00000O0 +O00000OO +O0000O +O0000O0 +O0000O00 +O0000O0O +O0000OO +O0000OO0 +O0000OOO +O000O +O000O0 +O000O00 +O000O000 +O000O00O +O000O0O +O000O0O0 +O000o0oO +O000Oo +O000OO0 +O000oo00 +O000OO0O +O000OOO +O000OOO0 +O000OOOO +O00O +O00O0 +O00O00 +O00O000 +O00O0000 +O00O000O +O00O00O +O00O00O0 +O00O00OO +O00O0O +O00O0O0 +O00O0O00 +O00O0O0O +O00O0oO +O00O0OO0 +O00O0OOO +O00OO +O00OO0 +O00OO00 +O00Oo000 +O00Oo00O +O00Oo0O +O00Oo0O0 +O00oo0oO +O00OOO +O00OOO0 +O00OoO00 +O00ooo0O +O00OOOO +O00oOoO0 +O00ooooO +O0O +O0O0 +O0O00 +O0O000 +O0O0000 +o0o00000 +o0o0000O +O0O000O +o0O000O0 +o0O000OO +O0O00O +O0O00O0 +o0O00O00 +o0O00O0O +O0O00oo +o0O00OO0 +o0O00OOo +O0o0o +O0O0O0 +O0O0O00 +o0O0O000 +o0O0O00o +O0O0O0O +o0O0O0O0 +o0O0O0OO +O0O0Oo +O0o0oo0 +o0O0OO00 +o0O0OO0o +O0o0ooo +o0O0OOo0 +o0O0OOOO +O0OO +O0OO0 +O0OO00 +O0OO000 +o0OO0000 +o0OO000O +o0Oo00O +o0OO00O0 +o0OO00oO +O0OO0o +O0OO0O0 +o0OO0O00 +o0oO0O0O +O0OO0OO +o0oO0Oo0 +o0oO0oOo +O0OOO +O0OOo0 +o0OoO00 +o0OOO000 +o0OoO00o +O0OoO0o +o0ooo0O0 +o0ooo0Oo +O0oOOO +O0OOOO0 +o0ooOO00 +o0OOOO0O +O0oOOOO +o0ooOOo0 +o0ooooOO +OO +OO0 +OO00 +OO000 +Oo0000 +OO00000 +oO000000 +oO00000O +OO0000O +oO0000O0 +oO0000OO +OO000O +OO000O0 +oO000O00 +oO000o0O +oO000OO +oO000OO0 +oo000ooo +OO00o +OO00o0 +OO00O00 +oO00O000 +oO00O00O +OO00O0O +oO00O0O0 +oO00O0OO +Oo00oO +OO00OO0 +oO00OO00 +oO00OO0o +Oo00oOo +oO00OOO0 +oO00OOOO +OO0O +OO0O0 +OO0O00 +OO0O000 +oO0O0000 +oO0O000O +OO0O00O +oO0O00O0 +oO0O00OO +OO0o0O +OO0O0O0 +oO0O0o00 +oo0o0O0O +Oo0o0OO +oO0O0OO0 +oO0O0Ooo +OO0Oo +OO0OO0 +OO0OO00 +oO0Oo000 +oO0Oo00o +OO0OO0O +oO0OO0O0 +oO0Oo0oO +Oo0OOO +OO0OOO0 +oO0OOo00 +oO0OoO0o +Oo0OoOO +oO0Oooo0 +oO0OoOOo +OOo +OOO0 +OoO00 +OOO000 +OOO0000 +oOo00000 +oOo0000o +OOO000O +oOo000O0 +oOo000oO +OOO00O +ooo00O0 +oOo00O00 +oOo00O0o +OOO00OO +oOO00oo0 +oOo00Ooo +OOo0O +OOO0O0 +OOO0O00 +oOO0o000 +oOO0o00O +Ooo0o0O +oOo0o0O0 +oOo0o0oo +OOO0OO +Ooo0Oo0 +oOO0OO00 +oOo0oo0o +ooo0ooo +oOO0OOO0 +oOo0oooo +OOOO +OooO0 +OOOO00 +OOOO000 +oOOO0000 +oOOO000O +ooOo00o +oOOO00O0 +oOOO00OO +OOOO0o +OOOO0O0 +oOOO0O00 +oOOO0O0O +Oooo0Oo +oOOO0Oo0 +oooO0oOo +Ooooo +OOoOO0 +OoOOO00 +ooOOO000 +ooOOO00o +OOOOO0O +oOOoO0o0 +ooOOO0OO +oooOoo +OOOOOO0 +ooOOoO00 +ooooOO0O +ooOOoOO +ooOOOOo0 +ooOOOoOO diff --git a/athena-all/logo.svg b/athena-all/logo.svg new file mode 100644 index 000000000..f54b7dcce --- /dev/null +++ b/athena-all/logo.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/DynamicAction.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/DynamicAction.java similarity index 82% rename from athena-all/src/main/java/run/mone/m78/ip/action/DynamicAction.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/DynamicAction.java index 283b13576..8622d0415 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/action/DynamicAction.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/DynamicAction.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.action; +package com.xiaomi.youpin.tesla.ip.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -6,10 +6,10 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.PromptService; -import run.mone.m78.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.PromptService; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/GenerateAction.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/GenerateAction.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/action/GenerateAction.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/GenerateAction.java index 519255ab6..59aa76568 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/action/GenerateAction.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/GenerateAction.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.action; +package com.xiaomi.youpin.tesla.ip.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -53,7 +53,7 @@ private void build(String filePath, String fileName) { } try { - Files.write(Paths.get(filePath + File.separator + fileName), "".getBytes()); + Files.write(Paths.get(filePath + File.separator + fileName), "abc--->zzy".getBytes()); } catch (IOException e) { e.printStackTrace(); } diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/MenuActionGroup.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/MenuActionGroup.java new file mode 100644 index 000000000..f8ff8ea70 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/MenuActionGroup.java @@ -0,0 +1,47 @@ +package com.xiaomi.youpin.tesla.ip.action; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.Tag; +import com.xiaomi.youpin.tesla.ip.common.ConfigCenter; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author caobaoyu + * @author goodjava@qq.com + * @description: + * @date 2023-06-14 14:15 + */ +public class MenuActionGroup extends ActionGroup { + + public MenuActionGroup() { + super("Prompt", true); + } + + @Override + public AnAction @NotNull [] getChildren(AnActionEvent e) { + if (ResourceUtils.checkDisableCodeCompletionStatus() || LabelUtils.getLabelValue(e.getProject(), Const.DISABLE_ACTION_GROUP, "false").equals("true")) { + return new AnAction[]{}; + } +// Map menuTag = ConfigCenter.getMenuTag(); +// Map> tagPromptInfo = new LinkedHashMap<>(); +// tagPromptInfo.put("Collection", Prompt.getCollected()); +// menuTag.keySet().forEach(tag -> tagPromptInfo.put(tag, Prompt.getPromptInfoByTag(tag))); +// List actions = tagPromptInfo.entrySet().stream().map((entry) -> new MenuAction(entry.getKey(), entry.getValue())).toList(); +// return actions.toArray(new AnAction[0]); + //第一个版本之显示系统级别的了 + List list = Prompt.getPromptInfoByTag("system"); + list.addAll(Prompt.getCollected()); + return list.stream().map(it -> new DynamicAction(it.getDesc(), Prompt.getPromptType(it), it)).toArray(AnAction[]::new); + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/NaviAction.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/NaviAction.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/action/NaviAction.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/NaviAction.java index 654325c43..9b897fc48 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/action/NaviAction.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/NaviAction.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package run.mone.m78.ip.action; +package com.xiaomi.youpin.tesla.ip.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.NaviComponent; +import com.xiaomi.youpin.tesla.ip.component.ChatComponent; +import com.xiaomi.youpin.tesla.ip.component.NaviComponent; import org.jetbrains.annotations.NotNull; /** diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/PluginAction.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/PluginAction.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/action/PluginAction.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/PluginAction.java index d3487a43c..ad59675f1 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/action/PluginAction.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/PluginAction.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.action; +package com.xiaomi.youpin.tesla.ip.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.PluginComponent; +import com.xiaomi.youpin.tesla.ip.component.PluginComponent; import org.jetbrains.annotations.NotNull; /** diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/UltramanAction.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/UltramanAction.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/action/UltramanAction.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/UltramanAction.java index 483aab16b..10341faeb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/action/UltramanAction.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/action/UltramanAction.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.action; +package com.xiaomi.youpin.tesla.ip.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Action.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Action.java new file mode 100644 index 000000000..06c76dd02 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Action.java @@ -0,0 +1,50 @@ +package com.xiaomi.youpin.tesla.ip.bo; + +public enum Action { + + CHAT(1, "chat"), + GENERATE_CODE(2, "generate_code"), + CODE_SUGGESTION(3, "code_suggestion"), + GENERATE_COMMENT(4, "generate_comment"), + SMART_NAMING(5, "smart_naming"), + GIT_PUSH(6, "git_push"), + UNIT_TEST(7, "unit_test"), + BUG_FIX(8, "bug_fix"), + INSERT_CODE_FROM_CHAT(9, "insert_code_from_chat"), + INLAY(10, "inlay"); + + private final int code; + private final String name; + + Action(int code, String name) { + this.code = code; + this.name = name; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } + + public static Action fromCode(int code) { + for (Action action : Action.values()) { + if (action.getCode() == code) { + return action; + } + } + throw new IllegalArgumentException("Invalid code: " + code); + } + + public static Action fromName(String name) { + for (Action action : Action.values()) { + if (action.getName().equalsIgnoreCase(name)) { + return action; + } + } + throw new IllegalArgumentException("Invalid name: " + name); + } +} + diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AddMethodConfig.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AddMethodConfig.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AddMethodConfig.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AddMethodConfig.java index 61bdbc5d0..c89f7c06f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AddMethodConfig.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AddMethodConfig.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.psi.PsiType; import lombok.Builder; @@ -20,4 +20,5 @@ public class AddMethodConfig implements Serializable { private boolean isInterface; + } diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AiCodePromptRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodePromptRes.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AiCodePromptRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodePromptRes.java index c3e1de3d7..d76a24a11 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AiCodePromptRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodePromptRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AiCodeRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodeRes.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AiCodeRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodeRes.java index 7c64059c0..2978a8671 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AiCodeRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiCodeRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AiMessage.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessage.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AiMessage.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessage.java index 050435e5c..c971bc357 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AiMessage.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessage.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AiMessageType.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessageType.java similarity index 78% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AiMessageType.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessageType.java index 5ff0bcc3c..fccd87415 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AiMessageType.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AiMessageType.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AnnoInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoInfo.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AnnoInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoInfo.java index 9cf904924..d90b51641 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AnnoInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AnnoMember.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoMember.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AnnoMember.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoMember.java index e1a02d7a5..cf000eea3 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AnnoMember.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AnnoMember.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AthenaReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AthenaReq.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AthenaReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AthenaReq.java index be765e312..351aaf7fa 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AthenaReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AthenaReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/AudioRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AudioRes.java similarity index 78% rename from athena-all/src/main/java/run/mone/m78/ip/bo/AudioRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AudioRes.java index abc345e40..a99a8d596 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/AudioRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/AudioRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ClassInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ClassInfo.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ClassInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ClassInfo.java index 1c16cee3b..0096ae6ec 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ClassInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ClassInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; @@ -15,6 +15,8 @@ public class ClassInfo implements Serializable, PsiInfo { private String className; + private String simpleName; + private String moduleName; private boolean hidden; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassMeta.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassMeta.java similarity index 63% rename from athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassMeta.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassMeta.java index de39c8395..518bac980 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassMeta.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassMeta.java @@ -1,8 +1,10 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParam; import lombok.Data; import java.io.Serializable; +import java.util.List; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassRes.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassRes.java index 0bd217344..e2ba850d0 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/CreateClassRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/CreateClassRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Dependency.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Dependency.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Dependency.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Dependency.java index 2f1434d62..bd4e6d464 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Dependency.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Dependency.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ElementInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ElementInfo.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ElementInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ElementInfo.java index 7eeb9418b..2f69c2ac5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ElementInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ElementInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/FieldInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/FieldInfo.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/FieldInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/FieldInfo.java index 76d9c10b4..3a975eab0 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/FieldInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/FieldInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/GenerateCodeReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/GenerateCodeReq.java similarity index 67% rename from athena-all/src/main/java/run/mone/m78/ip/bo/GenerateCodeReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/GenerateCodeReq.java index 7111cfaad..ed5ae042c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/GenerateCodeReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/GenerateCodeReq.java @@ -1,12 +1,14 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.common.PromptType; +import com.intellij.psi.PsiMethod; +import com.xiaomi.youpin.tesla.ip.common.PromptType; import lombok.Builder; import lombok.Data; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -16,7 +18,7 @@ * @author zhangzhiyong * @description: * @date 2023-05-17 16:53 - * + *

* 主要用来生成代码 */ @Data @@ -52,7 +54,11 @@ public class GenerateCodeReq { private String showDialog; - private Map param; + @Builder.Default + private Map param = new HashMap<>(); + + @Builder.Default + private Map objMap = new HashMap<>(); /** * 格式化代码 @@ -82,6 +88,9 @@ public class GenerateCodeReq { //class相关代码 private String classCode; + //class代码,且带着占位标记($$这里需要补全代码$$) + private String classCodeWithMark; + private String qualifiedName; private String className; @@ -94,9 +103,17 @@ public class GenerateCodeReq { //选中的方法code(鼠标停留的位置) private String methodCode; + //带行号的method + private String lineNumberedMethod; + + private PsiMethod psiMethod; + //选中的内容 private String selectText; + //当前行内容 + private String currentLine; + //操作系统名称 private String systemName; @@ -107,5 +124,19 @@ public class GenerateCodeReq { @Builder.Default private String taskType = "edit"; + //编辑器中的偏移量 + private int offset; + + private List inheritedMethods; + + //用户设定的scope + private String userSettingScope; + + //debug的错误信息 + private String debugErrorMessage; + + //用来阻塞用的 + private CountDownLatch countDownLatch; + } diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/IdeaPluginInfoBo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/IdeaPluginInfoBo.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/bo/IdeaPluginInfoBo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/IdeaPluginInfoBo.java index 99061caa0..aad726f2e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/IdeaPluginInfoBo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/IdeaPluginInfoBo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/LombokTest.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/LombokTest.java similarity index 77% rename from athena-all/src/main/java/run/mone/m78/ip/bo/LombokTest.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/LombokTest.java index c6591f5c5..e9b5906f1 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/LombokTest.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/LombokTest.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/M78CodeGenerationInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/M78CodeGenerationInfo.java new file mode 100644 index 000000000..930227cee --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/M78CodeGenerationInfo.java @@ -0,0 +1,71 @@ +package com.xiaomi.youpin.tesla.ip.bo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 实体类。 + * + * @author zhangzhiyong + * @since 2024-06-12 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class M78CodeGenerationInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer id; + + private Long ctime; + + private Long utime; + + private Integer state; + + private String projectName; + + private String className; + + private Integer codeLinesCount; + + private String methodName; + + private String username; + + /** + * 1 根据注释生成代码 + * 2 inlay代码提示 + */ + @Builder.Default + private int type = 1; + + private String annotation; + + /** + * 1 idea + * 2 vscode + */ + @Builder.Default + private int source = 1; + + private String pluginVersion; + + private String ip; + + private String systemVersion; + + /** + * 操作类型 (1聊天 2生成代码 3代码建议 4生成注释 5智能命名 6一键push 7单元测试 8bug_fix) + */ + @Builder.Default + private int action = 2; + + private String ideVersion; +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Message.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Message.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Message.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Message.java index 52d2ce9ef..067d834fe 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Message.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Message.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/MessageConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MessageConsumer.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/MessageConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MessageConsumer.java index 1797467fa..5fbaa1fb4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/MessageConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MessageConsumer.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/MethodInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MethodInfo.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/bo/MethodInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MethodInfo.java index 19068e47d..5ac86c0e6 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/MethodInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/MethodInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import java.io.Serializable; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ModelRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModelRes.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ModelRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModelRes.java index 78d05d655..959ebb7e7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ModelRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModelRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ModuleInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModuleInfo.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ModuleInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModuleInfo.java index dd9b80fd0..2a63e2fc9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ModuleInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ModuleInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Msg.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Msg.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Msg.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Msg.java index 8c3f5e735..bc5e70d58 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Msg.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Msg.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ParamDialogReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamDialogReq.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ParamDialogReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamDialogReq.java index eae8cb370..e5218e710 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ParamDialogReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamDialogReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ParamInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamInfo.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ParamInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamInfo.java index 92430e8c1..9ea67a34c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ParamInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ParamInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.psi.PsiType; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/PluginDeleteParam.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PluginDeleteParam.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/bo/PluginDeleteParam.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PluginDeleteParam.java index a08d374ee..5022a51bd 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/PluginDeleteParam.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PluginDeleteParam.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ProjectModuleInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProjectModuleInfo.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ProjectModuleInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProjectModuleInfo.java index 0d6118d84..8d3b6ab29 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ProjectModuleInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProjectModuleInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/PromptContext.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptContext.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/bo/PromptContext.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptContext.java index 5e2b7c875..9932a73d4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/PromptContext.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptContext.java @@ -1,9 +1,10 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.openapi.editor.Editor; import lombok.Data; import run.mone.ultraman.bo.AthenaFieldInfo; import run.mone.ultraman.bo.AthenaMethodInfo; +import run.mone.ultraman.bo.PoClassInfo; import java.io.Serializable; import java.util.List; @@ -29,6 +30,8 @@ public class PromptContext implements Serializable { private List resourceCode; + private List poClassInfos; + private List methodCodeList; private List fieldCodeList; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/PromptInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptInfo.java similarity index 69% rename from athena-all/src/main/java/run/mone/m78/ip/bo/PromptInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptInfo.java index d99b9137b..c452e98be 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/PromptInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PromptInfo.java @@ -1,7 +1,9 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.List; @@ -15,6 +17,8 @@ */ @Data @Builder +@AllArgsConstructor +@NoArgsConstructor public class PromptInfo implements Serializable { private Long id; @@ -47,6 +51,18 @@ public boolean open(String key) { return this.labels.getOrDefault(key, "false").equals("true"); } + public boolean has(String key) { + return this.labels.containsKey(key); + } + + public boolean open(String key, String defaultValue) { + return this.labels.getOrDefault(key, defaultValue).equals("true"); + } + + public String getLabelValue(String key, String defaultValue) { + return this.labels.getOrDefault(key, defaultValue); + } + @Override public boolean equals(Object o) { diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ProxyAsk.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProxyAsk.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ProxyAsk.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProxyAsk.java index 462581438..a04f9f900 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ProxyAsk.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ProxyAsk.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/PsiInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PsiInfo.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/PsiInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PsiInfo.java index fb1d621e9..465648021 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/PsiInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/PsiInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Req.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Req.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Req.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Req.java index 2fbcd8824..737a0cb52 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Req.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Req.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Response.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Response.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Response.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Response.java index 950bd559e..5c4d9e3f7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Response.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Response.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import java.io.Serializable; import java.util.Map; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Result.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Result.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Result.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Result.java index 1d631876d..47424f477 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Result.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Result.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/RobotContext.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotContext.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/RobotContext.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotContext.java index 58dc6a661..ade15fe05 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/RobotContext.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotContext.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/RobotReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotReq.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/RobotReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotReq.java index 14dec27cc..567a73380 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/RobotReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/RobotReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import com.intellij.openapi.project.Project; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ServerInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ServerInfo.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ServerInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ServerInfo.java index c3e977c70..4b2c5cb0f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ServerInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ServerInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/SpiderUrl.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/SpiderUrl.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/bo/SpiderUrl.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/SpiderUrl.java index 5a4e9ec77..5052e9b5b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/SpiderUrl.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/SpiderUrl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/Tag.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Tag.java similarity index 58% rename from athena-all/src/main/java/run/mone/m78/ip/bo/Tag.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Tag.java index 112fa75c5..c004a7af9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/Tag.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/Tag.java @@ -1,6 +1,9 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serializable; @@ -9,6 +12,9 @@ * @date 2023/5/27 14:45 */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Tag implements Serializable { diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/TbTask.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TbTask.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/bo/TbTask.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TbTask.java index 00fd02585..99f0adc40 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/TbTask.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TbTask.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/TeslaPluginConfig.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TeslaPluginConfig.java similarity index 81% rename from athena-all/src/main/java/run/mone/m78/ip/bo/TeslaPluginConfig.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TeslaPluginConfig.java index a3f8f12b6..f7ca9bc1d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/TeslaPluginConfig.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/TeslaPluginConfig.java @@ -14,14 +14,17 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; +import com.xiaomi.youpin.tesla.ip.common.Const; import lombok.Data; +import run.mone.ultraman.listener.bo.CompletionEnum; import java.io.Serializable; import java.util.List; + /** * @author goodjava@qq.com */ @@ -54,10 +57,18 @@ public class TeslaPluginConfig implements Serializable { private String zToken = ""; + // chat的model private String model = ""; + // 非chat的model + private String noChatModel = ""; + + private String shortcut = ""; + private List modelList; + private CompletionEnum completionMode = CompletionEnum.SINGLE_LINE; + public String getMvnPath() { return mvnPath; @@ -154,4 +165,19 @@ public String getzToken() { public void setzToken(String zToken) { this.zToken = zToken; } + + public CompletionEnum getCompletionMode() { + return completionMode; + } + + public void setCompletionMode(CompletionEnum completionMode) { + this.completionMode = completionMode; + } + + public void setModelList(List modelList) { + if(modelList != null && !modelList.contains(Const.USE_BOT_MODEL)){ + modelList.add(Const.USE_BOT_MODEL); + } + this.modelList = modelList; + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/UserBo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserBo.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/bo/UserBo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserBo.java index fe74ac60c..8ea284e93 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/UserBo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserBo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/UserVo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserVo.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/bo/UserVo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserVo.java index 8d6f4c315..b33884c98 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/UserVo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/UserVo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; /** diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ValueInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ValueInfo.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ValueInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ValueInfo.java index ef6103387..9ef8c4c17 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ValueInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ValueInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ZAddrRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAddrRes.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ZAddrRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAddrRes.java index 989c4e107..f8a31e3f3 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ZAddrRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAddrRes.java @@ -1,8 +1,9 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; import java.util.List; +import java.util.Map; /** * @author caobaoyu @@ -30,5 +31,5 @@ public class ZAddrRes { private List modelsV2; - + private String userName; } diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ZAskParam.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAskParam.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ZAskParam.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAskParam.java index e57c98bad..dc8fd03a9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ZAskParam.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZAskParam.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptAddonItem.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptAddonItem.java similarity index 82% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptAddonItem.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptAddonItem.java index 30ee19001..c40f87662 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptAddonItem.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptAddonItem.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptRes.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptRes.java index 6cea10b4d..f2dff338a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ZPromptRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZPromptRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/ZRequestPram.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZRequestPram.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/bo/ZRequestPram.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZRequestPram.java index 355b54c0c..71c5977f1 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/ZRequestPram.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/ZRequestPram.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo; +package com.xiaomi.youpin.tesla.ip.bo; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Choice.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Choice.java similarity index 75% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Choice.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Choice.java index 65bd71770..bd9b779fa 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Choice.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Choice.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Completions.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Completions.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Completions.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Completions.java index 1768aa682..222254ed0 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Completions.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Completions.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; @@ -16,7 +16,7 @@ public class Completions implements Serializable { @Builder.Default - private String model = "gpt-4-1106-preview"; + private String model = "gpt4_o"; private List messages; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Format.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Format.java similarity index 81% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Format.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Format.java index b6a216f6c..687676bbb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Format.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Format.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ImageUrl.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ImageUrl.java similarity index 78% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ImageUrl.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ImageUrl.java index ddcff8ea7..65d631118 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ImageUrl.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ImageUrl.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/LocalReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/LocalReq.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/LocalReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/LocalReq.java index 04565ea2f..df8783935 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/LocalReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/LocalReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Message.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Message.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Message.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Message.java index ffcd848ba..a12c9da6a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/Message.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/Message.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqContent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqContent.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqContent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqContent.java index 9c6e3e9ca..a24ab007a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqContent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqContent.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqMessage.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqMessage.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqMessage.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqMessage.java index 05d5720a8..161dce7b3 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/ReqMessage.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/ReqMessage.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/SpeechReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/SpeechReq.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/SpeechReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/SpeechReq.java index d3ce03d8d..fa4fe0cdd 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/SpeechReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/SpeechReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionReq.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionReq.java index f4418b7b1..572cbf6dc 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionRes.java similarity index 78% rename from athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionRes.java index 92533e03e..ad18dd8bc 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/chatgpt/VisionRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/chatgpt/VisionRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.chatgpt; +package com.xiaomi.youpin.tesla.ip.bo.chatgpt; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParam.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParam.java similarity index 82% rename from athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParam.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParam.java index ccd82c65f..2411e9cbe 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParam.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParam.java @@ -1,12 +1,12 @@ -package run.mone.m78.ip.bo.prompt; +package com.xiaomi.youpin.tesla.ip.bo.prompt; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.LabelUtils; -import run.mone.m78.ip.util.PackageUtils; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.PackageUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; import lombok.Data; import java.io.Serializable; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParamType.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParamType.java similarity index 80% rename from athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParamType.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParamType.java index 36b0737dc..19e333bb5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/prompt/PromptParamType.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/prompt/PromptParamType.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.prompt; +package com.xiaomi.youpin.tesla.ip.bo.prompt; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiChatMessage.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiChatMessage.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiChatMessage.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiChatMessage.java index bc012147c..1f4d082a6 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiChatMessage.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiChatMessage.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiMessageManager.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiMessageManager.java similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiMessageManager.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiMessageManager.java index c4f3f0d61..5f476ceca 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/AiMessageManager.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/AiMessageManager.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/BoolData.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/BoolData.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/BoolData.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/BoolData.java index 8087d46a9..877712dd6 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/BoolData.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/BoolData.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/EventRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/EventRes.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/EventRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/EventRes.java index 6e5ae359b..00bef7748 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/EventRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/EventRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/ItemData.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ItemData.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/ItemData.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ItemData.java index c056e7483..a3ffe0fc4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/ItemData.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ItemData.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapData.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapData.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapData.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapData.java index 035e004bf..0e34219fd 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapData.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapData.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapDataValue.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapDataValue.java similarity index 84% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapDataValue.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapDataValue.java index 67fa89c32..1ea802412 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MapDataValue.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MapDataValue.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageData.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageData.java similarity index 67% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageData.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageData.java index 5ea160dca..8cced2eb9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageData.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageData.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageReq.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageReq.java index bda2f4876..320b693ea 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageRes.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageRes.java index f90f2e108..5c3d0755b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageType.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageType.java similarity index 86% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageType.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageType.java index 551f51061..9bc10bf1d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/MessageType.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/MessageType.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/ProjectAiMessageManager.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ProjectAiMessageManager.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/ProjectAiMessageManager.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ProjectAiMessageManager.java index 3f5165a7b..1532572f4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/ProjectAiMessageManager.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/ProjectAiMessageManager.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; import com.google.gson.Gson; import com.intellij.openapi.project.Project; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/Role.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/Role.java similarity index 72% rename from athena-all/src/main/java/run/mone/m78/ip/bo/robot/Role.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/Role.java index ff1a019af..f53e26e89 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/robot/Role.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/robot/Role.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.robot; +package com.xiaomi.youpin.tesla.ip.bo.robot; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/z/EmbeddingStatus.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/EmbeddingStatus.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/bo/z/EmbeddingStatus.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/EmbeddingStatus.java index 975a3f9f2..c8fd20687 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/z/EmbeddingStatus.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/EmbeddingStatus.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.z; +package com.xiaomi.youpin.tesla.ip.bo.z; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/z/ZKnowledgeRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZKnowledgeRes.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/bo/z/ZKnowledgeRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZKnowledgeRes.java index 052619481..1ca1d3d6d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/z/ZKnowledgeRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZKnowledgeRes.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.z; +package com.xiaomi.youpin.tesla.ip.bo.z; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/bo/z/ZResult.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZResult.java similarity index 82% rename from athena-all/src/main/java/run/mone/m78/ip/bo/z/ZResult.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZResult.java index 3c7695802..f4553483f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/bo/z/ZResult.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/bo/z/ZResult.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.bo.z; +package com.xiaomi.youpin.tesla.ip.bo.z; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/client/MyHttpClient.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/client/MyHttpClient.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/client/MyHttpClient.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/client/MyHttpClient.java index 92798ca90..ed2bdc815 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/client/MyHttpClient.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/client/MyHttpClient.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.client; +package com.xiaomi.youpin.tesla.ip.client; import okhttp3.OkHttpClient; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ApiCall.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiCall.java similarity index 80% rename from athena-all/src/main/java/run/mone/m78/ip/common/ApiCall.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiCall.java index a2c78c041..36d901864 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ApiCall.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiCall.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.google.gson.Gson; @@ -28,7 +28,7 @@ */ public class ApiCall { - private static final String END_POINT = ""; + private static final String END_POINT = "http://127.0.0.1:8999"; public static final String MUSIC_API = END_POINT + "/music"; public static final String TEXT_API = END_POINT + "/text"; @@ -66,4 +66,14 @@ public String callIt(String url, String name) { } + public static void main(String[] args) { + ApiCall call = new ApiCall(); + //System.out.println(list); + + Map m = new HashMap<>(); + m.put("name", "zzy"); + m.put("cmd", "get"); + String res = call.postCall(CODE_API, new Gson().toJson(m)); + System.out.println(res); + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ApiRes.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiRes.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/common/ApiRes.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiRes.java index 85b794b3e..1152c151a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ApiRes.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ApiRes.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import java.io.Serializable; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/AthenaBiConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaBiConsumer.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/common/AthenaBiConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaBiConsumer.java index ddac9950d..3f3eb8b67 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/AthenaBiConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaBiConsumer.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.project.Project; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/AthenaMessageConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaMessageConsumer.java similarity index 86% rename from athena-all/src/main/java/run/mone/m78/ip/common/AthenaMessageConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaMessageConsumer.java index fad04c126..e1c9511f6 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/AthenaMessageConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/AthenaMessageConsumer.java @@ -1,8 +1,8 @@ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.google.gson.Gson; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; import lombok.extern.slf4j.Slf4j; /** diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Base64Utils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Base64Utils.java new file mode 100644 index 000000000..398e259d9 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Base64Utils.java @@ -0,0 +1,16 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import java.nio.charset.Charset; +import java.util.Base64; + +/** + * @author goodjava@qq.com + * @date 2024/6/19 08:47 + */ +public class Base64Utils { + + public static String decodeBase64String(String str) { + return new String(Base64.getDecoder().decode(str.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")); + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ChromeUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ChromeUtils.java new file mode 100644 index 000000000..ed1562ab2 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ChromeUtils.java @@ -0,0 +1,59 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import com.google.common.net.UrlEscapers; +import com.google.gson.Gson; +import com.intellij.ui.jcef.JBCefBrowser; +import com.xiaomi.youpin.tesla.ip.bo.Req; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.listener.UltrmanTreeKeyAdapter; +import lombok.SneakyThrows; + +/** + * @author goodjava@qq.com + * @date 2023/6/2 16:44 + */ +public class ChromeUtils { + + private static final Gson gson = new Gson(); + + @SneakyThrows + public static void call(String projectName, String method, String param, boolean useReq) { + if (useReq) { + param = UrlEscapers.urlFragmentEscaper().escape(gson.toJson(Req.builder().code(500).message(param))); + } else { + param = UrlEscapers.urlFragmentEscaper().escape(param); + } + JBCefBrowser jbCefBrowser = UltrmanTreeKeyAdapter.browserMap.get(projectName); + if (null != jbCefBrowser) { + jbCefBrowser.getCefBrowser().executeJavaScript(method + "('" + param + "');", jbCefBrowser.getCefBrowser().getURL(), 1); + } + } + + + public static void call(String projectName, String param, int code) { + call(projectName, param, "", code); + } + + public static void call(String projectName, String param, String sound, int code) { + param = UrlEscapers.urlFragmentEscaper().escape(gson.toJson(Req.builder().code(code).message(param).sound(sound))); + JBCefBrowser jbCefBrowser = UltrmanTreeKeyAdapter.browserMap.get(projectName); + if (null != jbCefBrowser) { + jbCefBrowser.getCefBrowser().executeJavaScript("showErrorCode" + "('" + param + "');", jbCefBrowser.getCefBrowser().getURL(), 1); + } + } + + public static void call(String projectName, AiChatMessage res) { + String param = UrlEscapers.urlFragmentEscaper().escape(gson.toJson(res)); + JBCefBrowser jbCefBrowser = UltrmanTreeKeyAdapter.browserMap.get(projectName); + if (null != jbCefBrowser) { + jbCefBrowser.getCefBrowser().executeJavaScript("showErrorCode" + "('" + param + "');", jbCefBrowser.getCefBrowser().getURL(), 1); + } + } + + + public static void call(String projectName, String method, String param) { + call(projectName, method, param, false); + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigCenter.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigCenter.java new file mode 100644 index 000000000..74b437474 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigCenter.java @@ -0,0 +1,71 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.xiaomi.youpin.tesla.ip.bo.AiCodeRes; +import com.xiaomi.youpin.tesla.ip.bo.Tag; +import com.xiaomi.youpin.tesla.ip.bo.ZPromptRes; +import com.xiaomi.youpin.tesla.ip.bo.ZRequestPram; +import lombok.Data; +import lombok.Getter; +import run.mone.ultraman.http.HttpClient; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author caobaoyu + * @description: 从Z获取一些基础配置 对应 -> 68 Athena の cfg center + * @date 2023-05-30 11:02 + */ +@Data +public class ConfigCenter { + + + private static Map copyrightingMap = new HashMap<>(); + + @Getter + private static List guide = new ArrayList<>(); + + private static List menuTag = new ArrayList<>(); + + public static Map getMenuTag() { + return menuTag.stream().collect(Collectors.toMap(Tag::getName, Function.identity())); + } + + public static void init(String zAddr) { + guide.clear(); + menuTag.clear(); + buildCopyrighting(zAddr); + } + + private static void buildCopyrighting(String zAddr) { + Safe.run(() -> { + ZRequestPram param = ZRequestPram.builder().token(ConfigUtils.getConfig().getzToken()).type(68).build(); + String url = zAddr + "/list"; + Gson gson = new Gson(); + String httpRes = HttpClient.callZServer(url, "copyrighting", gson.toJson(param)); + List data = gson.fromJson(httpRes, new TypeToken>() { + }.getType()); + Map collect = data.stream().collect(Collectors.toMap(ZPromptRes::getName, Function.identity())); + List> res = gson.fromJson(collect.get("copyrighting").getMeta(), new TypeToken>>() { + }.getType()); + res.forEach(l -> copyrightingMap.putAll(l)); + guide.addAll(gson.fromJson(collect.get("guide").getData(), new TypeToken>() { + }.getType())); + menuTag.addAll(gson.fromJson(collect.get("menu").getData(), new TypeToken>() { + }.getType())); + }); + + } + + public static AiCodeRes build(String type) { + return copyrightingMap.get(type); + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ConfigUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigUtils.java similarity index 60% rename from athena-all/src/main/java/run/mone/m78/ip/common/ConfigUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigUtils.java index dfc9454f4..b05751629 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ConfigUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ConfigUtils.java @@ -14,30 +14,41 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.google.gson.Gson; import com.intellij.ide.util.PropertiesComponent; -import run.mone.m78.ip.bo.TeslaPluginConfig; +import com.xiaomi.youpin.tesla.ip.bo.TeslaPluginConfig; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.AthenaContext; +import java.util.Map; + /** * @author goodjava@qq.com */ public abstract class ConfigUtils { public static TeslaPluginConfig getConfig() { - String v = PropertiesComponent.getInstance().getValue(""); + String v = PropertiesComponent.getInstance().getValue("tesla_plugin_token"); if (StringUtils.isNotEmpty(v)) { TeslaPluginConfig config = new Gson().fromJson(v, TeslaPluginConfig.class); + // 聊天的model设置 String model = config.getModel(); if (StringUtils.isNotEmpty(model)) { AthenaContext.ins().setGptModel(model); AthenaContext.ins().setModelList(config.getModelList()); } + // 非聊天的model设置 + String noChatModel = config.getNoChatModel(); + if (StringUtils.isNotEmpty(noChatModel)) { + AthenaContext.ins().setNoChatModel(noChatModel); + } + + // setup from env if (StringUtils.isEmpty(config.getDashServer())) { config.setDashServer(System.getenv("DASH")); } @@ -48,6 +59,21 @@ public static TeslaPluginConfig getConfig() { config.setChatgptKey(System.getenv("API")); } + // setup from inner config + Map athenaConfig = ResourceUtils.getAthenaConfig(); + if (StringUtils.isEmpty(config.getDashServer())) { + config.setDashServer(athenaConfig.get(Const.CONF_DASH_URL).trim()); + } + if (StringUtils.isEmpty(config.getNickName())) { + config.setNickName(athenaConfig.get(Const.CONF_NICK_NAME).trim()); + } + if (StringUtils.isEmpty(config.getAiProxy())) { + config.setAiProxy(athenaConfig.get(Const.CONF_AI_PROXY_URL).trim()); + } + if (StringUtils.isEmpty(config.getChatServer())) { + config.setChatServer(athenaConfig.get(Const.CONF_PORT).trim()); + } + AthenaContext.ins().setToken(config.getToken()); return config; } diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Const.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Const.java new file mode 100644 index 000000000..7598225f5 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Const.java @@ -0,0 +1,150 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import com.intellij.openapi.util.Key; +import com.intellij.util.messages.Topic; +import run.mone.ultraman.listener.AthenaMessageListener; + +/** + * @author goodjava@qq.com + * @date 2023/6/17 09:37 + */ +public interface Const { + + String MODULE_FILE_NAME = "athena_module.md"; + + String BOT_ID = "botId"; + + String TOKEN = "token"; + + String REQ_PACKAGE = "req_package"; + + String DEFAULT_REQ_PACKAGE = "run.mone.bo"; + + String DISABLE_SEARCH = "disable.search"; + + String AI_PROXY_CHAT = "ai.proxy.chat"; + + String ENABLE_ATHENA_STATUS_BAR = "enable.athena.status.bar"; + + String DISABLE_ACTION_GROUP = "disable.action.group"; + + String BIZ_WRITE = "biz_write"; + + String OPEN_AI_KEY = "open_ai_key"; + + String OPEN_AI_PROXY = "open_ai_proxy"; + + //直接本地调用chatgpt(local模式) + String OPEN_AI_LOCAL = "open_ai_local"; + + //使用bot + String USE_BOT = "use_bot"; + + String INLAY = "inlay"; + + //整体的代码补全功能是否关闭 + String DISABLE_CODE_COMPLETION = "DISABLE_CODE_COMPLETION"; + + //开启Prompt menu + String ENABLE_PROMPT_MENU = "enable.prompt.menu"; + + String STREAM = "stream"; + + String FALSE = "false"; + + String TRUE = "true"; + + //本地测试 + String OPEN_AI_TEST = "open.ai.test"; + + //提问的时候是否开启选中的文本 + String OPEN_SELECT_TEXT = "open.select.text"; + + //本地使用的模型(优先:gpt-4o) + String OPEN_AI_MODEL = "open_ai_model"; + + String SEARCH = "search"; + + int UI_CANCEL_CODE = 555; + + String OPEN_GUIDE = "open.guide"; + + String DEBUG = "debug"; + + //多模态模式 + String VISION = "vision"; + + String CODE_SCRIPT = "code.script"; + + String TREE_SELECT = "tree.select"; + + String BOT_URL = "bot.url"; + + String INLAY_DELAY = "inlay.delay"; + + String INLAY_BOT_ID = "inlay.bot.id"; + + String INLAY_SCOPE = "inlay.scope"; + + String CONF_NICK_NAME = "conf.nickName"; + + String CONF_DASH_URL = "conf.dash.url"; + + String CONF_AI_PROXY_URL = "conf.ai-proxy.url"; + + String CONF_PORT = "conf.port"; + + Key T_KEY = new Key<>("t"); + + Topic ATHENA_TOPIC = new Topic(AthenaMessageListener.class); + + String CONF_M78_URL = "conf.m78.url"; + + String CONF_M78_SPEECH2TEXT = "conf.a2t.endpoint"; + + String CONF_M78_TEXT2SPEECH = "conf.t2a.endpoint"; + + String CONF_M78_UPLOAD_CODE_INFO = "conf.upload.info.endpoint"; + + String CONF_M78_CODE_GEN_WITH_ENTER = "conf.codegen.trigger.enter"; + + String PROMPT_LABEL_TYPE = "type"; + + String CONF_COMPLETION_TYPE = "conf.completion.type"; + + //生成代码的prompt name + String GENERATE_CODE = "biz_sidecar"; + + //生产代码的注释 + String GENERATE_CODE_COMMENT = "biz_sidecar_comment"; + + //单元测试的prompt name + String UNIT_TEST = "test_code"; + + String CLIENT_VERSION = "clientVersion"; + + String CLIENT_NAME = "clientName"; + + String PLUGIN_NAME = "Mione"; + + String MIONE_CONSOLE_NAME = "MioneConsole"; + + // 右侧聊天用的prompt name + String ATHENA_CHAT = "athena_chat"; + + // 代码检查的prompt name + String CODE_REVIEW = "bot_stream"; + + // 配置用于控制右侧聊天是否走BOT逻辑,默认走 + String CONF_CHAT_USE_BOT = "conf.chat.use.bot"; + + // 执行BOT传递参数的模型的key + String AI_MODEL_PARAM_KEY = "model"; + + // 使用BOT默认模型的选项 + String USE_BOT_MODEL = "默认"; + + // 生成单测prompt name + String GENERATE_UNIT_TEST = "generate_unit_test"; + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Context.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Context.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/common/Context.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Context.java index c783f4641..ea9f9f011 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Context.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Context.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.project.Project; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/DownloadUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/DownloadUtils.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/DownloadUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/DownloadUtils.java index 53d5c7d89..f72f5d585 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/DownloadUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/DownloadUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import java.io.IOException; diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/TaskService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ErrorMessage.java similarity index 74% rename from athena-all/src/main/java/run/mone/m78/ip/service/TaskService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ErrorMessage.java index a105ab331..a90d53f3d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/TaskService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ErrorMessage.java @@ -14,19 +14,14 @@ * limitations under the License. */ -package run.mone.m78.ip.service; - -import java.util.List; +package com.xiaomi.youpin.tesla.ip.common; /** - * @Author goodjava@qq.com - * @Date 2021/11/9 14:04 + * @author shanwb + * @date 2024-07-05 */ -public class TaskService { - +public class ErrorMessage { - public List tasks(String name) { - return null; - } + public static final String ERR_NOT_IN_CLASS_SCOPE = "请检查当前位置是否在class范围内{}"; } diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Events.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Events.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/Events.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Events.java index 58e8ce0ca..42f4c876b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Events.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Events.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.application.ApplicationManager; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/FileUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/FileUtils.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/common/FileUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/FileUtils.java index 192d444fb..74556ed4d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/FileUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/FileUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import org.apache.commons.io.IOUtils; import org.beetl.core.Configuration; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/GlobalConfig.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/GlobalConfig.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/common/GlobalConfig.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/GlobalConfig.java index 2117c579b..b26f8c6be 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/GlobalConfig.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/GlobalConfig.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; public class GlobalConfig { public static final String PLUGIN_NAME = "youpin_plugin"; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/IdeaPluginVersion.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/IdeaPluginVersion.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/common/IdeaPluginVersion.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/IdeaPluginVersion.java index 5e68a42c8..9461f5d91 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/IdeaPluginVersion.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/IdeaPluginVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/JavaClassUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/JavaClassUtils.java new file mode 100644 index 000000000..dca29ad1f --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/JavaClassUtils.java @@ -0,0 +1,120 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import com.intellij.ide.highlighter.JavaFileType; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiShortNamesCache; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import org.jetbrains.annotations.NotNull; + +/** + * @author goodjava@qq.com + * @date 2023/4/12 11:05 + */ +public abstract class JavaClassUtils { + + /** + * Create a class. + */ + public static void createClass(AnActionEvent e) { + createClass(e.getProject(), e.getData(PlatformDataKeys.EDITOR), "abc", ""); + } + + public static void createClass(Project project, Editor editor, String name, String code) { + if (project == null) { + return; + } + String classContent = code; + @NotNull PsiFile javaClassFile = PsiFileFactory.getInstance(project).createFileFromText(name, JavaFileType.INSTANCE, classContent); + javaClassFile.setName(name + ".java"); + //Add Java classes to the project. + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiDirectory containerDirectory = psiFile.getContainingDirectory(); + WriteCommandAction.runWriteCommandAction(project, () -> { + containerDirectory.add(javaClassFile); + }); + } + + + + public static void createClass(Project project, Editor editor, String name, String code, boolean testClass) { + if (project == null) { + return; + } + String classContent = code; + @NotNull PsiFile javaClassFile = PsiFileFactory.getInstance(project).createFileFromText(name, JavaFileType.INSTANCE, classContent); + javaClassFile.setName(name + ".java"); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiDirectory containerDirectory = testClass ? CodeService.getSourceDirectory(project, "", true) : psiFile.getContainingDirectory(); + WriteCommandAction.runWriteCommandAction(project, () -> { + containerDirectory.add(javaClassFile); + }); + } + + public static void createClass(Project project, Editor editor, String name, String code, boolean testClass, String packagePath) { + if (project == null) { + return; + } + String classContent = code; + @NotNull PsiFile javaClassFile = PsiFileFactory.getInstance(project).createFileFromText(name, JavaFileType.INSTANCE, classContent); + javaClassFile.setName(name + ".java"); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiDirectory containerDirectory = testClass ? CodeService.getSourceDirectory(project, true, packagePath) : psiFile.getContainingDirectory(); + WriteCommandAction.runWriteCommandAction(project, () -> { + containerDirectory.add(javaClassFile); + // 生成后打开文件 + openClass(project, name); + }); + } + + + public static void openClass(AnActionEvent e) { + // 获取当前项目实例 + Project project = e.getProject(); + if (project == null) { + return; + } + // 定位目标Java类 + String targetClassName = "MyNewJavaClass"; + PsiClass[] targetClasses = PsiShortNamesCache.getInstance(project).getClassesByName(targetClassName, GlobalSearchScope.allScope(project)); + if (targetClasses.length > 0) { + PsiClass targetClass = targetClasses[0]; + PsiFile containingFile = targetClass.getContainingFile(); + // 打开目标Java文件 + FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + fileEditorManager.openFile(containingFile.getVirtualFile(), true); + } + } + + public static void openClass(Project project, String className) { + // 获取当前项目实例 + if (project == null) { + return; + } + // 定位目标Java类 + String targetClassName = className; + PsiClass[] targetClasses = PsiShortNamesCache.getInstance(project).getClassesByName(targetClassName, GlobalSearchScope.allScope(project)); + if (targetClasses.length > 0) { + PsiClass targetClass = targetClasses[0]; + PsiFile containingFile = targetClass.getContainingFile(); + // 打开目标Java文件 + FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + fileEditorManager.openFile(containingFile.getVirtualFile(), true); + } + } + + + public static String getClassName(String className) { + String[] classNameParts = className.split("\\."); + String simpleClassName = classNameParts[classNameParts.length - 1]; + return simpleClassName; + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/MessageQueue.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/MessageQueue.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/common/MessageQueue.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/MessageQueue.java index 7eb5a0717..636f294e4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/MessageQueue.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/MessageQueue.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; -import run.mone.m78.ip.bo.Response; +import com.xiaomi.youpin.tesla.ip.bo.Response; import java.util.HashMap; import java.util.Map; +import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; /** diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Mp3Player.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3Player.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/common/Mp3Player.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3Player.java index b0b1ead8c..faca14455 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Mp3Player.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3Player.java @@ -14,14 +14,20 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.diagnostic.Logger; +import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.net.URL; import java.util.Objects; /** @@ -36,6 +42,11 @@ public class Mp3Player { private static final Logger log = Logger.getInstance(Mp3Player.class); + public static void main(String[] args) throws IOException, UnsupportedAudioFileException { +// Mp3Player player = new Mp3Player(); + + } + public void playMp3Url(String url) throws UnsupportedAudioFileException, IOException { } diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Mp3PlayerV2.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3PlayerV2.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/common/Mp3PlayerV2.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3PlayerV2.java index 51214ab51..8e1c1d49b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Mp3PlayerV2.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Mp3PlayerV2.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.diagnostic.Logger; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/NotificationCenter.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/NotificationCenter.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/NotificationCenter.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/NotificationCenter.java index 92d2c896f..071c54e52 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/NotificationCenter.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/NotificationCenter.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/OggPlayer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OggPlayer.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/common/OggPlayer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OggPlayer.java index a0287318f..9b88522d2 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/OggPlayer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OggPlayer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import javax.sound.sampled.AudioFormat; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/OpenImageConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenImageConsumer.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/common/OpenImageConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenImageConsumer.java index 6e101a960..01a7fa7c9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/OpenImageConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenImageConsumer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.actionSystem.DataContext; @@ -41,7 +41,7 @@ public class OpenImageConsumer implements Consumer { private static final Logger LOG = Logger.getInstance(OpenImageConsumer.class); - private String imgUrl = ""; + private String imgUrl = "xxx"; public OpenImageConsumer() { } diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/OpenTextConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenTextConsumer.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/common/OpenTextConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenTextConsumer.java index b824d886e..0bee7af36 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/OpenTextConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/OpenTextConsumer.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -27,6 +28,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.UUID; import java.util.function.Consumer; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/PluginVersion.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PluginVersion.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/common/PluginVersion.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PluginVersion.java index accaa8efd..4f35b3d5c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/PluginVersion.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PluginVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ProjectCache.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProjectCache.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/ProjectCache.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProjectCache.java index b4dc5d0d5..0bc6c81e4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ProjectCache.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProjectCache.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Prompt.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Prompt.java new file mode 100644 index 000000000..49d8f40e7 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Prompt.java @@ -0,0 +1,267 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import com.google.common.base.Splitter; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationInfo; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.Version; +import run.mone.ultraman.common.SafeRun; +import run.mone.ultraman.http.HttpClient; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @author caobaoyu + * @date 2023/4/15 08:38 + */ +@Slf4j +public class Prompt { + + private static Map promptMap = new HashMap<>(); + + private static CopyOnWriteArrayList promptMeta = new CopyOnWriteArrayList<>(); + + private static String zAddr = ""; + + private static AtomicBoolean loadFinish = new AtomicBoolean(); + + public static String get(String key) { + return promptMap.get(key); + } + + public static List getPromptMeta() { + return promptMeta; + } + + public static boolean isLoadFinish() { + return loadFinish.get(); + } + + + private static Gson gson = new Gson(); + + public static void flush() { + init(); + } + + public static int size() { + return promptMap.size(); + } + + + public static void init() { + zAddr = reportPluginInfo(); + if (StringUtils.isEmpty(zAddr)) { + return; + } + promptMeta.clear(); + promptMeta.addAll(getPrompt()); + ConfigCenter.init(zAddr); + loadFinish.set(true); + } + + public static List getPrompt() { + try { + ZRequestPram param = new ZRequestPram(); + String zToken = ConfigUtils.getConfig().getzToken(); + String url = zAddr + "/list"; + param.setType(64); + param.setToken(zToken); + String res = HttpClient.callHttpServer(url, "get_prompt_list", gson.toJson(param)); + List data = gson.fromJson(res, new TypeToken>() { + }.getType()); + return convertZResToInfo(data); + } catch (Throwable ex) { + log.error(ex.getMessage()); + NotificationCenter.notice("get prompt error:" + ex.getMessage(), NotificationType.ERROR, true); + return Lists.newArrayList(); + } + } + + + public static PromptInfo getPrompt(int type, String name) { + try { + ZRequestPram param = new ZRequestPram(); + String zToken = ConfigUtils.getConfig().getzToken(); + String url = zAddr + "/list"; + param.setType(type); + param.setName(name); + param.setToken(zToken); + String res = HttpClient.callHttpServer(url, "get_prompt:" + name, gson.toJson(param)); + List data = gson.fromJson(res, new TypeToken>() { + }.getType()); + List list = convertZResToInfo(data); + if (list.size() > 0) { + return list.get(0); + } + } catch (Throwable ex) { + log.error(ex.getMessage()); + NotificationCenter.notice("get prompt error:" + ex.getMessage(), NotificationType.ERROR, true); + } + return null; + } + + + /** + * 将Z的结果转换为实体 + * + * @param data + * @return + */ + private static List convertZResToInfo(List data) { + return data.stream().map(v -> PromptInfo.builder() + .id(v.getId()) + .promptName(v.getName()) + .tags(v.getTags()) + .data(v.getData()) + .labels(getLabels(v)) + .collected(v.getCollected()) + .usedTimes(v.getUsedTimes()) + .meta(v.getMeta()) + .desc(v.getDescription()) + .addon(v.getAddon()) + .addon_metas(v.getAddon_metas()) + .collectedSort(v.getCollectedSort()) + .build()).toList(); + } + + //用user的覆盖即可 + private static Map getLabels(ZPromptRes v) { + if (MapUtils.isNotEmpty(v.getUserLabels())) { + v.getLabels().putAll(v.getUserLabels()); + } + return v.getLabels(); + } + + public static List promptList(String tagName) { + return promptMeta.stream().filter(it -> { + List tags = it.getTags(); + if (null == tags) { + return false; + } + return tags.stream().filter(tag -> tag.getName().equals(tagName)).findAny().isPresent(); + }).collect(Collectors.toList()); + } + + public static boolean containsTag(List tags, String tagName) { + return tags.stream().filter(tag -> tag.getName().equals(tagName)).findAny().isPresent(); + } + + /** + * 查询是那种类型 + * + * @param info + * @return + */ + public static PromptType getPromptType(PromptInfo info) { + List tags = info.getTags(); + if (null == tags) { + return PromptType.modifyMethod; + } + + for (PromptType type : PromptType.values()) { + if (containsTag(info.getTags(), type.name())) { + return type; + } + } + return PromptType.modifyMethod; + } + + + public static String reportPluginInfo() { + try { + ZAddrRes zAddrRes = zAddrRes(); + initConfig(zAddrRes); + return zAddrRes.getAddr(); + } catch (Throwable ex) { + log.error(ex.getMessage()); + return ""; + } + } + + public static ZAddrRes zAddrRes() { + String aiProxy = ResourceUtils.getAthenaConfig().get(Const.CONF_AI_PROXY_URL); + AthenaReq req = AthenaReq.builder() + .userName(ConfigUtils.getConfig().getNickName()) + .zzToken(ConfigUtils.getConfig().getzToken()) + .version(new Version().toString()) + .os(System.getProperty("os.name").toLowerCase()) + .ideaVersion(ApplicationInfo.getInstance().getBuild().asString()) + .time(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())) + .build(); + String res = HttpClient.callHttpServer(aiProxy + "/report", "report", gson.toJson(req)); + ZAddrRes zAddrRes = gson.fromJson(res, ZAddrRes.class); + AthenaContext.ins().setZAddr(zAddrRes.getAddr()); + AthenaContext.ins().setModels(zAddrRes.getModelsV2()); + AthenaContext.ins().setUserName(zAddrRes.getUserName()); + AthenaContext.ins().convertModelsToModelMap(); + return zAddrRes; + } + + private static void initConfig(ZAddrRes zAddrRes) { + SafeRun.run(() -> { + if (StringUtils.isNotEmpty(zAddrRes.getAthenaConfig())) { + String config = zAddrRes.getAthenaConfig(); + Splitter.on(",").split(config).forEach(it -> { + List list = Splitter.on(":").splitToList(it); + if (null != list && list.size() == 2) { + ResourceUtils.putConfigIfAbsent(list.get(0), list.get(1)); + } + }); + } + }); + } + + + public static PromptInfo getPromptInfo(String promptName) { + return promptMeta.stream().filter(it -> it.getPromptName().equals(promptName)).findAny().get(); + } + + public static List getPromptInfoByTag(String tag) { + return promptMeta.stream().filter(promptInfo -> containsTag(promptInfo.getTags(), tag)).collect(Collectors.toList()); + } + + public static List getCollected() { + return promptMeta.stream().filter(PromptInfo::isCollected).sorted(Comparator.comparing(PromptInfo::getCollectedSort)).collect(Collectors.toList()); + } + + /** + * 获取使用次数最多的size个prompt + * + * @param size + * @return + */ + public static List getMostUsed(int size) { + return promptMeta.stream().sorted(Comparator.comparing(PromptInfo::getUsedTimes).reversed()).limit(size).collect(Collectors.toList()); + } + + /** + * 获取某个标签下使用次数最多的size个prompt + * + * @param size + * @param tag + * @return + */ + public static List getMostUsed(int size, String tag) { + return promptMeta.stream().filter(promptInfo -> containsTag(promptInfo.getTags(), tag)) + .sorted(Comparator.comparing(PromptInfo::getUsedTimes).reversed()).limit(size).collect(Collectors.toList()); + } + + public static String getzAddr() { + return zAddr; + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/PromptType.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PromptType.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/common/PromptType.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PromptType.java index 8c7a9c8a2..447e60a04 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/PromptType.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/PromptType.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; /** * @author goodjava@qq.com @@ -30,6 +30,7 @@ public enum PromptType { generateMiapiMethod("根据miapi知识库生成某接口调用方法"), generateTestMethod("生成测试代码"), generateInterface("提取公共方法生成接口"), + executeBot("执行bot(m78)"), question("ai会向你提问") ; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ProxyUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProxyUtils.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/common/ProxyUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProxyUtils.java index 89df49934..19dc27bdc 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ProxyUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/ProxyUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Safe.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Safe.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/Safe.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Safe.java index d2e123e91..6a1981182 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Safe.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/Safe.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import lombok.extern.slf4j.Slf4j; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/StringUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/StringUtils.java new file mode 100644 index 000000000..13bcd9fc1 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/StringUtils.java @@ -0,0 +1,51 @@ +package com.xiaomi.youpin.tesla.ip.common; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author goodjava@qq.com + * @date 2023/5/18 22:26 + */ +public abstract class StringUtils { + + public static Pattern endingKeywordPattern = Pattern.compile("(\\(|(|\\\\)(class|method|project|module)(\\)|)|\\\\)?$"); + + + public static String convertToCamelCase(String input) { + StringBuilder result = new StringBuilder(); + String[] words = input.split("_"); + result.append(words[0]); + for (int i = 1; i < words.length; i++) { + String word = words[i]; + String capitalizedWord = Character.toUpperCase(word.charAt(0)) + word.substring(1); + result.append(capitalizedWord); + } + return result.toString(); + } + + + //写一个正则,从结尾提取出我期望的字符(class、method、project、module),接下来描述时我用x代表目标字符,结尾场景有这三种情况:(x)、(x)、\x,不满足提取诉求的返回空 + public static String extractEndingKeyword(String input) { + if (org.apache.commons.lang3.StringUtils.isEmpty(input)) { + return ""; + } + input = extractMultilineComment(input); + Matcher matcher = endingKeywordPattern.matcher(input); + if (matcher.find()) { + return matcher.group(2); + } + return ""; + } + + //写一个方法,输入一个字符串,判断是否是多行注释,如果是多行注释,请把注释符号全去掉,只返回注释文本 + public static String extractMultilineComment(String input) { + if (input == null || !input.startsWith("/*") || !input.endsWith("*/")) { + return input; + } + return input.substring(2, input.length() - 2).replaceAll("\\*", "").trim(); + } + + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/TeslaConfigurable.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/TeslaConfigurable.java similarity index 71% rename from athena-all/src/main/java/run/mone/m78/ip/common/TeslaConfigurable.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/TeslaConfigurable.java index 74d2a66a3..635887dba 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/TeslaConfigurable.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/TeslaConfigurable.java @@ -14,19 +14,20 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.google.gson.Gson; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.SearchableConfigurable; -import run.mone.m78.ip.bo.TeslaPluginConfig; -import run.mone.m78.ip.ui.ConfigUi; +import com.xiaomi.youpin.tesla.ip.bo.TeslaPluginConfig; +import com.xiaomi.youpin.tesla.ip.ui.ConfigUi; import org.apache.commons.lang3.mutable.MutableBoolean; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.listener.bo.CompletionEnum; import javax.swing.*; import java.util.ArrayList; @@ -74,7 +75,6 @@ public boolean isModified() { public void apply() { TeslaPluginConfig config = new TeslaPluginConfig(); String oldServer = config.getDashServer(); - config.setDashServer(configUi.getDashServerTextField().getText()); if (null != config.getDashServer() && (null == oldServer || !config.getDashServer().equals(oldServer))) { Safe.run(() -> { if (null != AthenaContext.ins().getAthenaTreeKeyAdapter()) { @@ -82,20 +82,26 @@ public void apply() { } }); } - config.setNickName(configUi.getNickNameTextField().getText()); config.setzToken(configUi.getzTokenPassword().getText().trim()); - config.setAiProxy(configUi.getAiProxyTextField().getText().trim()); - if (configUi.getModelComboBox().getModel().getSize() > 0 && null != configUi.getModelComboBox().getSelectedItem()) { - config.setModel(configUi.getModelComboBox().getSelectedItem().toString()); + // 聊天模型的设置 + if (configUi.getChatModelComboBox().getModel().getSize() > 0 && null != configUi.getChatModelComboBox().getSelectedItem()) { + config.setModel(configUi.getChatModelComboBox().getSelectedItem().toString()); AthenaContext.ins().setGptModel(config.getModel()); } - ComboBoxModel model = configUi.getModelComboBox().getModel(); + // 非聊天模型的设置 + if (configUi.getNoChatModelComboBox().getModel().getSize() > 0 && null != configUi.getNoChatModelComboBox().getSelectedItem()) { + config.setNoChatModel(configUi.getNoChatModelComboBox().getSelectedItem().toString()); + AthenaContext.ins().setNoChatModel(config.getNoChatModel()); + } + ComboBoxModel model = configUi.getChatModelComboBox().getModel(); List list = new ArrayList<>(); for (int i = 0; i < model.getSize(); i++) { list.add(model.getElementAt(i).toString()); } config.setModelList(list); - PropertiesComponent.getInstance().setValue("", new Gson().toJson(config)); + ComboBoxModel completionMode = configUi.getCompletionMode().getModel(); + config.setCompletionMode(CompletionEnum.getTypeEnumByDesc(completionMode.getSelectedItem().toString())); + PropertiesComponent.getInstance().setValue("tesla_plugin_token", new Gson().toJson(config)); configUi.getModified().setValue(false); new Thread(Prompt::flush).start(); diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/UltramanEvent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanEvent.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/common/UltramanEvent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanEvent.java index 563b88143..10ebb2223 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/UltramanEvent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/UltramanNotifier.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanNotifier.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/common/UltramanNotifier.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanNotifier.java index fa09a69a2..6437c5703 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/common/UltramanNotifier.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/UltramanNotifier.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.common; +package com.xiaomi.youpin.tesla.ip.common; import com.intellij.util.messages.Topic; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/VersionUtil.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/VersionUtil.java new file mode 100644 index 000000000..0c7c9ca46 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/common/VersionUtil.java @@ -0,0 +1,80 @@ +/* + * Copyright 2020 Xiaomi + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.xiaomi.youpin.tesla.ip.common; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * @author shanwb + * @date 2024-06-18 + */ +public class VersionUtil { + + private static final String PLUGIN_VERSION_KEY = "pluginVersion"; + + public static volatile String ATHENA_VERSION = null; + + public static volatile String MINI_ATHENA_VERSION = "2025.06.13.1"; + + //读取src/main/resources/athena.properties文件中的pluginVersion属性,注意在jar环境下也能正确读取到(method) + public static String getAthenaPluginVersion() { + if (null == ATHENA_VERSION) { + synchronized (VersionUtil.class) { + if (null == ATHENA_VERSION) { // Double-checked locking + Properties properties = new Properties(); + try (final InputStream inputStream = VersionUtil.class.getResourceAsStream("/athena.properties");) { + if (inputStream != null) { + properties.load(inputStream); + ATHENA_VERSION = properties.getProperty("pluginVersion"); + } else { + throw new IOException("Athena properties file not found"); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + } + } + + return ATHENA_VERSION; + } + + //判断两个版本字符串 谁的版本更新, 版本字符串都是类似这样子的格式:2024.06.18.1 (method) + public static int compareVersions(String version1, String version2) { + String[] parts1 = version1.split("\\."); + String[] parts2 = version2.split("\\."); + + int length = Math.max(parts1.length, parts2.length); + for (int i = 0; i < length; i++) { + int v1 = i < parts1.length ? Integer.parseInt(parts1[i]) : 0; + int v2 = i < parts2.length ? Integer.parseInt(parts2[i]) : 0; + if (v1 != v2) { + return v1 - v2; + } + } + return 0; + } + + public static boolean isVersionNeedUpgrades() { + return compareVersions(getAthenaPluginVersion(), MINI_ATHENA_VERSION) >= 0; + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/ChatComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/ChatComponent.java similarity index 90% rename from athena-all/src/main/java/run/mone/m78/ip/component/ChatComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/ChatComponent.java index 5d3b09dd9..64771e3b3 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/ChatComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/ChatComponent.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.ChatUi; +import com.xiaomi.youpin.tesla.ip.ui.BuildUi; +import com.xiaomi.youpin.tesla.ip.ui.ChatUi; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/CreateProjectComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateProjectComponent.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/component/CreateProjectComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateProjectComponent.java index 75385dd22..e8179ac27 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/CreateProjectComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateProjectComponent.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.CodeGeneratorUi; +import com.xiaomi.youpin.tesla.ip.ui.CodeGeneratorUi; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/CreateSpringBootProjectComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateSpringBootProjectComponent.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/component/CreateSpringBootProjectComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateSpringBootProjectComponent.java index 11fecba86..cb48e6464 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/CreateSpringBootProjectComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/CreateSpringBootProjectComponent.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.SpringBootProGenerator; +import com.xiaomi.youpin.tesla.ip.ui.CodeGeneratorUi; +import com.xiaomi.youpin.tesla.ip.ui.SpringBootProGenerator; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/FilterComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/FilterComponent.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/component/FilterComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/FilterComponent.java index 2cf797090..39fc83d61 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/FilterComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/FilterComponent.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.FilterUi; +import com.xiaomi.youpin.tesla.ip.ui.FilterUi; public class FilterComponent implements ApplicationComponent { diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/NaviComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/NaviComponent.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/component/NaviComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/NaviComponent.java index bcc8eaae9..3366efc7b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/NaviComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/NaviComponent.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.NaviUi; +import com.xiaomi.youpin.tesla.ip.ui.ChatUi; +import com.xiaomi.youpin.tesla.ip.ui.NaviUi; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/PluginComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/PluginComponent.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/component/PluginComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/PluginComponent.java index c2d307e63..6b2006452 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/PluginComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/PluginComponent.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.BuildUi; +import com.xiaomi.youpin.tesla.ip.ui.BuildUi; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/TeslaAppComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/TeslaAppComponent.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/component/TeslaAppComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/TeslaAppComponent.java index 8d0233f94..cb8b11a43 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/TeslaAppComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/TeslaAppComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -40,13 +40,13 @@ import com.intellij.util.Consumer; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.common.*; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.UltramanService; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; -import run.mone.m78.ip.bo.*; -import run.mone.m78.ip.common.*; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.service.UltramanService; -import run.mone.m78.ip.util.ProjectUtils; import run.mone.ultraman.bo.ParamsInfo; import run.mone.ultraman.event.AthenaEventBus; import run.mone.ultraman.listener.AthenaFileDocumentManagerListener; @@ -54,6 +54,7 @@ import run.mone.ultraman.listener.AthenaMessageListenerImpl; import run.mone.ultraman.service.AutoFlushBizService; +import java.net.URI; import java.util.*; import java.util.stream.Collectors; diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/VersionComponent.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/VersionComponent.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/component/VersionComponent.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/VersionComponent.java index 65a4b34e3..bba4fa8db 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/VersionComponent.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/VersionComponent.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package run.mone.m78.ip.component; +package com.xiaomi.youpin.tesla.ip.component; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.VersionUi; +import com.xiaomi.youpin.tesla.ip.ui.VersionUi; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaProjectComment.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaProjectComment.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaProjectComment.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaProjectComment.java index a3791e924..6fcc464c9 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaProjectComment.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaProjectComment.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.component.project; +package com.xiaomi.youpin.tesla.ip.component.project; import com.intellij.ide.projectView.ProjectView; @@ -6,7 +6,7 @@ import com.intellij.ide.projectView.impl.ProjectViewTree; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; import org.jetbrains.annotations.NotNull; import javax.swing.tree.TreePath; diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaTreeSelectionListener.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaTreeSelectionListener.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaTreeSelectionListener.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaTreeSelectionListener.java index e91669c28..1b7c69f2a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/component/project/AthenaTreeSelectionListener.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/component/project/AthenaTreeSelectionListener.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.component.project; +package com.xiaomi.youpin.tesla.ip.component.project; import com.intellij.ide.projectView.impl.nodes.ClassTreeNode; import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; @@ -6,7 +6,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiPackage; -import run.mone.m78.ip.bo.ClassInfo; +import com.xiaomi.youpin.tesla.ip.bo.ClassInfo; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; import run.mone.ultraman.bo.PackageInfo; diff --git a/athena-all/src/main/java/run/mone/m78/ip/consumer/CodeConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/CodeConsumer.java similarity index 58% rename from athena-all/src/main/java/run/mone/m78/ip/consumer/CodeConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/CodeConsumer.java index f0a9cb23a..c69090dda 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/consumer/CodeConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/CodeConsumer.java @@ -1,10 +1,11 @@ -package run.mone.m78.ip.consumer; +package com.xiaomi.youpin.tesla.ip.consumer; import com.intellij.openapi.editor.Editor; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.service.CodeService; /** * @author goodjava@qq.com @@ -28,6 +29,7 @@ public void onEvent(AiMessage message) { @Override public void end(AiMessage message) { +// NotificationCenter.notice(com.xiaomi.youpin.tesla.ip.bo.Message.finishMsg); } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/consumer/FinishConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/FinishConsumer.java similarity index 77% rename from athena-all/src/main/java/run/mone/m78/ip/consumer/FinishConsumer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/FinishConsumer.java index cabfdf786..35fcc1df4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/consumer/FinishConsumer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/consumer/FinishConsumer.java @@ -1,7 +1,7 @@ -package run.mone.m78.ip.consumer; +package com.xiaomi.youpin.tesla.ip.consumer; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/AthenaTableCellEditor.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/AthenaTableCellEditor.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/AthenaTableCellEditor.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/AthenaTableCellEditor.java index 37012557f..9886f7e10 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/AthenaTableCellEditor.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/AthenaTableCellEditor.java @@ -1,18 +1,18 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.google.common.base.Joiner; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import run.mone.m78.ip.bo.ClassInfo; -import run.mone.m78.ip.bo.CreateClassRes; -import run.mone.m78.ip.bo.Message; -import run.mone.m78.ip.bo.prompt.PromptParamType; -import run.mone.m78.ip.ui.CreateClassUi; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.bo.prompt.PromptParam; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.bo.ClassInfo; +import com.xiaomi.youpin.tesla.ip.bo.CreateClassRes; +import com.xiaomi.youpin.tesla.ip.bo.Message; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParam; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParamType; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.ui.CreateClassUi; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; import lombok.Setter; import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.bo.PackageInfo; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/ChromeDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ChromeDialog.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/ChromeDialog.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ChromeDialog.java index b92f973f6..5b0e2c7e7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/ChromeDialog.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ChromeDialog.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; @@ -7,8 +7,8 @@ import com.intellij.ui.jcef.JBCefApp; import com.intellij.ui.jcef.JBCefBrowser; import com.intellij.ui.jcef.JBCefClient; -import run.mone.m78.ip.listener.ChromeMessageRouterHandler; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.listener.ChromeMessageRouterHandler; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; import org.cef.browser.CefMessageRouter; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogContext.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogContext.java similarity index 81% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/DialogContext.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogContext.java index d968f744f..17a8f8933 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogContext.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogContext.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.intellij.openapi.module.Module; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogReq.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogReq.java similarity index 90% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/DialogReq.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogReq.java index 037dbea20..d1ee6726b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogReq.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogReq.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.intellij.openapi.module.Module; import lombok.Builder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogResult.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogResult.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/DialogResult.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogResult.java index 3c03070ff..149d0e162 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/DialogResult.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DialogResult.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/DirectoryTreeDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DirectoryTreeDialog.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/DirectoryTreeDialog.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DirectoryTreeDialog.java index 7df5af0f8..a8fa09849 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/DirectoryTreeDialog.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/DirectoryTreeDialog.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.intellij.icons.AllIcons; import com.intellij.ide.util.treeView.NodeRenderer; @@ -8,8 +8,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.treeStructure.Tree; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/MarkdownDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/MarkdownDialog.java new file mode 100644 index 000000000..de437857b --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/MarkdownDialog.java @@ -0,0 +1,203 @@ +//package com.xiaomi.youpin.tesla.ip.dialog; +// +//import com.google.common.collect.Lists; +//import com.intellij.openapi.application.ApplicationManager; +//import com.intellij.openapi.editor.Document; +//import com.intellij.openapi.editor.Editor; +//import com.intellij.openapi.editor.EditorFactory; +//import com.intellij.openapi.editor.event.DocumentEvent; +//import com.intellij.openapi.editor.event.DocumentListener; +//import com.intellij.openapi.fileTypes.FileType; +//import com.intellij.openapi.fileTypes.FileTypeManager; +//import com.intellij.openapi.project.Project; +//import com.intellij.openapi.ui.DialogWrapper; +//import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension; +//import com.vladsch.flexmark.ext.tables.TablesExtension; +//import com.vladsch.flexmark.ext.toc.TocExtension; +//import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension; +//import com.vladsch.flexmark.html.HtmlRenderer; +//import com.vladsch.flexmark.parser.Parser; +//import com.vladsch.flexmark.util.ast.Node; +//import com.vladsch.flexmark.util.data.MutableDataSet; +//import lombok.Getter; +// +//import javax.swing.*; +//import java.awt.*; +//import java.awt.datatransfer.Clipboard; +//import java.awt.datatransfer.StringSelection; +//import java.io.BufferedWriter; +//import java.io.File; +//import java.io.FileWriter; +//import java.io.IOException; +//import java.util.Arrays; +// +///** +// * @author goodjava@qq.com +// * @author caobaoyu +// * @date 2023/7/13 +// * 一个md编辑器的dialog +// */ +//public class MarkdownDialog extends DialogWrapper { +// private Project project; +// private JButton saveButton; +// private JButton copyButton; +// private Editor editor; +// private JFrame frame; +// @Getter +// private DialogResult dialogResult = new DialogResult(); +// +// +// public MarkdownDialog(Project project) { +// super(true); +// this.project = project; +// init(); +// setTitle("Athena Markdown Editor"); +// editor = createEditor(project); +// createButtons(); +// } +// +// @Override +// public void show() { +// if (editor != null) { +// JPanel editorPanel = new JPanel(new BorderLayout()); +// editorPanel.add(editor.getComponent(), BorderLayout.CENTER); +// editorPanel.setPreferredSize(new Dimension(800, 600)); +// // 添加Markdown预览 +// JEditorPane previewPane = new JEditorPane(); +// previewPane.setEditable(false); +// previewPane.setContentType("text/html"); +// JScrollPane previewScrollPane = new JScrollPane(previewPane); +// previewScrollPane.setPreferredSize(new Dimension(400, 600)); +// JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, editorPanel, previewScrollPane); +// splitPane.setResizeWeight(0.5); +// splitPane.setOneTouchExpandable(true); +// splitPane.setDividerSize(2); // 设置分隔条的宽度 +// +// JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); +// buttonPanel.add(copyButton); +// buttonPanel.add(saveButton); +// +// frame = new JFrame("Markdown Editor"); +// frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); +// frame.getContentPane().add(splitPane, BorderLayout.CENTER); +// frame.getContentPane().add(buttonPanel, BorderLayout.SOUTH); +// frame.pack(); +// frame.setVisible(true); +// // 更新Markdown预览 +// editor.getDocument().addDocumentListener(new DocumentListener() { +// @Override +// public void documentChanged(DocumentEvent event) { +// ApplicationManager.getApplication().runReadAction(() -> { +// String markdown = event.getDocument().getText(); +// MutableDataSet options = new MutableDataSet(); +// options.set(Parser.EXTENSIONS, Arrays.asList( +// TablesExtension.create(), +// TocExtension.create(), +// StrikethroughExtension.create(), +// WikiLinkExtension.create() +// )); +// Parser parser = Parser.builder(options).build(); +// Node document = parser.parse(markdown); +// HtmlRenderer renderer = HtmlRenderer.builder(options).build(); +// String html = renderer.render(document); +// previewPane.setText(html); +// }); +// } +// +// +// +// +// }); +// } +// } +// +// @Override +// protected JComponent createCenterPanel() { +// return new JPanel(new FlowLayout(FlowLayout.RIGHT)); +// } +// +// private Editor createEditor(Project project) { +// EditorFactory editorFactory = EditorFactory.getInstance(); +// Document document = EditorFactory.getInstance().createDocument("# Hello world"); +// final FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension("md"); +// Editor editor = editorFactory.createEditor(document, project, fileType, false); +// editor.getSettings().setLineNumbersShown(true); +// editor.getSettings().setFoldingOutlineShown(true); +// editor.getSettings().setAutoCodeFoldingEnabled(true); +// editor.getSettings().setAdditionalLinesCount(1); +// editor.getSettings().setAdditionalColumnsCount(1); +// editor.getSettings().setRightMarginShown(true); +// editor.getSettings().setRightMargin(80); +// editor.getSettings().setCaretRowShown(true); +// editor.getSettings().setUseSoftWraps(true); +// editor.getSettings().setSoftMargins(Lists.newArrayList(80)); +// editor.getSettings().setTabSize(4); +// editor.getSettings().setUseTabCharacter(false); +// +// return editor; +// } +// +// +// private void createButtons() { +// saveButton = new JButton("Save"); +// copyButton = new JButton("Copy"); +// +// saveButton.addActionListener(e -> onSaveButtonClick()); +// copyButton.addActionListener(e -> onCopyButtonClick()); +// } +// +// private void onSaveButtonClick() { +// JPanel panel = new JPanel(); +// String fileName = JOptionPane.showInputDialog(panel, "Enter file name:"); +// if (fileName != null && !fileName.trim().isEmpty()) { +// try { +// String path = project.getBaseDir().getPath() + "/" + fileName + ".md"; +// File file = new File(path); +// BufferedWriter writer = new BufferedWriter(new FileWriter(file)); +// String markdownContent = getMarkdownContent(); +// writer.write(markdownContent); +// writer.close(); +// putInfo(markdownContent); +// close(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// } +// +// private void onCopyButtonClick() { +// String markdownContent = getMarkdownContent(); +// if (!markdownContent.isEmpty()) { +// StringSelection selection = new StringSelection(markdownContent); +// Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); +// clipboard.setContents(selection, null); +// putInfo(markdownContent); +// close(); +// } +// +// } +// +// private String getMarkdownContent() { +// Editor editor = this.editor; +// if (editor != null) { +// Document document = editor.getDocument(); +// return document.getText(); +// } +// return ""; +// } +// +// public void close() { +// SwingUtilities.invokeLater(() -> { +// frame.dispose(); +// this.dispose(); +// }); +// } +// +// public void putInfo(String msg) { +// this.dialogResult.getData().put("text", msg); +// } +// +//} +// +// +// diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/ParamTableDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ParamTableDialog.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/ParamTableDialog.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ParamTableDialog.java index 22eff8871..1ef459f15 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/ParamTableDialog.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/ParamTableDialog.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -8,16 +8,17 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; -import run.mone.m78.ip.bo.ValueInfo; -import run.mone.m78.ip.bo.prompt.PromptParamType; -import run.mone.m78.ip.bo.ParamDialogReq; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.bo.prompt.PromptParam; -import run.mone.m78.ip.util.EditorUtils; -import run.mone.m78.ip.util.FileUtils; -import run.mone.m78.ip.util.ResourceUtils; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.bo.ParamDialogReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.ValueInfo; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParam; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParamType; +import com.xiaomi.youpin.tesla.ip.util.EditorUtils; +import com.xiaomi.youpin.tesla.ip.util.FileUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -80,7 +81,6 @@ public ParamTableDialog(ParamDialogReq req, @Nullable Project project, Map classList = ClassFinder.findClassList(project, type, name, moduleName); - classList.add(ClassInfo.builder().className("New").build()); + if (this.newClass) { + //class 支持new出来 + classList.add(ClassInfo.builder().className("New").build()); + } changeListModel(classList, "Class"); tabbedPane.setSelectedIndex(1); } if (selectedTab.equals("Class")) { if (req.getCmd().equals("test") || req.getCmd().equals("docean_controller")) { - String clazz = this.listMap.get("Class").getSelectedValue().getName(); + JBList list = this.listMap.get("Class"); + if (null == list || list.isEmpty()) { + return; + } + String clazz = list.getSelectedValue().getName(); this.result.getData().put("class", clazz); - PsiClass psiClass = CodeService.getPsiClass(project, context.getModule(), clazz); + //得用选中的selectModule,不然找不到class + PsiClass psiClass = CodeService.getPsiClass(project, ProjectUtils.getModuleWithName(project, selectModuleName), clazz); List methodList = new ArrayList<>(); if (null != psiClass) { + //查找所有public方法 methodList.addAll(CodeService.methods(psiClass).stream().map(it -> { MethodInfo mi = new MethodInfo(it); return mi; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/SelectModuleDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/SelectModuleDialog.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/SelectModuleDialog.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/SelectModuleDialog.java index 239af2565..3901cd908 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/SelectModuleDialog.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/SelectModuleDialog.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog; +package com.xiaomi.youpin.tesla.ip.dialog; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; diff --git a/athena-all/src/main/java/run/mone/m78/ip/dialog/bo/CellValue.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/bo/CellValue.java similarity index 87% rename from athena-all/src/main/java/run/mone/m78/ip/dialog/bo/CellValue.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/bo/CellValue.java index dc30a4d99..db6220cb7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/dialog/bo/CellValue.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/dialog/bo/CellValue.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.dialog.bo; +package com.xiaomi.youpin.tesla.ip.dialog.bo; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/enums/InvokePromptEnums.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/InvokePromptEnums.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/enums/InvokePromptEnums.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/InvokePromptEnums.java index 870bfda9e..e577c7d50 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/enums/InvokePromptEnums.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/InvokePromptEnums.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.enums; +package com.xiaomi.youpin.tesla.ip.enums; import lombok.Getter; diff --git a/athena-all/src/main/java/run/mone/m78/ip/enums/ZTagEnums.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTagEnums.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/enums/ZTagEnums.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTagEnums.java index e7c2cb864..3dac14fef 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/enums/ZTagEnums.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTagEnums.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.enums; +package com.xiaomi.youpin.tesla.ip.enums; import lombok.Getter; diff --git a/athena-all/src/main/java/run/mone/m78/ip/enums/ZTypeEnums.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTypeEnums.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/enums/ZTypeEnums.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTypeEnums.java index 1e813b132..838048ebb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/enums/ZTypeEnums.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/enums/ZTypeEnums.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.enums; +package com.xiaomi.youpin.tesla.ip.enums; /** * @author caobaoyu diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/framework/flex/Flex.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/framework/flex/Flex.java new file mode 100644 index 000000000..1d041cae5 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/framework/flex/Flex.java @@ -0,0 +1,72 @@ +package com.xiaomi.youpin.tesla.ip.framework.flex; + +import com.intellij.psi.*; +import org.apache.commons.lang3.tuple.Pair; + +/** + * @author goodjava@qq.com + * @date 2024/1/29 13:53 + *

+ * 对mybatis flex 框架的一个适配 + */ +public class Flex { + + //获取ServiceImpl中的第二个泛型(也就是数据库中对应的类) + public static String findAndProcessServiceImplWithGeneric(PsiClass psiClass) { + PsiReferenceList extendsList = psiClass.getExtendsList(); + if (extendsList != null) { + for (PsiJavaCodeReferenceElement referenceElement : extendsList.getReferenceElements()) { + PsiClass superClass = (PsiClass) referenceElement.resolve(); + if (superClass != null && "ServiceImpl".equals(superClass.getName())) { + // 获取泛型参数 + PsiReferenceParameterList parameterList = referenceElement.getParameterList(); + if (parameterList != null) { + PsiType[] typeArguments = parameterList.getTypeArguments(); + if (typeArguments.length == 2) { + PsiType secondTypeArgument = typeArguments[1]; + if (secondTypeArgument instanceof PsiClassType) { + PsiClassType classType = (PsiClassType) secondTypeArgument; + PsiClass pc = classType.resolve(); + if (pc != null) { + return pc.getText(); + } + } + } + } + } + } + } + return ""; + } + + + //public interface E extends BaseMapper (获取到L) + public static Pair getBaseMapperGenericTypeNameAndText(PsiClass psiClass) { + PsiReferenceList extendsList = psiClass.getExtendsList(); + if (extendsList != null) { + for (PsiJavaCodeReferenceElement referenceElement : extendsList.getReferenceElements()) { + PsiElement resolved = referenceElement.resolve(); + if (resolved instanceof PsiClass) { + PsiClass baseMapperInterface = (PsiClass) resolved; + // 检查是否是 BaseMapper 接口 + if ("BaseMapper".equals(baseMapperInterface.getName())) { + // 获取 BaseMapper 接口的泛型参数 + PsiType[] typeArguments = referenceElement.getTypeParameters(); + if (typeArguments.length == 1) { + PsiType typeArgument = typeArguments[0]; + if (typeArgument instanceof PsiClassType) { + PsiClassType classTypeArgument = (PsiClassType) typeArgument; + PsiClass poClass = classTypeArgument.resolve(); + if (poClass != null) { + return Pair.of(poClass.getQualifiedName(), poClass.getText()); + } + } + } + } + } + } + } + return Pair.of("", ""); + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/generator/ClassGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/ClassGenerator.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/generator/ClassGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/ClassGenerator.java index 85a51a6e7..0116496d1 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/generator/ClassGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/ClassGenerator.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package run.mone.m78.ip.generator; +package com.xiaomi.youpin.tesla.ip.generator; -import run.mone.m78.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; import java.io.File; import java.util.Map; diff --git a/athena-all/src/main/java/run/mone/m78/ip/generator/DirectoryGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/DirectoryGenerator.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/generator/DirectoryGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/DirectoryGenerator.java index 0926d1bb1..96cb2398f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/generator/DirectoryGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/DirectoryGenerator.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package run.mone.m78.ip.generator; +package com.xiaomi.youpin.tesla.ip.generator; -import run.mone.m78.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; import java.io.File; diff --git a/athena-all/src/main/java/run/mone/m78/ip/generator/FileGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/FileGenerator.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/generator/FileGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/FileGenerator.java index c61fe7994..991a073f5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/generator/FileGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/FileGenerator.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package run.mone.m78.ip.generator; +package com.xiaomi.youpin.tesla.ip.generator; -import run.mone.m78.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; import java.io.File; +import java.util.HashMap; import java.util.Map; /** diff --git a/athena-all/src/main/java/run/mone/m78/ip/generator/PackageGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PackageGenerator.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/generator/PackageGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PackageGenerator.java index 1f4bc4234..bb20a6d95 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/generator/PackageGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PackageGenerator.java @@ -14,9 +14,12 @@ * limitations under the License. */ -package run.mone.m78.ip.generator; +package com.xiaomi.youpin.tesla.ip.generator; -import run.mone.m78.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; + +import java.util.HashMap; +import java.util.Map; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/m78/ip/generator/PomGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PomGenerator.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/generator/PomGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PomGenerator.java index 45a82b968..f99ee4f0e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/generator/PomGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/generator/PomGenerator.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package run.mone.m78.ip.generator; +package com.xiaomi.youpin.tesla.ip.generator; -import run.mone.m78.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; import java.io.File; import java.util.Map; diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/ChromeMessageRouterHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/ChromeMessageRouterHandler.java similarity index 57% rename from athena-all/src/main/java/run/mone/m78/ip/listener/ChromeMessageRouterHandler.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/ChromeMessageRouterHandler.java index 8a5f90044..5bfd910ca 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/ChromeMessageRouterHandler.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/ChromeMessageRouterHandler.java @@ -14,54 +14,47 @@ * limitations under the License. */ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; -import cn.hutool.core.bean.BeanUtil; -import com.google.common.base.Splitter; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.newvfs.RefreshQueue; +import com.xiaomi.youpin.tesla.ip.bo.Action; +import com.xiaomi.youpin.tesla.ip.bo.AiCodePromptRes; +import com.xiaomi.youpin.tesla.ip.bo.AiCodeRes; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.ProjectModuleInfo; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.ServerInfo; +import com.xiaomi.youpin.tesla.ip.common.ConfigCenter; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.JavaClassUtils; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.enums.InvokePromptEnums; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.GuideService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.mutable.Mutable; -import org.apache.commons.lang3.mutable.MutableInt; -import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.tuple.Pair; import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; import org.cef.callback.CefQueryCallback; import org.cef.handler.CefMessageRouterHandlerAdapter; -import org.jetbrains.annotations.Nullable; -import run.mone.m78.ip.bo.*; -import run.mone.m78.ip.bo.z.EmbeddingStatus; -import run.mone.m78.ip.common.*; -import run.mone.m78.ip.enums.InvokePromptEnums; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.service.PromptService; -import run.mone.m78.ip.service.RobotService; -import run.mone.m78.ip.service.ScriptService; -import run.mone.m78.ip.ui.VersionUi; -import run.mone.m78.ip.util.LabelUtils; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.m78.ip.util.ResourceUtils; -import run.mone.m78.ip.util.UltramanConsole; import run.mone.ultraman.AthenaContext; -import run.mone.ultraman.bo.CodeReq; -import run.mone.ultraman.bo.Version; +import run.mone.ultraman.common.CodeUtils; import run.mone.ultraman.common.SafeRun; -import run.mone.ultraman.service.AthenaCodeService; -import run.mone.ultraman.service.ModuleService; -import run.mone.ultraman.state.ProjectFsmManager; -import java.io.File; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -125,12 +118,15 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String return true; } + // 从右侧聊天框插入代码到左侧代码编辑区 if (req.getCmd().equals("idea_insert_code")) { log.info("idea insert code"); String code = req.getData().get("code"); ApplicationManager.getApplication().invokeLater(() -> { CodeService.insertCode(project, code); }); + // 代码统计 + CodeUtils.uploadCodeGenInfo(Action.INSERT_CODE_FROM_CHAT.getCode(), code, "", project); } //调用miapi 这里需要拿到用户的key @@ -145,6 +141,10 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String res = key; } + if (req.getCmd().equals("user")) { + res = AthenaContext.ins().getUserName(); + } + //获取http服务器信息和一些ide信息 if (req.getCmd().equals("server_info")) { res = this.getServerInfo(req); @@ -191,9 +191,9 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String res = gson.toJson(ConfigCenter.getGuide()); } - //ai导航信息(上传代码的调用也再这里) + //ai导航信息(上传代码的调用也再这里):?就能开始调用的服务,主要用来测试 if (req.getCmd().equals("ai_guide")) { - res = this.aiGuide(req); + res = GuideService.aiGuide(req, this.project); } @@ -352,196 +352,6 @@ private String getAiCodePrompt() { return sb.toString(); } - /** - * AI引导方法,根据请求参数中的问题,获取相应的提示信息列表 - * - * @param req 请求参数对象,包含问题信息 - * @return 返回提示信息列表的JSON字符串 - */ - private String aiGuide(Req req) { - AiCodeRes res = new AiCodeRes(); - String question = req.getData().get("question"); - if (question.equals("flush")) { - Prompt.flush(); - res.setMsg("flush success"); - return gson.toJson(res); - } - - if (question.startsWith("invoke_code:")) { - List list = Splitter.on(":").splitToList(question); - if (list.size() == 4) { - String codeName = list.get(1); - String method = list.get(2); - String param = list.get(3); - Object codeRes = ScriptService.ins().invoke(ScriptService.getScript(codeName), method, Maps.newHashMap(), param); - res.setMsg("invoke code success:" + codeRes); - } else { - res.setMsg(list + " list size != 4"); - } - return gson.toJson(res); - } - - if (question.startsWith("model")) { - List list = Splitter.on(":").splitToList(question); - if (list.size() == 2) { - AthenaContext.ins().setGptModel(list.get(1)); - res.setMsg("set model success model:" + list.get(1)); - } - return gson.toJson(res); - } - - if (question.startsWith("aidebug")) { - List list = Splitter.on(":").splitToList(question); - if (list.size() == 2) { - AthenaContext.ins().setDebugAiProxy(Boolean.valueOf(list.get(1))); - res.setMsg("ai debug:" + list.get(1)); - } - return gson.toJson(res); - } - - if (question.equals("refreshconfig")) { - ResourceUtils.getAthenaConfig(this.project, true); - res.setMsg("refresh config success"); - return gson.toJson(res); - } - - //获取作者信息 - if (question.equals("author")) { - return author(res); - } - - if (question.startsWith("troubleshoot")) { - RobotService.troubleshoot(null, RobotReq.builder().project(this.project).param(question).build()); - return ""; - } - - //获取embedding 信息 - if (question.equals("embedding_status")) { - return embeddingStatus(req, res); - } - - //打开配置 - if (question.equals("config")) { - ApplicationManager.getApplication().invokeLater(() -> LabelUtils.showLabelConfigUi(this.project)); - res.setMsg("show config success"); - return gson.toJson(res); - } - - if (question.equals("collected")) { - res.setMsg(" "); - res.setPromptInfoList(buildAiCodePromptRes(Prompt.getCollected())); - return gson.toJson(res); - } - - if (question.equals("debug")) { - res.setMsg(new Version().toString()); - return gson.toJson(res); - } - - //刷新业务代码到知识库 - if (question.equals("flush_biz")) { - return flushBizCode(req, res); - } - - if (question.equals("class_len")) { - return getClassLen(res); - } - - //停止状态机 - if (question.equals("stop")) { - ProjectFsmManager.stop(project.getName()); - res.setMsg("退出状态机"); - return gson.toJson(res); - } - - //查询状态机状态 - if (question.equals("state")) { - String state = ProjectFsmManager.state(project.getName()); - res.setMsg("state:" + state); - return gson.toJson(res); - } - - AiCodeRes cache = ConfigCenter.build(question); - if (null == cache) { - res.setMsg(Message.unsupportedCommand); - return gson.toJson(res); - } - res.setMsg(cache.getMsg()); - if (!"help".equals(question)) { - List promptRes = Lists.newArrayList(); - List promptList = Prompt.getPromptInfoByTag(cache.getTagName()); - promptRes.addAll(cache.getPromptInfoList()); - promptRes.addAll(buildAiCodePromptRes(promptList)); - res.setPromptInfoList(promptRes); - } else { - res.setPromptInfoList(cache.getPromptInfoList()); - } - return gson.toJson(res); - } - - private String embeddingStatus(Req req, AiCodeRes res) { - String scope = req.getData().getOrDefault("scope", "project"); - CodeReq.CodeReqBuilder builder = CodeReq.builder(); - builder.projectName(this.project.getName()); - if (!scope.equals("project")) { - builder.moduleName(getModule(req.getData().get("module")).getName()); - } - EmbeddingStatus status = AthenaCodeService.embeddingStatus(builder.build()); - String msg = scope.equals("project") ? ("project_" + req.getData().get("project")) : ("module_" + req.getData().get("module")); - res.setMsg(gson.toJson(status) + ":" + msg); - return gson.toJson(res); - } - - //刷新业务代码到知识库 - private String flushBizCode(Req req, AiCodeRes res) { - String moduleName = req.getData().get("module"); - String scope = req.getData().get("scope"); - ApplicationManager.getApplication().invokeLater(() -> { - if ("project".equals(scope)) { - //Refresh all modules. - List list = ProjectUtils.listAllModules(this.project).stream().filter(it -> !it.equals(req.getData().get("project"))).collect(Collectors.toList()); - list.stream().forEach(it -> ModuleService.uploadModelText(this.project, getModule(it))); - } else { - ModuleService.uploadModelText(this.project, getModule(moduleName)); - } - }); - res.setMsg("flush biz success"); - return gson.toJson(res); - } - - //获取当前打开类的长度 - private String getClassLen(AiCodeRes res) { - MutableInt num = new MutableInt(); - ApplicationManager.getApplication().invokeAndWait(() -> { - String text = CodeService.getClassText(this.project); - num.setValue(text.length()); - }); - res.setMsg(String.valueOf(num.getValue())); - return gson.toJson(res); - } - - //获取作者信息 - private String author(AiCodeRes res) { - ApplicationManager.getApplication().invokeLater(() -> { - VersionUi versionUi = new VersionUi(); - versionUi.show(); - }); - res.setMsg(new Version().toString()); - return gson.toJson(res); - } - - @Nullable - private Module getModule(String moduleName) { - if (StringUtils.isEmpty(moduleName)) { - Mutable mutable = new MutableObject<>(); - ApplicationManager.getApplication().invokeAndWait(() -> { - mutable.setValue(ProjectUtils.getCurrentModule(this.project)); - }); - return mutable.getValue(); - } else { - return ProjectUtils.getModuleWithName(this.project, moduleName); - } - } /** * 获取项目信息并以JSON格式返回。 @@ -563,21 +373,4 @@ public void onQueryCanceled(CefBrowser browser, CefFrame frame, long query_id) { } - private void refreshProject(String targetExtractionDir) { - VirtualFile targetFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(targetExtractionDir)); - RefreshQueue.getInstance().refresh(false, true, null, targetFile); - } - - private List buildAiCodePromptRes(List promptInfoList) { - List list = promptInfoList.stream().filter(p -> p.getTags().stream().anyMatch(tag -> tag.getName().equals("plugin"))).map(promptInfo -> { - AiCodePromptRes promptRes = new AiCodePromptRes(); - BeanUtil.copyProperties(promptInfo, promptRes); - promptRes.setType("cmd"); - promptRes.setShowDialog(promptInfo.getLabels().getOrDefault("showDialog", "false")); - return promptRes; - }).collect(Collectors.toList()); - return list; - } - - } diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/DevToolsDialog.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/DevToolsDialog.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/listener/DevToolsDialog.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/DevToolsDialog.java index da292ec0b..1d564377e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/DevToolsDialog.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/DevToolsDialog.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import org.cef.browser.CefBrowser; diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/LocalHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/LocalHandler.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/listener/LocalHandler.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/LocalHandler.java index c67b1cbcd..7a0ced87c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/LocalHandler.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/LocalHandler.java @@ -1,14 +1,14 @@ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.LocalReq; +import com.xiaomi.youpin.tesla.ip.bo.robot.*; +import com.xiaomi.youpin.tesla.ip.service.LocalAiService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import run.mone.m78.ip.bo.chatgpt.LocalReq; -import run.mone.m78.ip.bo.robot.*; -import run.mone.m78.ip.service.LocalAiService; import run.mone.ultraman.AthenaContext; import run.mone.ultraman.bo.ClientData; import run.mone.ultraman.common.GsonUtils; diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/MenuHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/MenuHandler.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/listener/MenuHandler.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/MenuHandler.java index dc65e5891..0abec178e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/MenuHandler.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/MenuHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/OpenAiListener.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/OpenAiListener.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/listener/OpenAiListener.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/OpenAiListener.java index 0acdec9fc..e77b3693c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/OpenAiListener.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/OpenAiListener.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/PromptHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/PromptHandler.java new file mode 100644 index 000000000..36b25d9fa --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/PromptHandler.java @@ -0,0 +1,127 @@ +package com.xiaomi.youpin.tesla.ip.listener; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.LocalAiService; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.MutableObject; +import run.mone.ultraman.manager.ConsoleViewManager; +import run.mone.ultraman.service.AiCodeService; +import run.mone.ultraman.state.ProjectFsmManager; + +import java.util.UUID; + +/** + * @author goodjava@qq.com + * @date 2023/12/10 16:01 + */ +public class PromptHandler { + + + //修改用户的问题 + public static String handler(Project project, Req req) { + if (req.getCmd().equals("modifyPrompt")) { + String prompt = req.getData().get("prompt"); + MutableObject r = new MutableObject<>(); + r.setValue(prompt); + changePrompt(project, prompt, r, req); + return r.getValue(); + } + return ""; + } + + //根据给定的提示更改提示信息,并在需要的情况下生成代码 + private static void changePrompt(Project project, String prompt, MutableObject r, Req req) { + //如果有长问答,长问答的优先级要更高 + if (!prompt.startsWith("?")) { + boolean process = ProjectFsmManager.processMsg(project.getName(), prompt); + if (process) { + r.setValue("?$$$" + prompt); + return; + } + } else { + r.setValue(prompt); + return; + } + + //机器人指令 + if (prompt.startsWith(">>")) { + String cmd = prompt.substring(2); + VisionHandler.callBot(project, cmd); + r.setValue("?$$$" + cmd); + return; + } + + + //直接生成业务代码 + if (prompt.startsWith("//")) { + removeSelection(project); + AiCodeService.generateBizCode(req.getData().get("scope"), project, prompt); + String message = prompt.substring(2); + ProjectAiMessageManager.getInstance().appendMsg(project, AiChatMessage.builder().id(UUID.randomUUID().toString()).role(Role.user).message(message).data(message).build()); + //返回这种协议开头的,前端就不在问chatgpt了,只做显示 + r.setValue("?$$$" + message); + return; + } + + + ApplicationManager.getApplication().invokeAndWait(() -> { + Editor editor = CodeService.getEditor(project); + if (null != editor) { + r.setValue(prompt); + + //直接本地问chatgpt + if (prompt.startsWith("::")) { + removeSelection(project); + String newPrompt = prompt.substring(2); + LocalAiService.localCall(project, newPrompt); + //返回这种协议开头的,前端就不在问chatgpt了,只做显示 + r.setValue("?$$$" + newPrompt); + } + + + if (ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_SELECT_TEXT, "true").equals("true")) { + //选中编辑器中的文本 + if (CodeService.isTextSelected(editor)) { + SelectionModel selectionModel = editor.getSelectionModel(); + String selectedText = selectionModel.getSelectedText(); + StringBuilder sb = new StringBuilder(prompt); + sb.append("\n```\n" + selectedText + "\n```\n"); + r.setValue(sb.toString()); + } + + //选中Console中的文本 + String text = ConsoleViewManager.getSelectedText(project); + if (StringUtils.isNotEmpty(text)) { + StringBuilder sb = new StringBuilder(prompt); + sb.append("\n```\n" + text + "\n```\n"); + r.setValue(sb.toString()); + } + } + + } + }); + + + } + + + //移除选择 + private static void removeSelection(Project project) { + ApplicationManager.getApplication().invokeAndWait(() -> { + Editor editor = CodeService.getEditor(project); + if (null != editor) { + editor.getSelectionModel().removeSelection(); + } + }); + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/Req.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/Req.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/listener/Req.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/Req.java index 216d9e3df..aadeb79d3 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/Req.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/Req.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import java.util.Map; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/RequestHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/RequestHandler.java new file mode 100644 index 000000000..fad9220c9 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/RequestHandler.java @@ -0,0 +1,21 @@ +package com.xiaomi.youpin.tesla.ip.listener; + +import org.cef.browser.CefBrowser; +import org.cef.handler.CefRequestHandlerAdapter; + +/** + * @author goodjava@qq.com + * @date 2023/11/22 18:40 + */ +public class RequestHandler extends CefRequestHandlerAdapter { + + +// @Override +// public void onPermissionRequest(CefBrowser browser, String origin_url, int permissionType, boolean isMainFrame, PermissionCallback callback) { +// if (permissionType == CefRequestHandler.PERMISSIONTYPE_MEDIASTREAM_MIC || permissionType == CefRequestHandler.PERMISSIONTYPE_MEDIASTREAM_CAMERA) { +// callback.Continue(true); +// } else { +// callback.Continue(false); +// } +// } +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/UltrmanTreeKeyAdapter.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/UltrmanTreeKeyAdapter.java similarity index 77% rename from athena-all/src/main/java/run/mone/m78/ip/listener/UltrmanTreeKeyAdapter.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/UltrmanTreeKeyAdapter.java index 031eebacc..c89037d8d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/UltrmanTreeKeyAdapter.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/UltrmanTreeKeyAdapter.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import com.google.gson.Gson; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; @@ -24,27 +25,27 @@ import com.intellij.ui.jcef.JBCefApp; import com.intellij.ui.jcef.JBCefBrowser; import com.intellij.ui.jcef.JBCefClient; -import run.mone.m78.ip.renderer.CustomIconRenderer; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.m78.ip.bo.SpiderUrl; -import run.mone.m78.ip.bo.TbTask; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.service.SpiderService; -import run.mone.m78.ip.service.TaskService; -import run.mone.m78.ip.service.UserService; -import run.mone.m78.ip.util.FileUtils; -import run.mone.m78.ip.util.UltramanConsole; +import com.xiaomi.youpin.tesla.ip.bo.SpiderUrl; +import com.xiaomi.youpin.tesla.ip.bo.TbTask; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.renderer.CustomIconRenderer; +import com.xiaomi.youpin.tesla.ip.service.SpiderService; +import com.xiaomi.youpin.tesla.ip.service.TaskService; +import com.xiaomi.youpin.tesla.ip.service.UserService; +import com.xiaomi.youpin.tesla.ip.util.FileUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.cef.CefClient; import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; import org.cef.browser.CefMessageRouter; -import org.cef.callback.CefContextMenuParams; -import org.cef.callback.CefMediaAccessCallback; -import org.cef.callback.CefMenuModel; -import org.cef.handler.CefContextMenuHandlerAdapter; -import org.cef.handler.CefLifeSpanHandlerAdapter; +import org.cef.callback.*; +import org.cef.handler.*; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -56,6 +57,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.stream.Collectors; @@ -123,6 +125,16 @@ public void loadMone(String apiUrl, String text) { return true; }); + if (System.getProperty("os.name").contains("Linux")) { + client.getCefClient().addDialogHandler((browser, mode, title, defaultFilePath, acceptFilters, callback) -> { + // TODO + String filePath = showFileChooserDialog(project); + acceptFilters.add(filePath); + callback.Continue(acceptFilters); + return true; + }); + } + client.addLifeSpanHandler(new CefLifeSpanHandlerAdapter() { @Override public boolean onBeforePopup(CefBrowser browser, CefFrame frame, String target_url, String target_frame_name) { @@ -269,4 +281,37 @@ private void setTreeModel(String name, List list, Function fun tree1.setCellRenderer(new CustomIconRenderer(name)); } + public String showFileChooserDialog(Project project) { + AtomicReference filePath = new AtomicReference<>(""); + ApplicationManager.getApplication().invokeAndWait(() -> { + FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(true, false, false, false, false, false); + fileChooserDescriptor.setTitle("选择文件"); + fileChooserDescriptor.setDescription("请选择一个图片"); + VirtualFile file = FileChooser.chooseFile(fileChooserDescriptor, project, null); + if (file != null) { + filePath.set(file.getCanonicalPath()); + } + }); + return filePath.get(); + } + + public static void forceRefresh(JBCefBrowser cefBrowser,String url) { + if (cefBrowser != null) { + // 通过重新加载当前URL来强制刷新浏览器 + String currentUrl = cefBrowser.getCefBrowser().getURL(); + if (StringUtils.isNotEmpty(url)) { + currentUrl = url; + } + cefBrowser.loadURL(currentUrl); + refreshWithDisableCache(cefBrowser); + log.info("Refresh with load on: {}", currentUrl); + } + } + + public static void refreshWithDisableCache(JBCefBrowser cefBrowser) { + Safe.run(()->{ + final CefBrowser[] devTools = {cefBrowser.getCefBrowser().getDevTools()}; + devTools[0].reloadIgnoreCache(); + }); + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/VisionHandler.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/VisionHandler.java similarity index 59% rename from athena-all/src/main/java/run/mone/m78/ip/listener/VisionHandler.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/VisionHandler.java index cb5b07f68..7bf7cc770 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/VisionHandler.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/listener/VisionHandler.java @@ -1,21 +1,24 @@ -package run.mone.m78.ip.listener; +package com.xiaomi.youpin.tesla.ip.listener; import cn.hutool.core.codec.Base64; import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonObject; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.infra.rpc.Result; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.*; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.LocalAiService; +import com.xiaomi.youpin.tesla.ip.service.M78Service; +import com.xiaomi.youpin.tesla.ip.service.PromptService; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.bo.chatgpt.*; -import run.mone.m78.ip.common.ChromeUtils; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.LocalAiService; -import run.mone.m78.ip.service.PromptService; import run.mone.ultraman.background.AthenaTask; import java.io.File; @@ -32,17 +35,20 @@ public class VisionHandler { public static String handler(Project project, Req req) { //传递录制的声音 if (req.getCmd().equals("sound")) { - return saveSound(project, req); +// return saveSound(project, req); + return saveSound2(project, req); } //播放声音 if (req.getCmd().equals("play sound")) { - return playSound2(project, req); +// return playSound2(project, req); + return playSound3(project, req); } //多模态,可以对图像提问 if (req.getCmd().equals("vision")) { - return vision(project, req); +// return vision(project, req); + return vision2(project, req); } return ""; } @@ -74,6 +80,25 @@ public void run(@NotNull ProgressIndicator indicator) { return res; } + private static String saveSound2(Project project, Req req) { + String soundInBase64 = req.getData().get("sound"); + String res = ""; + AthenaTask.start(new Task.Backgroundable(project, "speech to text", true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("text", soundInBase64); + jsonObject.addProperty("format", "mp3"); + Result transRes = M78Service.speechToText2(jsonObject); + if (transRes.getCode() == 0) { + ChromeUtils.call(project.getName(), transRes.getData(), 0); + } + } + }); + res = "ok:" + soundInBase64.length(); + return res; + } + @NotNull private static String playSound2(Project project, Req req) { String res; @@ -91,6 +116,24 @@ public void run(@NotNull ProgressIndicator indicator) { return res; } + private static String playSound3(Project project, Req req) { + String res; + AthenaTask.start(new Task.Backgroundable(project, "text to speech", true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("text", req.getData().get("input")); + Result result = M78Service.textToSpeech(jsonObject); + if (result.getCode() == 0) { + String s = new String(result.getData()); + ChromeUtils.call(project.getName(), s, 777); + } + } + }); + res = ""; + return res; + } + //多模态能力(可以识别图片) @NotNull private static String vision(Project project, Req req) { @@ -114,6 +157,19 @@ public void run(@NotNull ProgressIndicator indicator) { return res; } + private static String vision2(Project project, Req req) { + // 将req构建为m78格式的多模态ws请求 + JsonObject jsonReq = new JsonObject(); + jsonReq.addProperty("multimodal", 2); + jsonReq.addProperty("botId", 100307); + jsonReq.addProperty("topicId", 4090); + jsonReq.addProperty("input", req.getData().get("input")); + jsonReq.addProperty("mediaType", req.getData().get("mediaType")); + jsonReq.addProperty("postscript", req.getData().get("postscript")); + M78Service.imageHandle(project, jsonReq); + return "processing pic..."; + } + private static Pair playSound(Req req) { return LocalAiService.speech(SpeechReq.builder().input(req.getData().get("input")).build()); } diff --git a/athena-all/src/main/java/run/mone/m78/ip/renderer/CustomIconRenderer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/renderer/CustomIconRenderer.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/renderer/CustomIconRenderer.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/renderer/CustomIconRenderer.java index cb3aa7f7e..582a975ec 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/renderer/CustomIconRenderer.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/renderer/CustomIconRenderer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.renderer; +package com.xiaomi.youpin.tesla.ip.renderer; import com.intellij.openapi.util.IconLoader; diff --git a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributor.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributor.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributor.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributor.java index 4c504f2dd..053fe07f7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributor.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributor.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.search; +package com.xiaomi.youpin.tesla.ip.search; import com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor; import com.intellij.openapi.module.Module; @@ -7,15 +7,15 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.util.Processor; -import run.mone.m78.ip.bo.ElementInfo; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.service.PromptService; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.bo.ElementInfo; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; import lombok.SneakyThrows; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributorFactory.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributorFactory.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributorFactory.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributorFactory.java index 322776cef..b464e80b5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchEverywhereContributorFactory.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchEverywhereContributorFactory.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.search; +package com.xiaomi.youpin.tesla.ip.search; import com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor; import com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributorFactory; diff --git a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchInfo.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchInfo.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchInfo.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchInfo.java index 04ec19f11..3dafd0090 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/search/AthenaSearchInfo.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/AthenaSearchInfo.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.search; +package com.xiaomi.youpin.tesla.ip.search; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/m78/ip/search/MyChooseByNameContributor.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyChooseByNameContributor.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/search/MyChooseByNameContributor.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyChooseByNameContributor.java index 14fe6670c..6e727bbd8 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/search/MyChooseByNameContributor.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyChooseByNameContributor.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.search; +package com.xiaomi.youpin.tesla.ip.search; import com.intellij.navigation.ChooseByNameContributor; import com.intellij.navigation.ItemPresentation; diff --git a/athena-all/src/main/java/run/mone/m78/ip/search/MyCustomNavigationItem.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyCustomNavigationItem.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/search/MyCustomNavigationItem.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyCustomNavigationItem.java index d2f29b12c..c1db18276 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/search/MyCustomNavigationItem.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/search/MyCustomNavigationItem.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.search; +package com.xiaomi.youpin.tesla.ip.search; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/AbstractService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AbstractService.java similarity index 92% rename from athena-all/src/main/java/run/mone/m78/ip/service/AbstractService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AbstractService.java index aa64165d0..8a35396c2 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/AbstractService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AbstractService.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Context; +import com.xiaomi.youpin.tesla.ip.common.Context; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AiService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AiService.java new file mode 100644 index 000000000..1cb822191 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/AiService.java @@ -0,0 +1,30 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.gson.JsonObject; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; + +/** + * @author goodjava@qq.com + * @date 2023/12/5 22:51 + */ +public class AiService { + + + //同时支持远程和本地的(本地的被限流的次数会更少) + public static JsonObject call(String req, long timeout, boolean vip, boolean jsonResult) { + if (LabelUtils.open(Const.OPEN_AI_TEST)) { + return LocalAiService.call(req, timeout); + } + return ProxyAiService.call(req, timeout, vip, jsonResult); + + } + + + public static JsonObject call(String req, long timeout, boolean vip) { + return call(req, timeout, vip, true); + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/BotService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/BotService.java new file mode 100644 index 000000000..7b6506a66 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/BotService.java @@ -0,0 +1,356 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.common.base.Stopwatch; +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.common.*; +import com.xiaomi.youpin.tesla.ip.service.consumer.BotMsgConsumer; +import com.xiaomi.youpin.tesla.ip.util.ActionUtils; +import com.xiaomi.youpin.tesla.ip.util.GitUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import com.xiaomi.youpin.tesla.ip.util.TerminalUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.background.AthenaTask; +import run.mone.ultraman.bo.Version; +import run.mone.ultraman.common.CodeUtils; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.common.TestRunnerUtils; +import run.mone.ultraman.http.HttpClient; +import run.mone.ultraman.http.WsClient; +import run.mone.ultraman.listener.event.TaskEvent; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2024/6/5 23:03 + * 目前是Athena最核心的逻辑 + * 主要用来调用bot(调用m78平台) + * 分为同步调用和异步调用 + */ +@Slf4j +public class BotService { + + private static final String BOT_URL = "http://localhost/open-apis/ai-plugin-new/feature/router/probot/query"; + + //执行bot(支持流式调用,和直接json返回) + public static void executeBot(GenerateCodeReq req) { + PromptInfo promptInfo = req.getPromptInfo(); + if (null != promptInfo) { + Map labels = promptInfo.getLabels(); + if (isLabeldWithSteam(labels)) { + //调用流试服务(实现打字机效果),比如代码生成 + streamBotCall(req, labels); + } else { + //直接调用bot,返回json,比如:给方法从命名,一键提交代码 + directBotCall(req, labels); + } + // 执行bot之后上传插件统计信息。这块只统计非生成代码的行为。生成代码会在BotMsgConsumer中进行统计 + Action action = ActionUtils.getActionByReq(req); + if (Action.GENERATE_CODE != action) { + CodeUtils.uploadCodeGenInfo(action.getCode(), + req.getProjectName(), + req.getClassName(), + req.getPsiMethod() == null ? "" : req.getPsiMethod().getName()); + } + } + } + + private static boolean isLabeldWithSteam(Map labels) { + return labels.getOrDefault("stream", "false").equals("true"); + } + + private static void directBotCall(GenerateCodeReq req, Map labels) { + JsonObject jsonReq = new JsonObject(); + jsonReq.addProperty(Const.BOT_ID, labels.get("botId")); + + //如果是private_prompt = true 的bot,需要注意传一个params参数,这个参数实际是一个Map结构 + + //git push + if (handleGitPushInfo(req, jsonReq)) return; + + //修改方法名 + handleModifyMethodName(req, jsonReq); + + //bug fix(问题修复) + if (handleBugFix(req, labels, jsonReq)) return; + + handleGenerateCodeReqAndBotRes(req, jsonReq); + } + + private static void handleGenerateCodeReqAndBotRes(GenerateCodeReq req, JsonObject jsonReq) { + String botRes = null; + try { + botRes = callBot(req.getProject(), jsonReq); + } catch (Throwable e) { + log.warn("callBot error:{}", e.getMessage()); + return; + } + //处理结果 + handleGenerateCodeReqAndBotRes(req, botRes); + } + + private static boolean handleBugFix(GenerateCodeReq req, Map labels, JsonObject jsonReq) { + //bug fix(问题修复) + if (Action.BUG_FIX == ActionUtils.getActionByReq(req)) { + ApplicationManager.getApplication().invokeLater(() -> { + TestRunnerUtils.runTest(req.getProject(), req.getPsiMethod().getName(), pair -> { + //查问题需要行号 + Map params = ImmutableMap.of("method", pair.getKey(), "error", pair.getValue()); + jsonReq.add("params", GsonUtils.gson.toJsonTree(params)); + jsonReq.addProperty("input", ""); + //处理结果 + handleGenerateCodeReqAndBotRes(req, jsonReq); + }); + }); + return true; + } + return false; + } + + private static void handleModifyMethodName(GenerateCodeReq req, JsonObject jsonReq) { + if (Action.SMART_NAMING == ActionUtils.getActionByReq(req)) { + Map params = ImmutableMap.of("code", req.getMethodCode()); + jsonReq.add("params", GsonUtils.gson.toJsonTree(params)); + jsonReq.addProperty("input", ""); + } + } + + private static boolean handleGitPushInfo(GenerateCodeReq req, JsonObject jsonReq) { + if (Action.GIT_PUSH == ActionUtils.getActionByReq(req)) { + List list = GitUtils.getAffectedFileNames(req.getProject()); + String commitDiff = GitUtils.getCommitDiff(req.getProject()); + if (commitDiff.length() > 10000) { + // 太长了,截断下 + commitDiff = commitDiff.substring(0, 5000); + } + String currentBranch = GitUtils.getCurrentBranch(req.getProject()); + if (list.isEmpty()) { + log.info("getAffectedFileNames num:0"); + return true; + } + JsonObject input = new JsonObject(); + input.add("changedFiles", GsonUtils.gson.toJsonTree(list)); + input.addProperty("diff", commitDiff); + input.addProperty("branch", currentBranch); + jsonReq.addProperty("input", input.toString()); + } + return false; + } + + private static void handleGenerateCodeReqAndBotRes(GenerateCodeReq req, String botRes) { + switch (ActionUtils.getActionByReq(req)) { + //操作terminal + case GIT_PUSH: + TerminalUtils.executeTerminalCommand(req.getProject(), botRes); + break; + //给方法重命名 + case SMART_NAMING: + PsiMethodUtils.renameMethod(req.getProject(), req.getPsiMethod(), botRes); + break; + //bug fix + case BUG_FIX: + log.info("fix method:{}", botRes); + //替换这个方法的内容 + PsiMethodUtils.replacePsiMethod(req.getProject(), req.getPsiMethod(), botRes); + break; + } + } + + //这里会调用到m78:WebSocketHandler + private static void streamBotCall(GenerateCodeReq req, Map labels) { + String out = req.getPromptInfo().getLabels().getOrDefault("bot_out", "athena"); + WsClient wsClient = new WsClient(); + if (!Objects.isNull(req.getCountDownLatch())) { + wsClient.setLatch(req.getCountDownLatch()); + } + //for test +// wsClient.setUrl("ws://127.0.0.1:8077/ws/bot/abc"); + wsClient.setProjectName(req.getProject().getName()); + String id = UUID.randomUUID().toString(); + wsClient.setId(id); + + ImportCode importCode = new ImportCode(); + importCode.setProject(req.getProject()); + importCode.setEditor(req.getEditor()); + + Stopwatch sw = Stopwatch.createStarted(); + wsClient.init(getAiMessageConsumer(req, out, importCode, sw)); + JsonObject jsonReq = new JsonObject(); + jsonReq.addProperty(Const.BOT_ID, labels.get("botId")); + //ztoken(可以用来换取用户名) + jsonReq.addProperty(Const.TOKEN, ConfigUtils.getConfig().getzToken()); + + String input = ""; + switch (ActionUtils.getActionByReq(req)) { + case GENERATE_CODE: + //通过注释生成代码 + if (null != req.getParam().get(Const.GENERATE_CODE_COMMENT)) { + input = req.getParam().get(Const.GENERATE_CODE_COMMENT); + } else { + input = req.getCurrentLine(); + } + + if (req.getParam().containsKey("__code")) { + input = req.getParam().get("__code"); + } + //生成代码的时候有许多参数和上下文,靠这里拿到这些参数列表 + JsonObject params = generateParams(req, input); + input = ""; + jsonReq.add("params", params); + break; + case CHAT: + // 聊天 + input = req.getParam().get("chatContent"); + break; + case UNIT_TEST: + // 单元测试 + jsonReq.add("params", generateUnitTestParams(req)); + break; + case GENERATE_COMMENT: + case CODE_SUGGESTION: + //给代码添加注释, 代码建议 + if (StringUtils.isNotEmpty(req.getMethodCode())) { + input = req.getMethodCode(); + } else { + wsClient.getWs().close(1000, null); + return; + } + break; + } + jsonReq.addProperty("input", input); + jsonReq.addProperty("topicId", id); + // 添加version参数 + addVersionParam(jsonReq); + // 添加用户自定义model + setModel(req, jsonReq); + + wsClient.send(jsonReq); + } + + @NotNull + public static JsonObject generateParams(GenerateCodeReq req, String input) { + JsonObject params = new JsonObject(); + params.addProperty("code", input); + params.addProperty("class", req.getClassCode()); + + if (null == req.getInheritedMethods()) { +// NotificationCenter.notice(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE, NotificationType.ERROR); +// throw new RuntimeException(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE); + log.error(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE); + } else { + params.addProperty("inheritedMethods", req.getInheritedMethods().stream().collect(Collectors.joining("\n\n\n"))); + } + params.addProperty("fqcn", req.getQualifiedName()); + //计算上下文(context) + updateParamsWithContext(req, params); + return params; + } + + @NotNull + public static JsonObject generateUnitTestParams(GenerateCodeReq req) { + JsonObject params = new JsonObject(); + params.addProperty("code", req.getParam().get("code")); + params.addProperty("testClassCode", req.getParam().get("testClassCode")); + return params; + } + + private static void updateParamsWithContext(GenerateCodeReq req, JsonObject params) { + Safe.run(() -> { + String context = getContextFromGenerateCodeReq(req); + params.addProperty("context", context); + }); + } + + //获取计算 + private static String getContextFromGenerateCodeReq(GenerateCodeReq req) { + AthenaTask athenaTask = PromptService.generateMethod(req, false); + athenaTask.getInitRunnable().run(); + athenaTask.initContexts(); + athenaTask.calculateAndOptimizeRequestSize(); + String context = athenaTask.getContext(); + return context; + } + + + @NotNull + private static Consumer getAiMessageConsumer(GenerateCodeReq req, String out, ImportCode importCode, Stopwatch sw) { + return new BotMsgConsumer(req, out, importCode, sw); + } + + + //直接调用bot,然后返回json,解析json结果 + public static String callBot(Project project, JsonObject jsonReq) { + String userName = ConfigUtils.getConfig().getNickName(); + jsonReq.addProperty("userName", userName); + jsonReq.addProperty("projectName", project.getName()); + jsonReq.addProperty(Const.TOKEN, ConfigUtils.getConfig().getzToken()); + // 添加version参数 + addVersionParam(jsonReq); + String param = jsonReq.toString(); + + //看起来很麻烦,是因为这个不一定在那个线程里,只能通过这种方式稳定的调用 + ApplicationManager.getApplication().getMessageBus().syncPublisher(TaskEvent.TOPIC).onEvent(TaskEvent.builder().message("begin").build()); + Stopwatch sw = Stopwatch.createStarted(); + String resStr = ""; + try { + String botUrl = ResourceUtils.getAthenaConfig().getOrDefault(Const.BOT_URL, ""); + if (StringUtils.isEmpty(botUrl)) { + botUrl = BOT_URL; + } + //for test +// http://127.0.0.1:8077/open-apis/v1/ai-plugin-new/feature/router/probot/query + resStr = HttpClient.callHttpServer(botUrl, "callBot", param, false, false, 20); + } finally { + ApplicationManager.getApplication().getMessageBus().syncPublisher(TaskEvent.TOPIC).onEvent(TaskEvent.builder().message("end").time(sw.elapsed(TimeUnit.SECONDS)).build()); + } + + log.info("call bot res:{} param:{}", resStr, param); + JsonObject resObj = GsonUtils.gson.fromJson(resStr, JsonObject.class); + + //处理结果中的错误 + handleResponse(resObj); + + String commond = JsonParser.parseString(resObj.get("data").getAsString()).getAsJsonObject().get("result").getAsJsonObject().get("data").getAsString(); + return commond; + } + + private static void handleResponse(JsonObject resObj) { + if (resObj.get("code").getAsInt() != 0) { + NotificationCenter.notice(resObj.get("message").getAsString(), NotificationType.ERROR); + throw new RuntimeException("callHttpServer error:" + resObj); + } + } + + // 在给定的JsonObject中添加version参数(class) + private static void addVersionParam(JsonObject resObj) { + Version version = new Version(); + resObj.addProperty(Const.CLIENT_VERSION, version.getVersion()); + resObj.addProperty(Const.CLIENT_NAME, version.getName()); + } + + private static void setModel(GenerateCodeReq req, JsonObject jsonReq) { + Action action = ActionUtils.getActionByReq(req); + String model = action == Action.CHAT ? AthenaContext.ins().getGptModel() : AthenaContext.ins().getNoChatModel(); + if (!Const.USE_BOT_MODEL.equals(model)) { + jsonReq.addProperty(Const.AI_MODEL_PARAM_KEY, model); + } + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ClassFinder.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClassFinder.java similarity index 81% rename from athena-all/src/main/java/run/mone/m78/ip/service/ClassFinder.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClassFinder.java index a4eec91e5..0b775226d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ClassFinder.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClassFinder.java @@ -1,8 +1,8 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.ClassInfo; -import run.mone.m78.ip.util.AnnoUtils; +import com.xiaomi.youpin.tesla.ip.bo.ClassInfo; +import com.xiaomi.youpin.tesla.ip.util.AnnoUtils; import org.apache.commons.compress.utils.Lists; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ClipboardService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClipboardService.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/service/ClipboardService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClipboardService.java index a6f52344c..b2b7f6d94 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ClipboardService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ClipboardService.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import lombok.SneakyThrows; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/CodeService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/CodeService.java new file mode 100644 index 000000000..43d5f35b9 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/CodeService.java @@ -0,0 +1,1774 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.intellij.codeInsight.lookup.LookupEx; +import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.ide.util.DirectoryUtil; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.AllClassesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Query; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.common.*; +import com.xiaomi.youpin.tesla.ip.util.*; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Response; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.MutableObject; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.openai.OpenaiCall; +import run.mone.openai.ReqConfig; +import run.mone.openai.StreamListener; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.common.TemplateUtils; +import run.mone.ultraman.service.AthenaCodeService; +import run.mone.ultraman.visitor.M78Visitor; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + */ +@Slf4j +public class CodeService extends AbstractService { + + private static Gson gson = new Gson(); + + /** + * 打个某个指定的class + * + * @param project + * @param className + */ + public static PsiClass openJavaClass(Project project, String className) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + if (project == null) { + return null; + } + //Search for Java classes + JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); + PsiClass psiClass = javaPsiFacade.findClass(className, GlobalSearchScope.allScope(project)); + + if (psiClass == null) { + return null; + } + // 创建 OpenFileDescriptor + OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(project, psiClass.getContainingFile().getVirtualFile()); + // 使用 FileEditorManager 打开 Java 类 + FileEditorManager.getInstance(project).openTextEditor(openFileDescriptor, true); + return psiClass; + }); + } + + + public static PsiClass[] getClassesInPackage(Project project, String packageName) { + JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); + PsiPackage psiPackage = javaPsiFacade.findPackage(packageName); + if (psiPackage != null) { + PsiClass[] psiClasses = psiPackage.getClasses(); + return psiClasses; + } + return new PsiClass[0]; + } + + + /** + * 移动到方法的开头,且插入空行 + * Navigate to the beginning of the method and insert a blank line. + * + * @param project + */ + public static void moveToMethodAndInsertLine(Project project) { + PsiMethod method = getMethod(project); + if (null == method) { + return; + } + int offset = method.getTextRange().getStartOffset(); + Editor editor = getEditor(project); + CaretModel caretModel = editor.getCaretModel(); + caretModel.moveToOffset(offset); + WriteCommandAction.runWriteCommandAction(project, () -> editor.getDocument().insertString(offset, "\n\t")); + } + + //获取Editor中上一行的内容,如果是注释则返回注释内容,且当前所处位置是PsiClass中(class) + public static String getPreviousLineIfComment(Editor editor) { + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + int lineNumber = document.getLineNumber(offset); + System.out.println(lineNumber); + if (lineNumber > 0) { + int previousLineStartOffset = document.getLineStartOffset(lineNumber - 1); + int previousLineEndOffset = document.getLineEndOffset(lineNumber - 1); + String previousLineText = document.getText(new TextRange(previousLineStartOffset, previousLineEndOffset)); + if (readCodeContinue(previousLineText)) { + return previousLineText; + } + } + return null; + } + + + //根据class name获取PsiClass(class) + public static PsiClass getPsiClassByName(Project project, String className) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + if (project == null || className == null || className.isEmpty()) { + return null; + } + JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); + return javaPsiFacade.findClass(className, GlobalSearchScope.allScope(project)); + }); + } + + + //给你class名字和method名字帮我获取这个PsiMethod(class) + public static String getPsiMethodByName(Project project, String className, String methodName) { + PsiClass psiClass = getPsiClassByName(project, className); + if (psiClass == null || methodName == null || methodName.isEmpty()) { + return null; + } + for (PsiMethod method : psiClass.getMethods()) { + if (methodName.equals(method.getName())) { + return getMethodAndLineNumbers(method); + } + } + return null; + } + + //我在Editor中选中一个被调用的方法(类似:),帮我找到这个方法的代码,并返回(class) + public static PsiMethod findSelectedMethod(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null) { + return null; + } + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile == null) { + return null; + } + PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset()); + PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); + return method; + } + + public static PsiMethod getPsiMethod(Project project, String className, String methodName) { + PsiClass psiClass = getPsiClassByName(project, className); + if (psiClass == null || methodName == null || methodName.isEmpty()) { + return null; + } + for (PsiMethod method : psiClass.getMethods()) { + if (methodName.equals(method.getName())) { + return method; + } + } + return null; + } + + /** + * 获取方法及行号相关信息 + */ + public static String getMethodAndLineNumbers(PsiMethod method) { + StringBuilder sb = new StringBuilder(); + PsiFile psiFile = method.getContainingFile(); + if (psiFile != null) { + Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); + if (document != null) { + TextRange methodRange = method.getTextRange(); + int startLine = document.getLineNumber(methodRange.getStartOffset()); + int endLine = document.getLineNumber(methodRange.getEndOffset()); + + for (int line = startLine; line <= endLine; line++) { + int lineStartOffset = document.getLineStartOffset(line); + int lineEndOffset = document.getLineEndOffset(line); + String lineText = document.getText(new TextRange(lineStartOffset, lineEndOffset)); + // 注释内容直接跳过 + if (readCodeContinue(lineText)) { + continue; + } + sb.append("line:" + (line + 1) + " code:" + lineText + "\n"); + } + } + } + return sb.toString(); + } + + public static String getClassName(PsiClass psiClass) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> psiClass.getQualifiedName()); + } + + private static boolean readCodeContinue(String lineCode) { + return lineCode.trim().startsWith("//") || lineCode.trim().startsWith("/*") + || lineCode.trim().startsWith("*") || lineCode.trim().startsWith("*/"); + } + + public static String getClassAndLineNumbers(PsiClass psiClass) { + StringBuilder sb = new StringBuilder(); + PsiFile psiFile = psiClass.getContainingFile(); + if (psiFile != null) { + Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); + if (document != null) { + TextRange methodRange = psiClass.getTextRange(); + int startLine = document.getLineNumber(methodRange.getStartOffset()); + int endLine = document.getLineNumber(methodRange.getEndOffset()); + + for (int line = startLine; line <= endLine; line++) { + int lineStartOffset = document.getLineStartOffset(line); + int lineEndOffset = document.getLineEndOffset(line); + String lineText = document.getText(new TextRange(lineStartOffset, lineEndOffset)); + sb.append("line:" + (line + 1) + " code:" + lineText + "\n"); + } + } + } + return sb.toString(); + } + + public static void addField(Project project, Document document, PsiClass psiClass, String code, String name) { + boolean find = Arrays.stream(psiClass.getFields()).filter(it -> it.getType().getCanonicalText().equals(name)).findAny().isPresent(); + if (!find) { + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + PsiField field = factory.createFieldFromText(code, null); + WriteCommandAction.runWriteCommandAction(project, () -> { + psiClass.add(field); + psiClass.getContainingFile().getVirtualFile().refresh(false, false); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + } + } + + /** + * 添加方法 + * + * @param project + * @param code + */ + public static void addMethod(Project project, String code) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + PsiMethod method = factory.createMethodFromText(code, null); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + WriteCommandAction.runWriteCommandAction(project, () -> { + psiClass.add(method); + psiClass.getContainingFile().getVirtualFile().refresh(false, false); + }); + } + + + /** + * 在光标处插入指定数量的空白行。 + * + * @param project 当前操作的项目对象 + * @param editor 当前操作的编辑器对象 + * @param numberOfBlankLines 要插入的空白行数 + */ + public static void insertBlankLinesAtCaret(Project project, Editor editor, int numberOfBlankLines) { + // 获取当前文档和光标所在的偏移量 + Document document = editor.getDocument(); + int caretOffset = editor.getCaretModel().getOffset(); + + // 创建一个包含指定数量空行的字符串 + StringBuilder newLines = new StringBuilder(); + for (int i = 0; i < numberOfBlankLines; i++) { + newLines.append("\n"); + } + + //保证线程安全 + ApplicationManager.getApplication().invokeLater(() -> { + WriteCommandAction.runWriteCommandAction(project, () -> { + // 在光标位置插入空行 + document.insertString(caretOffset, newLines.toString()); + + // 提交文档更改 + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + }); + } + + + public static void insertCode(Project project, String code) { + insertCode(project, code, true); + } + + public static void insertCode(Project project, String code, boolean enter) { + Editor editor = getEditor(project); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + insertCode(project, code, enter, offset, editor); + } + + public static void insertCode(Project project, String code, boolean enter, int offset, Editor editor) { + log.info("insert code at offset:{}", offset); + WriteCommandAction.runWriteCommandAction(project, () -> { + Document document = editor.getDocument(); + document.insertString(offset, code + (enter ? "\n" : "")); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + formatCode(project); + } + + public static void insertCode(Project project, Document document, int offset, String code, boolean enter, boolean format) { + WriteCommandAction.runWriteCommandAction(project, () -> { + document.insertString(offset, code + (enter ? "\n" : "")); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + if (format) { + formatCode(project); + } + } + + /** + * 添加 import list + * + * @param project + * @param importStrList + */ + @SneakyThrows + public static void addImport(Project project, List importStrList) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + addImport(project, editor, importStrList); + } + + + public static void addImport(Project project, Editor editor, List importStrList) { + ImportUtils.addImport(project, editor, importStrList); + } + + + public static PsiClass createPsiClass(PsiElementFactory factory, String className) { + return ImportUtils.createPsiClass(factory, className); + } + + + /** + * 根据需求直接生成方法 + * + * @param project + * @param prompt + */ + public static void generateMethod(Project project, String prompt) { + } + + /** + * 向方法中添加语句 + * + * @param project + * @param code + */ + public static void addStatementToMethod(Project project, String code) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + PsiStatement statement = factory.createStatementFromText(code, null); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiMethod psiMethod = PsiTreeUtil.getParentOfType(elementAtCaret, PsiMethod.class); + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiCodeBlock body = psiMethod.getBody(); + body.addBefore(statement, body.getFirstBodyElement()); + psiMethod.getContainingFile().getVirtualFile().refresh(false, false); + }); + } + + /** + * 把代码写入Idea Editor + * + * @param project + * @param editor + * @param code + */ + public static void writeCode2(Project project, Editor editor, String code) { + writeCode4(project, editor, code, true); + } + + public static void writeCode4(Project project, Editor editor, String code, boolean appendT) { + @NotNull Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + WriteCommandAction.runWriteCommandAction(project, () -> { + int offset = caretModel.getOffset(); + Pair pair = lineAndColumnNum(document, offset); + int line = pair.getKey(); + for (; ; ) { + int startOffset = caretModel.getOffset(); + int endOffset = document.getLineEndOffset(line - 1); + String content = document.getText(new TextRange(startOffset, endOffset)); + //如果后边是空的,则直接添加 + if (StringUtils.isEmpty(content.trim())) { + String s = ""; + //补一个tab,看起来更美观 + if (isFirstColumn(startOffset, editor)) { + s = appendT ? "\t" + code : "" + code; + } else { + s = code; + } + document.insertString(startOffset, s); + caretModel.moveToOffset(startOffset + s.length()); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + break; + } else { //否则插入空行 + editor.getCaretModel().moveToOffset(endOffset); + addLineBreak(project, document, line, 1); + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + } + } + }); + } + + /** + * 用于关闭完成操作 + * 获取项目对应的编辑器,如果不为空则隐藏该项目的活动查找 + */ + public static void closeCompletion(Project project) { + if (project == null || project.isDisposed()) { + return; + } + @Nullable LookupEx lookup = LookupManager.getInstance(project).getActiveLookup(); + if (null != lookup) { + LookupManager.getInstance(project).hideActiveLookup(); + } + } + + + /** + * 将编辑器中的光标移动到当前行的末尾。 + * + * @param editor 需要操作的编辑器对象 + */ + public static void moveCaretToEndOfLine(Editor editor) { + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int lineNumber = document.getLineNumber(caretModel.getOffset()); + int lineEndOffset = document.getLineEndOffset(lineNumber); + caretModel.moveToOffset(lineEndOffset); + } + + //移动光标到指定PsiMethod上(method) + public static void moveCaretToMethod(Editor editor, PsiMethod method) { + int offset = method.getTextOffset(); + LogicalPosition logicalPosition = editor.offsetToLogicalPosition(offset); + editor.getCaretModel().moveToLogicalPosition(logicalPosition); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + + + //移动光标到指定PsiComment的最后位置(class) + public static void moveCaretToCommentEnd(Editor editor, PsiComment comment) { + int offset = comment.getTextRange().getEndOffset(); + LogicalPosition logicalPosition = editor.offsetToLogicalPosition(offset); + editor.getCaretModel().moveToLogicalPosition(logicalPosition); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + + public static void moveCaretToOffset(Editor editor, int offset) { + LogicalPosition logicalPosition = editor.offsetToLogicalPosition(offset); + editor.getCaretModel().moveToLogicalPosition(logicalPosition); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + + + // 判断光标Caret所在位置后面是否没有任何字符 + public static boolean isCaretAtEndOfLine(Editor editor) { + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int caretOffset = caretModel.getOffset(); + int lineNumber = document.getLineNumber(caretOffset); + int lineEndOffset = document.getLineEndOffset(lineNumber); + return caretOffset >= lineEndOffset; + } + + // 判断光标向前遇到的第一个字符是不是 "{", "}" , ";" + public static boolean isPreCharBrace(Editor editor) { + if (editor == null) { + return false; + } + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + if (offset == 0) { + return false; + } + CharSequence text = document.getCharsSequence(); + for (int i = offset - 1; i >= 0; i--) { + char currentChar = text.charAt(i); + if (Character.isWhitespace(currentChar)) { + continue; + } + return currentChar == '{' || currentChar == '}' || currentChar == ';'; + } + return false; + } + + + /** + * 将编辑器的光标移动到方法的结束位置。 + * + * @param editor 编辑器对象 + * @param method 要移动光标到其结束位置的方法对象 + */ + public static void moveCaretToMethodEnd(Editor editor, PsiMethod method) { + if (method == null || null == method.getBody()) { + return; + } + PsiJavaToken rBrace = method.getBody().getRBrace(); + if (Objects.isNull(rBrace)) { + return; + } + int methodEndOffset = rBrace.getTextOffset(); + editor.getCaretModel().moveToOffset(methodEndOffset - 1); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + } + + + private static boolean isFirstColumn(int offset, Editor editor) { + int lineNumber = editor.getDocument().getLineNumber(offset); + int lineStartOffset = editor.getDocument().getLineStartOffset(lineNumber); + boolean isFirstColumn = (offset - lineStartOffset) == 0; + return isFirstColumn; + } + + + public static void writeCode3(Project project, String code) { + UltramanConsole.append(project, code, false); + } + + + public static Pair lineAndColumnNum(Document document, int offset) { + int lineNumber = document.getLineNumber(offset) + 1; + int columnNumber = offset - document.getLineStartOffset(lineNumber - 1); + return Pair.of(lineNumber, columnNumber); + } + + + /** + * 移动到指定行号 + * + * @param project + * @param lineNumber + */ + public static void moveLine(Project project, int lineNumber) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + LogicalPosition position = new LogicalPosition(lineNumber - 1, 0); // 创建逻辑位置对象 + editor.getCaretModel().moveToLogicalPosition(position); // 将光标移动到指定行 + } + + + /** + * 关闭当前Editor + * + * @param project + */ + public static void closeEditor(Project project) { + EditorUtils.closeEditor(project); + } + + /** + * 格式化当前代码 + */ + public static void formatCode(Project project) { + if (null == project) { + return; + } + WriteCommandAction.runWriteCommandAction(project, () -> { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); + codeStyleManager.reformat(psiFile); + }); + } + + @Nullable + public static Project deleteCode(@NotNull Editor editor) { + Project project = editor.getProject(); + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiMethod psiMethod = CodeService.getMethod(project); + if (null != psiMethod) { + String methodText = psiMethod.getText(); + methodText = methodText.replace("//❁", ""); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiMethod newMethod = factory.createMethodFromText(methodText, psiMethod); + psiMethod.replace(newMethod); + } + if (project != null && editor.getDocument() != null) { + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + } + }); + return project; + } + + + /** + * 替换指定PsiFile文件的内容为新的文本内容 + * + * @param psiFile 要替换内容的PsiFile对象 + * @param newContent 新的文件内容字符串 + */ + public static void replaceFileContent(PsiFile psiFile, String newContent) { + Project project = psiFile.getProject(); + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); + Document document = psiDocumentManager.getDocument(psiFile); + + if (document != null) { + // 开始一个写操作,以修改文件内容 + WriteCommandAction.runWriteCommandAction(project, () -> { + document.setText(newContent); + psiDocumentManager.commitDocument(document); + }); + } + } + + + /** + * 删除指定行 + * + * @param project + * @param lineToDelete + */ + public static void deleteLine(Project project, int lineToDelete) { + lineToDelete = lineToDelete - 1; + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + Document document = editor.getDocument(); + int startOffset = document.getLineStartOffset(lineToDelete); + int endOffset = document.getLineEndOffset(lineToDelete); + WriteCommandAction.runWriteCommandAction(project, () -> { + document.deleteString(startOffset, endOffset); + }); + + ApplicationManager.getApplication().invokeLater(() -> editor.getContentComponent().repaint()); + } + + + /** + * 返回所有method + * + * @param project + * @return + */ + public static List methods(Project project) { + Editor editor = getEditor(project); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); + PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + return Arrays.stream(currentPsiClass.getAllMethods()).map(it -> it.getName()).collect(Collectors.toList()); + } + + + /** + * 通过module查询会快点 + * + * @param project + * @param module + * @param name + * @return + */ + public static PsiClass getPsiClass(Project project, Module module, String name) { + PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(name, GlobalSearchScope.moduleScope(module)); + return psiClass; + } + + + public static List methods(PsiClass psiClass) { + return Arrays.stream(psiClass.getMethods()).filter(it -> it.getModifierList().hasModifierProperty("public")).map(it -> it.getName()).collect(Collectors.toList()); + } + + + public static List fields(Project project) { + Editor editor = getEditor(project); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); + PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + return Arrays.stream(currentPsiClass.getAllFields()).map(it -> it.getName()).collect(Collectors.toList()); + } + + public static PsiMethod getMethod(Project project) { + Editor editor = getEditor(project); + if (null == editor) { + return null; + } + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + //如果有选中内容,则分析选中的是否是PsiMethod + if (isTextSelected(editor)) { + PsiElement pe = getSelectedPsiMethod(editor, psiFile); + if (pe instanceof PsiMethod) { + return (PsiMethod) pe; + } + } + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiMethod method = PsiTreeUtil.getParentOfType(elementAtCaret, PsiMethod.class); + return method; + } + + public static String getMethodCode(Project project) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> getMethod(project).getText()); + } + + public static PsiField getPsiField(Project project) { + Editor editor = getEditor(project); + if (null == editor) { + return null; + } + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiField psiField = PsiTreeUtil.getParentOfType(elementAtCaret, PsiField.class); + return psiField; + } + + + public static boolean isTextSelected(Editor editor) { + return editor.getSelectionModel().hasSelection(); + } + + public static String getSelectedText(Editor editor) { + if (isTextSelected(editor)) { + SelectionModel selectionModel = editor.getSelectionModel(); + String selectedText = selectionModel.getSelectedText(); + return selectedText; + } + return ""; + } + + + public static PsiElement getSelectedPsiMethod(Editor editor, PsiFile psiFile) { + SelectionModel selectionModel = editor.getSelectionModel(); + int start = selectionModel.getSelectionStart(); + int end = selectionModel.getSelectionEnd(); + for (int i = start; i < end; i++) { + PsiElement element = psiFile.findElementAt(i); + @Nullable PsiMethod pm = PsiTreeUtil.getParentOfType(element, PsiMethod.class); + if (null != pm) { + return pm; + } + } + return null; + } + + public static PsiMethod getPsiMethodWithLineNum(Project project, Document document, int lineNum) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + @Nullable PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + int start = document.getLineStartOffset(lineNum - 1); + int end = document.getLineEndOffset(lineNum - 1); + for (int i = start; i < end; i++) { + PsiElement element = psiFile.findElementAt(i); + @Nullable PsiMethod pm = PsiTreeUtil.getParentOfType(element, PsiMethod.class); + if (null != pm) { + return pm; + } + } + return null; + }); + } + + public static PsiField getPsiFieldWithLineNum(Project project, Document document, int lineNum) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + @Nullable PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + int start = document.getLineStartOffset(lineNum - 1); + int end = document.getLineEndOffset(lineNum - 1); + for (int i = start; i < end; i++) { + PsiElement element = psiFile.findElementAt(i); + @Nullable PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class); + if (null != field) { + return field; + } + } + return null; + }); + } + + + public static PsiClass getPsiClassWithLineNum(Project project, Document document, int lineNum) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + @Nullable PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + int start = document.getLineStartOffset(lineNum - 1); + int end = document.getLineEndOffset(lineNum - 1); + for (int i = start; i < end; i++) { + PsiElement element = psiFile.findElementAt(i); + @Nullable PsiClass pm = PsiTreeUtil.getParentOfType(element, PsiClass.class); + if (null != pm) { + return pm; + } + } + return null; + }); + + } + + + public static TextRange getTextRange(Project project, final Class clazz) { + Editor editor = getEditor(project); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + + while (true) { + if (elementAtCaret.getClass().equals(clazz)) { + return elementAtCaret.getTextRange(); + } + elementAtCaret = elementAtCaret.getParent(); + if (null == elementAtCaret) { + return null; + } + } + } + + public static String getText(Project project, Class clazz) { + Editor editor = getEditor(project); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiElement element = PsiTreeUtil.getParentOfType(elementAtCaret, clazz); + return element.getText(); + } + + public static TextRange getParentTextRange(Project project) { + Editor editor = getEditor(project); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + return psiFile.findElementAt(offset).getParent().getParent().getTextRange(); + } + + + public static PsiClass getPsiClass(Project project) { + Editor editor = getEditor(project); + if (null == editor) { + return null; + } + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile != null) { + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + return psiClass; + } else { + return null; + } + } + + public static PsiClass getPsiClassInRead(Project project) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + return getPsiClass(project); + }); + } + + public static PsiElement getParentOfType(Project project, Class clazz) { + Editor editor = getEditor(project); + if (null == editor) { + return null; + } + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiElement res = PsiTreeUtil.getParentOfType(elementAtCaret, clazz); + return res; + } + + + public static PsiClass getPsiClass2(Project project) { + Editor editor = getEditor(project); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiClass psiClass = Arrays.stream(psiFile.getChildren()).filter(it -> it instanceof PsiClass).map(it -> (PsiClass) it).findFirst().get(); + return psiClass; + } + + public static PsiFile getPsiFile(Project project) { + Editor editor = getEditor(project); + return PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + } + + + public static PsiMethod getMethod(PsiClass psiClass, String methodName) { + PsiMethod[] methods = psiClass.findMethodsByName(methodName, false); + return methods[0]; + } + + + public static Map getLineContentsAndNumbersForMethod(PsiMethod method) { + Map lineContentsAndNumbers = new HashMap<>(); + PsiCodeBlock codeBlock = method.getBody(); + if (codeBlock != null) { + PsiFile containingFile = codeBlock.getContainingFile(); + Document document = PsiDocumentManager.getInstance(method.getProject()).getDocument(containingFile); + for (PsiElement element : codeBlock.getChildren()) { + int startOffset = element.getTextOffset(); + int endOffset = startOffset + element.getTextLength(); + int startLineNumber = document.getLineNumber(startOffset); + int endLineNumber = document.getLineNumber(endOffset); + for (int i = startLineNumber; i <= endLineNumber; i++) { + int lineStartOffset = document.getLineStartOffset(i); + int lineEndOffset = document.getLineEndOffset(i); + TextRange textRange = new TextRange(lineStartOffset, lineEndOffset); + String lineContent = document.getText(textRange).trim(); + lineContentsAndNumbers.put(i + 1, lineContent); + } + } + } + return lineContentsAndNumbers; + } + + + public static int getMethodLineCount(PsiMethod method) { + if (method == null) { + return 0; + } + PsiCodeBlock body = method.getBody(); + if (body == null) { + return 0; + } + Document document = getEditor(method.getProject()).getDocument(); + if (document == null) { + return 0; + } + int startLine = document.getLineNumber(body.getTextRange().getStartOffset()); + int endLine = document.getLineNumber(body.getTextRange().getEndOffset()); + return endLine - startLine + 1; + } + + public static String getClassText(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + return editor.getDocument().getText(); + } + + public static String getClassText2(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + Document document = editor.getDocument(); + int offset = editor.getCaretModel().getOffset(); + String text = document.getText(); + return text.substring(0, offset) + "//❁" + text.substring(offset); + } + + + /** + * 根据prompt删除注解 + * + * @param project + */ + public static void removeComments(Project project) { + } + + + public static void createEmptyClass(Project project, String moduleName, String packageName, String className) { + createEmptyClass(project, moduleName, packageName, className, false); + } + + /** + * 创建空的类 + * + * @param project + * @param packageName + * @param className + */ + public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath) { + PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath); + } + + + public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath, boolean isInterface) { + PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath, false, null, isInterface); + } + + + public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath, List annoList) { + PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath, annoList); + } + + + public static PsiDirectory getSourceDirectory(Project project, String moduleName, boolean testPath) { + return PsiClassUtils.getSourceDirectory(project, moduleName, testPath); + } + + public static PsiDirectory getSourceDirectory(Project project, boolean testPath, String packagePath) { + return PsiClassUtils.getSourceDirectory(project, testPath, packagePath); + } + + public static PsiDirectory getSourceDirectory(Project project) { + return PsiClassUtils.getSourceDirectory(project, "", false); + } + + + public static List getClassByServiceAnno(Project project, String anno) { + List className = Lists.newArrayList(); + PsiDirectory psiDirectory = getSourceDirectory(project); + List allJavaFiles = getAllJavaFiles(psiDirectory); + for (PsiJavaFile javaFile : allJavaFiles) { + for (PsiClass psiClass : javaFile.getClasses()) { + PsiAnnotation annotation = psiClass.getAnnotation(anno); + if (null != annotation) { + className.add(psiClass.getName()); + } + } + } + return className; + } + + private static List getAllJavaFiles(PsiDirectory dir) { + List javaFiles = new ArrayList<>(); + for (PsiFile file : dir.getFiles()) { + if (file instanceof PsiJavaFile) { + javaFiles.add((PsiJavaFile) file); + } + } + for (PsiDirectory subdir : dir.getSubdirectories()) { + javaFiles.addAll(getAllJavaFiles(subdir)); + } + return javaFiles; + } + + + /** + * 创建包路径 + * + * @param project + * @param packageName + */ + public static void createPackage(Project project, String packageName) { + if (project != null) { + // 获取项目的根目录 + PsiDirectory rootDirectory = PsiManager.getInstance(project).findDirectory(project.getBaseDir()); + if (rootDirectory != null) { + // 创建新的包 + @NonNls @NotNull String path = ProjectRootManager.getInstance(project).getContentSourceRoots()[0].getPath(); + WriteCommandAction.runWriteCommandAction(project, () -> { + DirectoryUtil.mkdirs(rootDirectory.getManager(), path + "/" + packageName.replace('.', '/')); + }); + } + } + } + + public static void createPackageInModule(Module module, String packageName) { + // 获取模块的根模型 + ModifiableRootModel modifiableRootModel = ModuleRootManager.getInstance(module).getModifiableModel(); + try { + // 获取模块的内容入口 + ContentEntry[] contentEntries = modifiableRootModel.getContentEntries(); + if (contentEntries.length > 0) { + // 通常情况下,我们使用第一个内容入口 + ContentEntry contentEntry = contentEntries[0]; + // 获取源文件夹的目录 + PsiDirectory directory = PsiManager.getInstance(module.getProject()).findDirectory(contentEntry.getFile()); + if (directory != null) { + // 使用 JavaDirectoryService 来创建或获取包 + PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(directory); + if (psiPackage != null) { + // 创建包路径 + String[] names = packageName.split("\\."); + for (String name : names) { + PsiDirectory subdirectory = directory.findSubdirectory(name); + if (subdirectory == null) { + // 如果子目录不存在,则创建它 + directory = directory.createSubdirectory(name); + } else { + directory = subdirectory; + } + } + } + } + } + } finally { + // 提交模块的根模型更改 + modifiableRootModel.commit(); + } + } + + public static List listMethodInfo(String clazz) { + return Lists.newArrayList(); + } + + /** + * 生成一个moon demo的handler + * + * @param project + */ + public static void generateMoonHandler(Project project) { + // 获取项目的根目录 + PsiDirectory rootDirectory = PsiManager.getInstance(project).findDirectory(project.getBaseDir()); + if (null != rootDirectory) { + @NonNls @NotNull String path = ProjectRootManager.getInstance(project).getContentSourceRoots()[0].getPath(); + } + String handlerName = "MoonDemoHandler"; + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); + // 获取最近的PsiClass + PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + PsiJavaFile psiJavaFile = (PsiJavaFile) currentPsiClass.getContainingFile(); + PsiPackage psiPackage = JavaPsiFacade.getInstance(currentPsiClass.getProject()).findPackage(psiJavaFile.getPackageName()); + String packageStr = psiPackage.getQualifiedName(); + // 创建一个类,写入class描述符是为了能打开它 + String text = "public class " + handlerName + "{}"; + JavaClassUtils.createClass(project, editor, handlerName, text, false, packageStr); + String qualifiedName = currentPsiClass.getQualifiedName(); + String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')); + deleteCode(project); + generateCodeWithAi(project, Prompt.get("moon_handler"), new String[]{packageName, "MoonDemoHandler"}); + } + + /** + * 获取当前类的package 路径 + * + * @param project + * @return 包路径 + */ + public static String getPackagePath(Project project) { + Editor editor = getEditor(project); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); + // 获取最近的PsiClass + PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + PsiJavaFile psiJavaFile = (PsiJavaFile) currentPsiClass.getContainingFile(); + PsiPackage psiPackage = JavaPsiFacade.getInstance(currentPsiClass.getProject()).findPackage(psiJavaFile.getPackageName()); + return psiPackage.getQualifiedName(); + } + + + @Override + public void execute(Context context, AnActionEvent e) { + this.next(context, e); + } + + public static void addClassAnno(Project project, PsiClass psiClass, List annoList) { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + PsiModifierList modifierList = psiClass.getModifierList(); + PsiAnnotation[] annotations = modifierList.getAnnotations(); + // 原来的注解 + List oldAnnoList = Arrays.stream(annotations).map(oldAnno -> "@" + oldAnno.getQualifiedName().substring(oldAnno.getQualifiedName().lastIndexOf('.') + 1)).toList(); + List addAnno = annoList.stream().filter(anno -> !oldAnnoList.contains(anno)).toList(); + List psiAnnotationList = addAnno.stream().map(i -> elementFactory.createAnnotationFromText(i, null)).toList(); + WriteCommandAction.runWriteCommandAction(project, () -> { + psiAnnotationList.forEach(anno -> modifierList.addBefore(anno, modifierList.getFirstChild())); + }); + } + + /** + * 删除这个编辑器中的所有内容 + * + * @param project + */ + public static void deleteCode(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + WriteCommandAction.runWriteCommandAction(project, () -> { + editor.getDocument().setText(""); + }); + Caret caret = editor.getCaretModel().getPrimaryCaret(); + caret.moveToOffset(0); + } + + public static void deleteTextRange(Project project, TextRange range) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + WriteCommandAction.runWriteCommandAction(project, () -> { + Document document = editor.getDocument(); + document.deleteString(range.getStartOffset(), range.getEndOffset()); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + } + + + public static boolean isClass(String text) { + if (text.contains(" class ")) { + return true; + } + return false; + } + + public static boolean isPrivateField(String text) { + if (text.contains("private") && text.contains(";")) { + return true; + } + return false; + } + + + private static Integer getNumFromStr(String str) { + Pattern pattern = Pattern.compile("\\d+"); + Matcher matcher = pattern.matcher(str); + String lineNumber = "0"; + if (matcher.find()) { + lineNumber = matcher.group(); + } + return Integer.valueOf(lineNumber); + } + + /** + * 通过chatgpt生成代码,然后插入编辑器中 + * + * @param project + * @param context + * @param prompt + */ + public static void generateCodeWithAi(Project project, String context, String[] prompt, BiConsumer consumer) { + String key = ConfigUtils.getConfig().getChatgptKey(); + try { + OpenaiCall.callStream(key, ProxyUtils.getProxy(), context, prompt, new StreamListener() { + @Override + public void onEvent(String str) { + consumer.accept(project, str); + } + + @Override + public void end() { + formatCode(project); + } + }, ReqConfig.builder().maxTokens(2000).build()); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + + public static void generateCodeWithAi2(Project project, String promptName, String[] pramas, BiConsumer consumer) { + generateCodeWithAi3(project, promptName, pramas, Maps.newHashMap(), consumer); + } + + + public static void generateCodeWithAi3(Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer) { + generateCodeWithAi4(project, promptName, pramas, paramMap, consumer, new MessageConsumer()); + } + + + public static void generateCodeWithAi4(Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer, MessageConsumer messageConsumer) { + generateCodeWithAi5(GenerateCodeReq.builder().promptName(promptName).project(project).build(), project, promptName, pramas, paramMap, consumer, messageConsumer); + } + + + @SneakyThrows + public static String call(String promptName, Map paramMap) { + //开启了本地模式(而且只有admin权限的用户可以) + if (ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_LOCAL, "false").equals("true")) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + String prompt = promptInfo.getData(); + if (StringUtils.isNotEmpty(prompt)) { + prompt = TemplateUtils.renderTemplate(prompt, paramMap.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().toString()))); + log.info(prompt); + } + } + + + ProxyAsk pa = new ProxyAsk(); + if (StringUtils.isNotEmpty(AthenaContext.ins().getGptModel())) { + pa.setModel(AthenaContext.ins().getGptModel()); + } + String id = UUID.randomUUID().toString(); + pa.setId(id); + pa.setPromptName(promptName); + pa.setParams(new String[]{}); + pa.setParamMap(paramMap); + pa.setZzToken(ConfigUtils.getConfig().getzToken()); + NotificationCenter.notice(null, "call prompt:" + promptName + " model:" + pa.getModel(), true); + StringBuilder sb = new StringBuilder(); + CountDownLatch latch = new CountDownLatch(1); + long begin = System.currentTimeMillis(); + OpenaiCall.callStream2(gson.toJson(pa), new StreamListener() { + @Override + public void begin() { + } + + @Override + public void onEvent(String str) { + str = new String(Base64.getDecoder().decode(str.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")); + log.info(str + " " + Arrays.toString(str.getBytes(Charset.forName("utf8")))); + sb.append(str); + } + + @Override + public void onFailure(Throwable t, Response response) { + if (null != t) { + log.error(t.getMessage(), t); + } + String message = getErrorMessage(t, response); + sb.append(message); + latch.countDown(); + } + + @Override + public void end() { + latch.countDown(); + } + }, ReqConfig.builder().connectTimeout(TimeUnit.SECONDS.toMillis(10)).readTimeout(TimeUnit.SECONDS.toMillis(20)).maxTokens(4096).askUrl(ConfigUtils.getConfig().getAiProxy() + "/ask").build()); + latch.await(10, TimeUnit.SECONDS); + NotificationCenter.notice(null, "call prompt:" + promptName + " model:" + pa.getModel() + "use time:" + (System.currentTimeMillis() - begin) + "ms", true); + return sb.toString(); + } + + + public static boolean isCursorInComment(Editor editor) { + // 获取光标的逻辑位置 + LogicalPosition logicalPosition = editor.getCaretModel().getLogicalPosition(); + int offset = editor.logicalPositionToOffset(logicalPosition); + + // 获取当前文件 + Document document = editor.getDocument(); + + // 获取光标位置 + CaretModel caretModel = editor.getCaretModel(); + int lineNumber = logicalPosition.line; + + // 获取当前行的文本 + String lineText = document.getText(new TextRange(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lineNumber))).trim(); + + // 检查该行是否以 "//" 开始 + if (lineText.startsWith("//")) { + return true; + } + + // 检查光标是否在多行注释中 + if (editor.getProject() != null) { + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(document); + if (psiFile == null) { + return false; + } + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiComment comment = PsiTreeUtil.getParentOfType(elementAtCaret, PsiComment.class); + return elementAtCaret instanceof PsiComment || comment != null; + } else { + return false; + } + } + + public static boolean isAtMultiCommentEnd(String line) { + return StringUtils.isNotEmpty(line) && line.trim().equals("*/"); + } + + public static boolean hasValidCharCnt(String line) { + return line.trim().length() > 2; + } + + // 当前caret是否不在任何方法里但是在类的大括号范围内, 且不在类的第一行(包含"{"的行)和最后一行(包含"}"的行) + public static boolean isCaretInClassButNotInMethod(Editor editor) { + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + int lineNumber = document.getLineNumber(offset); + + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(document); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); + PsiMethod psiMethod = PsiTreeUtil.getParentOfType(elementAtCaret, PsiMethod.class); + + if (psiClass == null || psiMethod != null) { + return false; + } + + int classStartLine = document.getLineNumber(psiClass.getTextRange().getStartOffset()); + int classEndLine = document.getLineNumber(psiClass.getTextRange().getEndOffset()); + + return lineNumber > classStartLine && lineNumber < classEndLine; + } + + + // 当前caret所在行是否只有一个注解 + public static boolean isCaretLineOnlyAnnotation(Editor editor) { + Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + int lineNumber = document.getLineNumber(offset); + int lineStartOffset = document.getLineStartOffset(lineNumber); + int lineEndOffset = document.getLineEndOffset(lineNumber); + String lineText = document.getText(new TextRange(lineStartOffset, lineEndOffset)).trim(); + return lineText.startsWith("@") && !lineText.contains(" "); + } + + + public static void generateCodeWithAi5(GenerateCodeReq req, Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer, MessageConsumer messageConsumer) { + try { + ProxyAsk pa = new ProxyAsk(); + setModelAndDebug(project, pa, paramMap, req); + String id = UUID.randomUUID().toString(); + pa.setId(id); + pa.setPromptName(promptName); + pa.setParams(pramas); + pa.setParamMap(paramMap); + pa.setZzToken(ConfigUtils.getConfig().getzToken()); + String projectName = project.getName(); + String strReq = gson.toJson(pa); + log.info("ask req:{}", strReq); + OpenaiCall.callStream2(strReq, new StreamListener() { + + @Override + public void begin() { + messageConsumer.begin(AiMessage.builder().projectName(projectName).type(AiMessageType.begin).id(id).build()); + } + + @Override + public void onEvent(String str) { + str = Base64Utils.decodeBase64String(str); + log.debug(str + " " + Arrays.toString(str.getBytes(Charset.forName("utf8")))); + consumer.accept(project, str); + messageConsumer.onEvent(AiMessage.builder().projectName(projectName).type(AiMessageType.process).id(id).text(str).build()); + } + + @Override + public void onFailure(Throwable t, Response response) { + if (null != t) { + log.error(t.getMessage(), t); + } + String message = getErrorMessage(t, response); + messageConsumer.failure(AiMessage.builder().projectName(projectName).id(id).text(message).type(AiMessageType.failure).build()); + NotificationCenter.notice("调用ai proxy发生了错误:" + message, NotificationType.ERROR); + } + + @Override + public void end() { + messageConsumer.end(AiMessage.builder().projectName(projectName).type(AiMessageType.success).id(id).build()); + if (req.isFormat()) { + formatCode(project); + } + } + }, ReqConfig.builder().connectTimeout(TimeUnit.SECONDS.toMillis(10)).readTimeout(TimeUnit.SECONDS.toMillis(60)).maxTokens(4000).askUrl(ConfigUtils.getConfig().getAiProxy() + "/ask").build()); + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + } + } + + public static void setModelAndDebug(Project project, ProxyAsk pa, Map paramMap, GenerateCodeReq req) { + int size = getCodeSize(paramMap); + if (StringUtils.isNotEmpty(AthenaContext.ins().getGptModel())) { + pa.setModel(AthenaContext.ins().getGptModel()); + int maxToken = AthenaContext.ins().getModel(pa.getModel()).getMaxToken(); + pa.setMaxToken(maxToken); + } else { + pa.setMaxToken(4000); + } + NotificationCenter.notice(project, "prompt:" + req.getPromptName() + " param size:" + size + " model:" + pa.getModel(), true); + pa.setDebug(AthenaContext.ins().isDebugAiProxy()); + } + + private static int getCodeSize(Map paramMap) { + int size = 0; + if (paramMap.containsKey("code")) { + size += paramMap.get("code").length(); + } + if (paramMap.containsKey("context")) { + size += paramMap.get("context").length(); + } + if (paramMap.containsKey("comment") && null != paramMap.get("comment")) { + size += paramMap.get("comment").length(); + } + return size; + } + + @NotNull + private static String getErrorMessage(Throwable t, Response response) { + String message = ""; + if (null != response) { + message = response.message(); + if (StringUtils.isNotEmpty(message)) { + message = "错误原因:" + message; + } else { + message = ""; + } + } + if (null != t) { + message += t.getMessage(); + } + return message; + } + + + public static void generateCodeWithAi(Project project, String context, String[] prompt) { + generateCodeWithAi(project, context, prompt, (p, code) -> { + writeCode(p, code); + }); + } + + /** + * 直接插入代码 + * + * @param project + * @param str + */ + public static void writeCode(Project project, String str) { + WriteCommandAction.runWriteCommandAction(project, () -> { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + Caret caret = editor.getCaretModel().getPrimaryCaret(); + Document document = editor.getDocument(); + int offset = caret.getOffset(); + editor.getDocument().insertString(offset, str); + int maxOffset = document.getTextLength(); + int nextLineStartOffset = caret.getOffset() + str.length(); + int insertOffset = maxOffset > nextLineStartOffset ? nextLineStartOffset : maxOffset; + caret.moveToOffset(insertOffset); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + } + ); + } + + /** + * 选中一个方法 + * + * @param project + */ + public static PsiMethod selectMethod(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (null == editor) { + return null; + } + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile == null) { + return null; + } + PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset()); + PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); + return method; + } + + public static void deleteMethod(Project project, PsiMethod method) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (null == editor) { + return; + } + + if (null == method) { + return; + } + Document document = editor.getDocument(); + int startOffset = method.getTextRange().getStartOffset(); + + editor.getCaretModel().getPrimaryCaret().moveToOffset(startOffset); + + int endOffset = method.getTextRange().getEndOffset(); + WriteCommandAction.runWriteCommandAction(project, () -> document.deleteString(startOffset, endOffset)); + } + + public static void deletePsiClass(Project project, PsiClass psiClass) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + Document document = editor.getDocument(); + int startOffset = psiClass.getTextRange().getStartOffset(); + editor.getCaretModel().getPrimaryCaret().moveToOffset(startOffset); + int endOffset = psiClass.getTextRange().getEndOffset(); + WriteCommandAction.runWriteCommandAction(project, () -> document.deleteString(startOffset, endOffset)); + } + + public static Editor getEditor(Project project) { + return EditorUtils.getEditor(project); + } + + public static Document getDocument(Project project) { + return getEditor(project).getDocument(); + } + + /** + * 添加空行 + * + * @param project + * @param document + * @param num + */ + public static void addLineBreak(Project project, Document document, int lineNum, int num) { + String v = "\n\t"; + int lineEndOffset = document.getLineEndOffset(lineNum - 1); + PsiClass pc = getPsiClass(project); + if (null != pc) { + int classOffset = pc.getTextRange().getEndOffset(); + lineEndOffset = Math.min(lineEndOffset, classOffset - 1); + v = "\n"; + } + int offset = lineEndOffset; + String str = Strings.repeat(v, num); + WriteCommandAction.runWriteCommandAction(project, () -> document.insertString(offset, str)); + PsiDocumentManager.getInstance(project).commitDocument(document); + } + + public static List getClassList(Project project, String end, String mn) { + GlobalSearchScope scope = StringUtils.isNotEmpty(mn) ? GlobalSearchScope.moduleScope(ProjectUtils.getModuleWithName(project, mn)) : GlobalSearchScope.projectScope(project); + Query query = AllClassesSearch.search(scope, project, s -> s.endsWith(end)); + Collection classes = query.findAll(); + return classes.stream().map(it -> { + String name = it.getQualifiedName(); + String moduleName = PsiClassUtils.getModule(project, it).getName(); + return ClassInfo.builder().className(name).moduleName(moduleName).build(); + }).collect(Collectors.toList()); + } + + private static String findPomDependencies(String basePath, String groupId, String artifactId, String version) throws IOException { + File baseDir = new File(basePath); + String[] extensions = {"xml"}; + boolean recursive = true; + + Collection pomFiles = FileUtils.listFiles(baseDir, extensions, recursive); + for (File pomFile : pomFiles) { + try { + MavenXpp3Reader reader = new MavenXpp3Reader(); + Model model = reader.read(new FileReader(pomFile)); + List dependencies = model.getDependencies(); + for (Dependency dependency : dependencies) { + if (dependency.getGroupId().equals(groupId) && + dependency.getArtifactId().equals(artifactId) && + dependency.getVersion().equals(version)) { + // 找到了指定的依赖项 + return "找到了"; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return "没找到"; + } + + /** + * 获取方法的注释 + * + * @param psiMethod + * @return + */ + public static String getMethodComment(PsiMethod psiMethod) { + PsiDocComment comment = psiMethod.getDocComment(); + if (comment != null) { + return comment.getText(); + } + return null; + } + + /** + * 获取属性的注释 + * + * @param psiField + * @return + */ + public static String getFieldComment(PsiField psiField) { + PsiDocComment comment = psiField.getDocComment(); + if (comment != null) { + return comment.getText(); + } + return ""; + } + + public static ImportCode createClassAndAddEmptyLine(Project project, String module, String packageName, String className, String classNameSuffix, boolean isTestClass, boolean isInterface) { + String qualifiedName = packageName + "." + className; + + PsiClass openJavaClass = CodeService.openJavaClass(project, qualifiedName + classNameSuffix); + if (null == openJavaClass) { + CodeService.createEmptyClass(project, module, packageName, className + classNameSuffix, isTestClass, isInterface); + openJavaClass = CodeService.openJavaClass(project, qualifiedName + classNameSuffix); + } + + Editor editor = CodeService.getEditor(project); + addEmptyLine(project, openJavaClass, editor); + + ImportCode importCode = new ImportCode(); + importCode.setProject(project); + importCode.setEditor(editor); + return importCode; + } + + private static void addEmptyLine(Project project, PsiClass openJavaClass, Editor editor) { + PsiMethod @NotNull [] methods = openJavaClass.getMethods(); + int offset = 0; + if (0 == methods.length) { + offset = openJavaClass.getTextRange().getEndOffset() - 3; + } else { + PsiMethod psiMethod = methods[methods.length - 1]; + offset = psiMethod.getTextRange().getEndOffset(); + } + editor.getCaretModel().moveToOffset(offset); + CodeService.writeCode2(project, editor, "\n"); + + } + + public static void tryParserBasedFix(String code, String projectName, String className) { + if (StringUtils.isBlank(code)) { + log.warn("empty code detected, projectName:{}, className:{}", projectName, className); + return; + } + AthenaClassInfo athenaClassInfo = AthenaCodeService.classInfoWithDetail(code, true); + Project project = ProjectUtils.projectFromManager(projectName); + PsiClass psiClass = PsiClassUtils.findClassByName(project, className); + // TODO: 根据className pattern制定fix规则 + M78Visitor m78Visitor = new M78Visitor(); + m78Visitor.setMissedImports(ImmutableList.of("org.bson.Document", "dev.morphia.annotations.Id")); + m78Visitor.setWildCardImportPackages(ImmutableList.of("java.util")); + psiClass.getParent().accept(m78Visitor); + // PsiClassFixer.fixUndefinedMethods(psiClass, project); + } + + public static void tryQuickFix(String code, JsonObject obj, String projectName, String className) { + if (StringUtils.isBlank(code)) { + log.warn("calling fix code with req:{}, but code is not generated yet, will do nothing...", obj); + return; + } + Project project = ProjectUtils.projectFromManager(projectName); + PsiClass psiClass = PsiClassUtils.findClassByName(project, className); + if (psiClass == null) { + log.warn("unable to find className:{} in project:{}, will quit quick fix...", className, projectName); + return; + } + PsiFile file = psiClass.getContainingFile(); + if (file == null) { + log.warn("unable to find psi file for className:{} in project:{}, will quit quick fix...", className, projectName); + return; + } + ApplicationManager.getApplication().invokeLater(() -> QuickFixInvokeUtil.quickFix2(project, file)); + } + + @Override + public void next(Context context, AnActionEvent e) { + super.next(context, e); + } + + public static T invoke(Supplier supplier) { + MutableObject mo = new MutableObject(); + ApplicationManager.getApplication().invokeAndWait(() -> { + Object obj = supplier.get(); + mo.setValue(obj); + }); + return (T) mo.getValue(); + } + + public static void invokeLater(Runnable runnable) { + ApplicationManager.getApplication().invokeLater(() -> runnable.run()); + } +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/DocumentService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/DocumentService.java new file mode 100644 index 000000000..5d7182480 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/DocumentService.java @@ -0,0 +1,107 @@ +/* + * Copyright 2020 Xiaomi + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.xiaomi.youpin.tesla.ip.service; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.impl.EditorImpl; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import org.apache.commons.lang.mutable.MutableObject; +import org.apache.commons.lang3.tuple.Pair; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + * @Author goodjava@qq.com + * @Date 2021/11/6 12:08 + */ +public class DocumentService { + + private static final Logger log = Logger.getInstance(DocumentService.class); + + /** + * 用ide打开文件 + * @param name + * @param text + */ + public void open(String name, String text) { + log.info("open file"); + Project project = ProjectManager.getInstance().getOpenProjects()[0]; + FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project); + try { + Files.write(Paths.get("/tmp/" + name), text.getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + (new WriteCommandAction.Simple(project) { + @Override + protected void run() { + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath("/tmp/" + name); + fileEditorManager.openFile(file, false); + } + }).execute(); + } + + /** + * 获取文件内容和文件名(content,fileName) + * @param anActionEvent + * @return + */ + public Pair getContent(AnActionEvent anActionEvent) { + log.info("get content"); + Editor editor = null; + if (null == anActionEvent) { + MutableObject mo = new MutableObject(); + ApplicationManager.getApplication().invokeAndWait(()->{ + Project project = ProjectManager.getInstance().getOpenProjects()[0]; + Editor e = FileEditorManager.getInstance(project).getSelectedTextEditor(); + mo.setValue(e); + }); + editor = (Editor) mo.getValue(); + } else { + editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + } + + if (null == editor) { + return null; + } + + String name = "tmp.java"; + if (editor instanceof EditorImpl) { + EditorImpl ei = (EditorImpl) editor; + name = ei.getVirtualFile().getName(); + System.out.println(name); + } + + Document document = editor.getDocument(); + String text = document.getText(); + return Pair.of(text, name); + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/EditorService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/EditorService.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/service/EditorService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/EditorService.java index 84ca1dac1..a44e4d5de 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/EditorService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/EditorService.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.intellij.openapi.editor.Editor; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/GuideService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/GuideService.java new file mode 100644 index 000000000..4273e356b --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/GuideService.java @@ -0,0 +1,464 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import cn.hutool.core.bean.BeanUtil; +import com.google.common.base.Splitter; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.RefreshQueue; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.impl.source.PsiMethodImpl; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.bo.z.EmbeddingStatus; +import com.xiaomi.youpin.tesla.ip.common.ConfigCenter; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.listener.Req; +import com.xiaomi.youpin.tesla.ip.ui.VersionUi; +import com.xiaomi.youpin.tesla.ip.util.*; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.mutable.MutableObject; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.CodeReq; +import run.mone.ultraman.bo.Version; +import run.mone.ultraman.common.ActionEventUtils; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.common.TestRunnerUtils; +import run.mone.ultraman.http.HttpClient; +import run.mone.ultraman.service.AthenaCodeService; +import run.mone.ultraman.service.ModuleService; +import run.mone.ultraman.state.ProjectFsmManager; + +import java.io.File; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2024/6/24 14:02 + */ +public class GuideService { + + private static Gson gson = GsonUtils.gson; + + private static ExecutorService pool = Executors.newSingleThreadExecutor(); + + /** + * AI引导方法,根据请求参数中的问题,获取相应的提示信息列表 + * + * @param req 请求参数对象,包含问题信息 + * @return 返回提示信息列表的JSON字符串 + */ + public static String aiGuide(Req req, Project project) { + AiCodeRes res = new AiCodeRes(); + String question = req.getData().get("question"); + if (question.equals("flush")) { + Prompt.flush(); + res.setMsg("flush success"); + return gson.toJson(res); + } + + if (question.startsWith("invoke_code:")) { + List list = Splitter.on(":").splitToList(question); + if (list.size() == 4) { + String codeName = list.get(1); + String method = list.get(2); + String param = list.get(3); + Object codeRes = ScriptService.ins().invoke(ScriptService.getScript(codeName), method, Maps.newHashMap(), param); + res.setMsg("invoke code success:" + codeRes); + } else { + res.setMsg(list + " list size != 4"); + } + return gson.toJson(res); + } + + //添加一个功能(entity mapper service controller),调用的事flow + if (question.startsWith("feature:")) { + callFlow(question, "256", project.getName(), new JsonObject()); + return gson.toJson(res); + } + + //添加一个功能(entity mapper service controller),调用的事flow (主要通过调用本地模板) + if (question.startsWith("feature2:")) { + String className = ApplicationManager.getApplication().runReadAction((Computable) () -> { + PsiClass psiClass = CodeService.getPsiClass(project); + return psiClass.getQualifiedName(); + }); + JsonObject object = new JsonObject(); + object.addProperty("codeGenClassName", className); + callFlow(question, "30016", project.getName(), object); + return gson.toJson(res); + } + + //生成单元测试类 + if (question.startsWith("cjunit")) { + ApplicationManager.getApplication().invokeLater(() -> { + List list = AnnoUtils.findClassWithAnno(project, "com.xiaomi.youpin.docean.anno.Service", null); + System.out.println(list); + list.stream().limit(3).forEach(ci -> { + String className = "run.mone.test.service." + ci.getSimpleName() + "Test"; + PsiClass psiClass = PsiClassUtils.findClassByName(project, className); + if (null != psiClass) { + return; + } + //创建这个PsiClass + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("testName", ci.getSimpleName() + "Test"); + jsonObject.addProperty("pojoName", ci.getSimpleName().replace("Service", "")); + String param = new String(Base64.getEncoder().encode(GsonUtils.gson.toJson(jsonObject).getBytes())); + ActionEventUtils.setupAndExecuteJavaAppConfiguration("run.mone.test.service.CodeGen", param, ProjectUtils.projectFromManager(project.getName())); + }); + }); + return gson.toJson(res); + } + + //直接生成单元测试(所有service直接生成单元测试) + if (question.startsWith("junit")) { + ApplicationManager.getApplication().invokeLater(() -> { + //查找到所有Service类 + List list = AnnoUtils.findClassWithAnno(project, "com.xiaomi.youpin.docean.anno.Service", null); + list.stream().forEach(ci -> { + String testClassName = "run.mone.test.service." + ci.getSimpleName() + "Test"; + //查看这个测试类是否存在,如果存在则直接跳过 + PsiClass psiClass = PsiClassUtils.findClassByName(project, testClassName); + if (null != psiClass) { + //获取单元测试的 + List methods = getNonConstructorMethodTexts(psiClass); + if (!methods.isEmpty()) { + return; + } + + //获取需要测试的那个类 + PsiClass pc = PsiClassUtils.findClassByName(project, ci.getClassName()); + if (null == pc) { + return; + } + + //获取实际要测试的类的方法集合 + @NotNull List mList = getNonConstructorMethodTexts(pc); + if (mList.isEmpty()) { + return; + } + + //保障单线程执行,一起操作ide,和一起操作ws都是有问题的 + pool.submit(() -> { + Mutable> mutable = new MutableObject<>(); + ApplicationManager.getApplication().invokeAndWait(()->{ + String testClassCode = PromptUtils.openUnitTestClass(project, testClassName); + Editor editor = CodeService.getEditor(project); + mutable.setValue(Pair.of(testClassCode, editor)); + }); + + String testClassCode = mutable.getValue().getKey(); + Editor editor = mutable.getValue().getValue(); + + mList.forEach(mText -> { + CountDownLatch latch = new CountDownLatch(1); + PromptUtils.generateUnitTest(project, mText, testClassName, new HashMap<>(), testClassCode, editor, latch); + try { + latch.await(20, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + //插入换行 + CodeService.writeCode2(project, editor, "\n\n"); + }); + + }); + + } + + }); + + + }); + return gson.toJson(res); + } + + //bug fix,调用的事flow + if (question.startsWith("fix")) { + JsonObject jo = new JsonObject(); + JsonObject input = new JsonObject(); + ApplicationManager.getApplication().invokeLater(() -> { + PsiMethod psiMethod = CodeService.getMethod(project); + TestRunnerUtils.runTest(project, psiMethod.getName(), pair -> { + //用来存储错误信息 + input.addProperty("input", pair.getValue()); + input.addProperty("host", AthenaContext.ins().getLocalAddress()); + input.addProperty("port", AthenaContext.ins().getLocalPort()); + input.addProperty("projectName", project.getName()); + jo.add("input", input); + + jo.addProperty("userName", AthenaContext.ins().getUserName()); + jo.addProperty("flowId", "60014"); + new Thread(() -> HttpClient.post("https://xxx", jo.toString())).start(); + }); + }); + return gson.toJson(res); + } + + if (question.startsWith("test")) { + ApplicationManager.getApplication().invokeLater(() -> PsiMethodUtils.extractMethodCallParts(project, CodeService.getEditor(project))); + return gson.toJson(res); + } + + if (question.startsWith("model")) { + List list = Splitter.on(":").splitToList(question); + if (list.size() == 2) { + AthenaContext.ins().setGptModel(list.get(1)); + res.setMsg("set model success model:" + list.get(1)); + } + return gson.toJson(res); + } + + if (question.startsWith("aidebug")) { + List list = Splitter.on(":").splitToList(question); + if (list.size() == 2) { + AthenaContext.ins().setDebugAiProxy(Boolean.valueOf(list.get(1))); + res.setMsg("ai debug:" + list.get(1)); + } + return gson.toJson(res); + } + + if (question.equals("refreshconfig")) { + ResourceUtils.getAthenaConfig(project, true); + res.setMsg("refresh config success"); + return gson.toJson(res); + } + + //获取作者信息 + if (question.equals("author")) { + return author(res); + } + + if (question.startsWith("troubleshoot")) { + RobotService.troubleshoot(null, RobotReq.builder().project(project).param(question).build()); + return ""; + } + + //获取embedding 信息 + if (question.equals("embedding_status")) { + return embeddingStatus(req, res, project); + } + + //打开配置 + if (question.equals("config")) { + ApplicationManager.getApplication().invokeLater(() -> LabelUtils.showLabelConfigUi(project)); + res.setMsg("show config success"); + return gson.toJson(res); + } + + if (question.equals("collected")) { + res.setMsg(" "); + res.setPromptInfoList(buildAiCodePromptRes(Prompt.getCollected())); + return gson.toJson(res); + } + + if (question.equals("debug")) { + res.setMsg(new Version().toString()); + return gson.toJson(res); + } + + //刷新业务代码到知识库 + if (question.equals("flush_biz")) { + return flushBizCode(req, res, project); + } + + if (question.equals("class_len")) { + return getClassLen(res, project); + } + + //停止状态机 + if (question.equals("stop")) { + ProjectFsmManager.stop(project.getName()); + res.setMsg("退出状态机"); + return gson.toJson(res); + } + + //git 代码push + if (question.equals("push")) { + PromptInfo promptInfo = Prompt.getPromptInfo("bot_call"); + ApplicationManager.getApplication().invokeLater(() -> PromptService.dynamicInvoke(GenerateCodeReq.builder().promptInfo(promptInfo).project(project).promptType(PromptType.executeBot).build())); + res.setMsg("push"); + return gson.toJson(res); + } + + //代码review + if (question.equals("review")) { + PromptInfo promptInfo = Prompt.getPromptInfo("bot_stream"); + ApplicationManager.getApplication().invokeLater(() -> PromptService.dynamicInvoke(GenerateCodeReq.builder().promptInfo(promptInfo).project(project).promptType(PromptType.executeBot).build())); + res.setMsg("review"); + return gson.toJson(res); + } + + //查询状态机状态 + if (question.equals("state")) { + String state = ProjectFsmManager.state(project.getName()); + res.setMsg("state:" + state); + return gson.toJson(res); + } + + //测试prompt + if (question.startsWith("prompt:")) { + String promptName = question.split(":")[1]; + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + PromptType promptType = Prompt.getPromptType(promptInfo); + ApplicationManager.getApplication().invokeLater(() -> { + PromptService.testPrompt(GenerateCodeReq.builder().project(project) + .promptName(promptName).promptInfo(promptInfo).promptType(promptType).build()); + }); + res.setMsg("ok"); + return gson.toJson(res); + } + + AiCodeRes cache = ConfigCenter.build(question); + if (null == cache) { + res.setMsg(Message.unsupportedCommand); + return gson.toJson(res); + } + res.setMsg(cache.getMsg()); + if (!"help".equals(question)) { + List promptRes = Lists.newArrayList(); + List promptList = Prompt.getPromptInfoByTag(cache.getTagName()); + promptRes.addAll(cache.getPromptInfoList()); + promptRes.addAll(buildAiCodePromptRes(promptList)); + res.setPromptInfoList(promptRes); + } else { + res.setPromptInfoList(cache.getPromptInfoList()); + } + return gson.toJson(res); + } + + @NotNull + private static List getNonConstructorMethodTexts(PsiClass psiClass) { + return Arrays.stream(psiClass.getMethods()).filter(it2 -> { + if (it2 instanceof PsiMethodImpl && !it2.isConstructor()) { + return true; + } + return false; + }).map(PsiElement::getText).collect(Collectors.toList()); + } + + private static void callFlow(String question, String flowId, String projectName, JsonObject jsonObject) { + List list = Splitter.on(":").splitToList(question); + JsonObject jo = new JsonObject(); + JsonObject input = new JsonObject(); + input.addProperty("input", list.get(1)); + input.addProperty("host", AthenaContext.ins().getLocalAddress()); + input.addProperty("port", AthenaContext.ins().getLocalPort()); + input.addProperty("projectName", projectName); + + jsonObject.keySet().forEach(key -> input.addProperty(key, jsonObject.get(key).getAsString())); + + jo.add("input", input); + jo.addProperty("userName", AthenaContext.ins().getUserName()); + jo.addProperty("flowId", flowId); + //异步化调用 + new Thread(() -> HttpClient.post("https://xx", jo.toString())).start(); + } + + + //获取当前打开类的长度 + private static String getClassLen(AiCodeRes res, Project project) { + MutableInt num = new MutableInt(); + ApplicationManager.getApplication().invokeAndWait(() -> { + String text = CodeService.getClassText(project); + num.setValue(text.length()); + }); + res.setMsg(String.valueOf(num.getValue())); + return gson.toJson(res); + } + + //获取作者信息 + private static String author(AiCodeRes res) { + ApplicationManager.getApplication().invokeLater(() -> { + VersionUi versionUi = new VersionUi(); + versionUi.show(); + }); + res.setMsg(new Version().toString()); + return gson.toJson(res); + } + + private static void refreshProject(String targetExtractionDir) { + VirtualFile targetFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(targetExtractionDir)); + RefreshQueue.getInstance().refresh(false, true, null, targetFile); + } + + private static List buildAiCodePromptRes(List promptInfoList) { + List list = promptInfoList.stream().filter(p -> p.getTags().stream().anyMatch(tag -> tag.getName().equals("plugin"))).map(promptInfo -> { + AiCodePromptRes promptRes = new AiCodePromptRes(); + BeanUtil.copyProperties(promptInfo, promptRes); + promptRes.setType("cmd"); + promptRes.setShowDialog(promptInfo.getLabels().getOrDefault("showDialog", "false")); + return promptRes; + }).collect(Collectors.toList()); + return list; + } + + //刷新业务代码到知识库 + private static String flushBizCode(Req req, AiCodeRes res, Project project) { + String moduleName = req.getData().get("module"); + String scope = req.getData().get("scope"); + ApplicationManager.getApplication().invokeLater(() -> { + if ("project".equals(scope)) { + //Refresh all modules. + List list = ProjectUtils.listAllModules(project).stream().filter(it -> !it.equals(req.getData().get("project"))).collect(Collectors.toList()); + list.stream().forEach(it -> ModuleService.uploadModelText(project, getModule(it, project))); + } else { + ModuleService.uploadModelText(project, getModule(moduleName, project)); + } + }); + res.setMsg("flush biz success"); + return gson.toJson(res); + } + + private static String embeddingStatus(Req req, AiCodeRes res, Project project) { + String scope = req.getData().getOrDefault("scope", "project"); + CodeReq.CodeReqBuilder builder = CodeReq.builder(); + builder.projectName(project.getName()); + if (!scope.equals("project")) { + builder.moduleName(getModule(req.getData().get("module"), project).getName()); + } + EmbeddingStatus status = AthenaCodeService.embeddingStatus(builder.build()); + String msg = scope.equals("project") ? ("project_" + req.getData().get("project")) : ("module_" + req.getData().get("module")); + res.setMsg(gson.toJson(status) + ":" + msg); + return gson.toJson(res); + } + + @Nullable + private static Module getModule(String moduleName, Project project) { + if (StringUtils.isEmpty(moduleName)) { + Mutable mutable = new MutableObject<>(); + ApplicationManager.getApplication().invokeAndWait(() -> { + mutable.setValue(ProjectUtils.getCurrentModule(project)); + }); + return mutable.getValue(); + } else { + return ProjectUtils.getModuleWithName(project, moduleName); + } + + + } +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/LocalAiService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/LocalAiService.java new file mode 100644 index 000000000..58f6daa4d --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/LocalAiService.java @@ -0,0 +1,520 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import cn.hutool.core.codec.Base64; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Message; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.*; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.MessageType; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Response; +import okhttp3.*; +import okhttp3.sse.EventSource; +import okhttp3.sse.EventSourceListener; +import okhttp3.sse.EventSources; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import run.mone.openai.OpenaiCall; +import run.mone.openai.ReqConfig; +import run.mone.openai.StreamListener; +import run.mone.ultraman.AthenaInspection; +import run.mone.ultraman.background.AthenaTask; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.state.ProjectFsmManager; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2023/11/23 13:56 + *

+ * 这个类允许你本地直连chatgpt(如果是国内的网络需要设置open_ai_proxy) + */ +@Slf4j +public class LocalAiService { + + + private static String getOpenAiUrl() { + String url = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_PROXY, ""); + if (StringUtils.isEmpty(url)) { + return "https://api.openai.com/v1/"; + } + return url; + } + + + /** + * 调用chatgpt的语音翻译(你需要有chatgpt的账号) + * + * @param file + * @return + */ + @SneakyThrows + public static Pair callChatgptTranscriptions(File file) { + String apiKey = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_KEY, ""); + + if (StringUtils.isEmpty(apiKey)) { + return Pair.of(500, "在环境变量中设置:OPENAI_API_KEY"); + } + + + RequestBody requestBody = RequestBody.create(MediaType.parse("audio/mpeg"), file); + + MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder(); + multipartBodyBuilder.setType(MultipartBody.FORM); + multipartBodyBuilder.addFormDataPart("file", "openai.mp3", requestBody); + multipartBodyBuilder.addFormDataPart("model", "whisper-1"); + + Request request = new Request.Builder() + .url(getOpenAiUrl() + "/audio/transcriptions") + .post(multipartBodyBuilder.build()) + .addHeader("Authorization", "Bearer " + apiKey) + .addHeader("Content-Type", "multipart/form-data") + .build(); + + OkHttpClient client = new OkHttpClient(); + + Response response = client.newCall(request).execute(); + + if (response.code() == 200) { + AudioRes res = new Gson().fromJson(response.body().string(), AudioRes.class); + return Pair.of(0, res.getText()); + } + + return Pair.of(500, ""); + } + + + /** + * 直接把文字转成语音 + * + * @param req + * @return + */ + @SneakyThrows + public static Pair speech(SpeechReq req) { + String apiKey = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_KEY, ""); + if (StringUtils.isEmpty(apiKey)) { + return Pair.of(500, "在环境变量中设置:OPENAI_API_KEY"); + } + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + MediaType mediaType = MediaType.parse("application/json"); + RequestBody body = RequestBody.create(mediaType, new Gson().toJson(req)); + Request request = new Request.Builder() + .url(getOpenAiUrl() + "/audio/speech") + .method("POST", body) + .addHeader("Authorization", "Bearer " + apiKey) + .addHeader("Content-Type", "application/json") + .build(); + Response response = client.newCall(request).execute(); + + if (response.code() == 200) { + byte[] saveData = response.body().bytes(); + Files.write(Paths.get("/tmp/sp.mp3"), saveData); + return Pair.of(0, Base64.encode(saveData)); + } + + return Pair.of(500, ""); + + } + + + //多模态调用(支持图片) + public static String vision(VisionReq req) { + String apiKey = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_KEY, ""); + if (StringUtils.isEmpty(apiKey)) { + return ""; + } + OkHttpClient client = new OkHttpClient().newBuilder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .build(); + MediaType mediaType = MediaType.parse("application/json"); + RequestBody body = RequestBody.create(mediaType, new Gson().toJson(req)); + Request request = new Request.Builder() + .url(getOpenAiUrl() + "/chat/completions") + .method("POST", body) + .addHeader("Content-Type", "application/json") + .addHeader("Authorization", "Bearer " + apiKey) + .build(); + try { + Response response = client.newCall(request).execute(); + String str = response.body().string(); + VisionRes visionRes = new Gson().fromJson(str, VisionRes.class); + System.out.println(visionRes.getChoices().get(0)); + return visionRes.getChoices().get(0).getMessage().getContent(); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + + + public static JsonObject call(List messageList) { + Completions completions = Completions.builder() + .stream(false) + .response_format(Format.builder().build()).messages(messageList).build(); + String req = GsonUtils.gson.toJson(completions); + return call(req); + } + + + public static JsonObject call(String req) { + return call(req, 5000); + } + + //这个会直接调用chatgpt + @SneakyThrows + public static JsonObject call(String req, long timeout) { + long time = timeout; + for (int i = 1; i <= 3; i++) { + time = time * i; + log.info("call gpt req:{} timeout:{}", req, timeout); + String apiKey = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_KEY, ""); + if (StringUtils.isEmpty(apiKey)) { + return null; + } + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(time, TimeUnit.MILLISECONDS) + .readTimeout(time, TimeUnit.MILLISECONDS) + .build(); + + MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); + + Request request = new Request.Builder() + .url(getOpenAiUrl() + "/chat/completions") + .addHeader("Content-Type", "application/json") + .addHeader("Authorization", "Bearer " + apiKey) + .post(RequestBody.create(mediaType, req.getBytes(Charset.forName("utf8")))) + .build(); + + try (Response response = client.newCall(request).execute()) { + // 判断请求是否成功 + if (response.isSuccessful() && response.body() != null) { + String responseBody = response.body().string(); + return parseJson(responseBody); + } else { + System.err.println("Request failed: " + response.code()); + } + } catch (IOException e) { + e.printStackTrace(); + TimeUnit.SECONDS.sleep(1); + } + } + return null; + } + + + //直接问问题(直接调用chatgpt) + public static void completions(String req, StreamListener sl) { + String apiKey = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_KEY, ""); + if (StringUtils.isEmpty(apiKey)) { + return; + } + MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); + + Request request = new Request.Builder() + .url(getOpenAiUrl() + "/chat/completions") + .addHeader("Content-Type", "application/json") + .addHeader("Authorization", "Bearer " + apiKey) + .post(RequestBody.create(mediaType, req.getBytes(Charset.forName("utf8")))) + .build(); + + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(5000, TimeUnit.MILLISECONDS) + .readTimeout(5000, TimeUnit.MILLISECONDS) + .build(); + + + EventSourceListener listener = new EventSourceListener() { + + @Override + public void onOpen(EventSource eventSource, Response response) { + log.info("onOpen"); + sl.begin(); + } + + @Override + public void onEvent(EventSource eventSource, String id, String type, String data) { + data = parse(data); + sl.onEvent(data); + } + + @Override + public void onClosed(EventSource eventSource) { + log.info("onClosed"); + sl.end(); + } + + @Override + public void onFailure(EventSource eventSource, Throwable t, Response response) { + log.info("onFailure response:" + response, t); + sl.onFailure(t, response); + sl.end(); + } + }; + + EventSource.Factory factory = EventSources.createFactory(client); + factory.newEventSource(request, listener); + } + + + private static String parse(String data) { + log.info(data); + if (data.equals("[DONE]")) { + return ""; + } + try { + JSONArray choices = JSON.parseObject(data).getJSONArray("choices"); + if (choices.isEmpty()) { + return ""; + } + + String obj = choices.getJSONObject(0).getJSONObject("delta").getString("content"); + if (null != obj) { + return obj; + } + return ""; + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + } + return ""; + } + + private static JsonObject parseJson(String data) { + log.info("data:{}", data); + JsonObject obj = GsonUtils.gson.fromJson(data, JsonObject.class); + JsonArray choices = obj.getAsJsonArray("choices"); + return GsonUtils.gson.fromJson(choices.get(0).getAsJsonObject().getAsJsonObject("message").get("content").getAsString(), JsonObject.class); + } + + //本地直接调用chatgpt,单条提问 + public static void localCall(Project project, String prompt) { + localCall(project, Lists.newArrayList(Message.builder().content(prompt).role("user").build()), false, 0); + } + + + public static void localCall(String projectName, boolean code) { + log.info("question call prompt"); + List> list = ProjectAiMessageManager.getInstance().getMessageList(projectName); + //转换为Message + List newMessageList = list.stream().map(it -> Message.builder().role(it.getRole().name()).content(it.toString()).build()).peek(it -> { + log.info("---->role:{} content:{}", it.getRole(), it.getContent()); + }).collect(Collectors.toList()); + String id = UUID.randomUUID().toString(); + chat(ProjectUtils.projectFromManager(projectName), code, newMessageList, projectName, id); + } + + + //目前是从前端拿到的,这个需要自己记录,这样以后能完成的事情更多 + public static void localCall(Project project, List messageList, boolean code, int num) { + //这是前端传过来的(以后只信任最后一条) + Message msg = messageList.get(messageList.size() - 1); + + boolean process = ProjectFsmManager.processMsg(project.getName(), msg.getContent()); + if (process) { + return; + } + + //这就是自己维护的那份消息列表(这里的id是判断这个msg的时候返回给前端的) + List> list = ProjectAiMessageManager.getInstance().addMessage(project, + AiChatMessage.builder() + .message(msg.getContent()) + .type(MessageType.string) + .data(msg.getContent()) + .id(msg.getId()) + .role(Role.user) + .build()); + + //转换为Message + List newMessageList = list.stream().map(it -> Message.builder().role(it.getRole().name()).content(it.toString()).build()).peek(it -> { + log.info("---->role:{} content:{}", it.getRole(), it.getContent()); + }).collect(Collectors.toList()); + + //取最后的一部分 + if (num != 0) { + newMessageList = getLastElements(newMessageList, num); + } + + + String projectName = project.getName(); + String msgId = UUID.randomUUID().toString(); + + // TODO 直接调用BOT + if("true".equals(ResourceUtils.get(Const.CONF_CHAT_USE_BOT, "true"))) { + Map param = new HashMap<>(); + param.put("chatContent", msg.getContent()); + AthenaInspection.invokePrompt(project, Const.ATHENA_CHAT, param); + return; + } + + //调用ai proxy + if (LabelUtils.open(project, Const.AI_PROXY_CHAT, "true")) { + aiProxyChat(project, newMessageList); + return; + } + + //直接本地调用 + chat(project, code, newMessageList, projectName, msgId); + } + + + public static List getLastElements(List list, int num) { + if (list == null || list.isEmpty() || num <= 0) { + return Collections.emptyList(); + } + int startIndex = Math.max(list.size() - num, 0); + return list.subList(startIndex, list.size()); + } + + private static void chat(Project project, boolean code, List newMessageList, String projectName, String id) { + ApplicationManager.getApplication().invokeLater(() -> AthenaTask.start(new Task.Backgroundable(project, "chat", true) { + @SneakyThrows + @Override + public void run(@NotNull ProgressIndicator indicator) { + String model = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_MODEL, "gpt-3.5-turbo"); + Completions completions = Completions.builder().model(model).messages(newMessageList).build(); + CountDownLatch latch = new CountDownLatch(1); + StringBuilder sb = new StringBuilder(); + LocalAiService.completions(GsonUtils.gson.toJson(completions), new StreamListener() { + + @Override + public void begin() { + AiMessage msg = AiMessage.builder().projectName(projectName).code(code).type(AiMessageType.begin).id(id).build(); + sendMsg(msg, projectName); + } + + @Override + public void onEvent(String str) { + AiMessage msg = AiMessage.builder().projectName(projectName).type(AiMessageType.process).id(id).text(str).build(); + sendMsg(msg, projectName); + sb.append(msg.getText()); + } + + + @Override + public void end() { + latch.countDown(); + AiMessage msg = AiMessage.builder().projectName(projectName).type(AiMessageType.success).id(id).build(); + sendMsg(msg, projectName); + String str = sb.toString(); + ProjectAiMessageManager.getInstance().addMessage(project, + AiChatMessage.builder().id(id).message(str).data(str).type(MessageType.string).role(Role.assistant).build()); + } + }); + latch.await(15, TimeUnit.SECONDS); + } + })); + } + + + //调用ai proxy(进行聊天) + private static void aiProxyChat(Project project, List newMessageList) { + ApplicationManager.getApplication().invokeLater(() -> AthenaTask.start(new Task.Backgroundable(project, "Athena", true) { + @SneakyThrows + @Override + public void run(@NotNull ProgressIndicator indicator) { + CountDownLatch latch = new CountDownLatch(1); + String projectName = project.getName(); + List msgList = newMessageList.stream().map(it -> { + Msg msg = new Msg(); + msg.setContent(it.getContent()); + msg.setRole(it.getRole().toUpperCase()); + return msg; + }).collect(Collectors.toList()); + try { + ProxyAsk pa = new ProxyAsk(); + pa.setMsgList(msgList); + pa.setType(1); + pa.setFrom("chat"); + CodeService.setModelAndDebug(project, pa, Maps.newHashMap(), GenerateCodeReq.builder().project(project).build()); + String id = UUID.randomUUID().toString(); + pa.setId(id); + pa.setZzToken(ConfigUtils.getConfig().getzToken()); + OpenaiCall.callStream2(GsonUtils.gson.toJson(pa), new StreamListener() { + + StringBuilder sb = new StringBuilder(); + + @Override + public void begin() { + AiMessage msg = AiMessage.builder().projectName(projectName).code(false).type(AiMessageType.begin).id(id).build(); + sendMsg(msg, projectName); + } + + @Override + public void onEvent(String str) { + str = new String(java.util.Base64.getDecoder().decode(str.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")); + AiMessage msg = AiMessage.builder().projectName(projectName).type(AiMessageType.process).id(id).text(str).build(); + sendMsg(msg, projectName); + sb.append(msg.getText()); + } + + @Override + public void onFailure(Throwable t, Response response) { + NotificationCenter.notice("调用ai proxy发生了错误:" + t.getMessage(), NotificationType.ERROR); + } + + @Override + public void end() { + latch.countDown(); + AiMessage msg = AiMessage.builder().projectName(projectName).type(AiMessageType.success).id(id).build(); + sendMsg(msg, projectName); + String str = sb.toString(); + ProjectAiMessageManager.getInstance().addMessage(project, + AiChatMessage.builder().id(id).message(str).data(str).type(MessageType.string).role(Role.assistant).build()); + } + }, ReqConfig.builder().connectTimeout(TimeUnit.SECONDS.toMillis(10)).readTimeout(TimeUnit.SECONDS.toMillis(30)).maxTokens(4000).askUrl(ConfigUtils.getConfig().getAiProxy() + "/ask").build()); + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + } + latch.await(1, TimeUnit.MINUTES); + } + })); + + + } + + //每次都只发一部分(发送到右侧 athena) + public static void sendMsg(AiMessage message, String projectName) { + String str = GsonUtils.gson.toJson(message); + ChromeUtils.call(projectName, "setResultCode", str); + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/M78Service.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/M78Service.java new file mode 100644 index 000000000..49ff0e22f --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/M78Service.java @@ -0,0 +1,79 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.common.base.Stopwatch; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.infra.rpc.Result; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.http.HttpClient; +import run.mone.ultraman.http.WsClient; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * @author HawickMason@xiaomi.com + * @date 6/6/24 16:22 + */ +@Slf4j +public class M78Service { + + public static Result speechToText2(JsonObject jsonObject) { + Map athenaConfig = ResourceUtils.getAthenaConfig(); + String apiSpeechToText2 = athenaConfig.get(Const.CONF_M78_URL) + + athenaConfig.get(Const.CONF_M78_SPEECH2TEXT); + String param = jsonObject.toString(); + log.info("calling:{}, param:{}", apiSpeechToText2, param); + String resp = HttpClient.callHttpServer(apiSpeechToText2, "callM78SpeechToText2", param, false, false, 30); + Result res = GsonUtils.gson.fromJson(resp, new TypeToken>() {}.getType()); + log.info("calling:{}, resCode:{}", apiSpeechToText2, res.getCode()); + return res; + } + + public static Result textToSpeech(JsonObject jsonObject) { + Map athenaConfig = ResourceUtils.getAthenaConfig(); + String apiTextToSpeech = athenaConfig.get(Const.CONF_M78_URL) + + athenaConfig.get(Const.CONF_M78_TEXT2SPEECH); + String param = jsonObject.toString(); + log.info("calling:{}, param:{}", apiTextToSpeech, param); + String resp = HttpClient.callHttpServer(apiTextToSpeech, "callM78TextToSpeech", param, false, false, 30); + Result res = GsonUtils.gson.fromJson(resp, new TypeToken>() {}.getType()); + log.info("calling:{}, resCode:{}", apiTextToSpeech, res.getCode()); + return res; + } + + public static Result uploadCodeInfo(String param) { + Map athenaConfig = ResourceUtils.getAthenaConfig(); + String uploadCodeInfo = athenaConfig.get(Const.CONF_M78_URL) + + athenaConfig.get(Const.CONF_M78_UPLOAD_CODE_INFO); + log.info("calling:{}, param:{}", uploadCodeInfo, param); + String resp = HttpClient.callHttpServer(uploadCodeInfo, "uploadCodeInfo", param, false, false, 30); + Result res = GsonUtils.gson.fromJson(resp, new TypeToken>() {}.getType()); + log.info("calling:{}, resCode:{}", uploadCodeInfo, res.getCode()); + return res; + } + + public static void imageHandle(Project project, JsonObject jsonObject) { + String projectName = project.getName(); + WsClient wsClient = new WsClient(); + wsClient.setProjectName(projectName); + String id = UUID.randomUUID().toString(); + wsClient.setId(id); + wsClient.init(getImageHandleConsumer(projectName)); + wsClient.send(jsonObject); + } + + private static Consumer getImageHandleConsumer(String projectName) { + return msg -> { + LocalAiService.sendMsg(msg, projectName); + }; + } +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PromptService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PromptService.java new file mode 100644 index 000000000..267d6a019 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PromptService.java @@ -0,0 +1,1001 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.common.base.CaseFormat; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationInfo; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.PsiMethodImpl; +import com.intellij.psi.impl.source.javadoc.PsiDocCommentImpl; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.search.GlobalSearchScope; +import com.unfbx.chatgpt.entity.chat.Message; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Completions; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Format; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.bo.z.ZKnowledgeRes; +import com.xiaomi.youpin.tesla.ip.common.*; +import com.xiaomi.youpin.tesla.ip.consumer.CodeConsumer; +import com.xiaomi.youpin.tesla.ip.consumer.FinishConsumer; +import com.xiaomi.youpin.tesla.ip.dialog.DialogReq; +import com.xiaomi.youpin.tesla.ip.dialog.DialogResult; +import com.xiaomi.youpin.tesla.ip.dialog.ParamTableDialog; +import com.xiaomi.youpin.tesla.ip.dialog.SelectClassAndMethodDialog; +import com.xiaomi.youpin.tesla.ip.framework.flex.Flex; +import com.xiaomi.youpin.tesla.ip.listener.OpenAiListener; +import com.xiaomi.youpin.tesla.ip.util.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.openai.Ask; +import run.mone.openai.OpenaiCall; +import run.mone.openai.ReqConfig; +import run.mone.openai.listener.AskListener; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.background.AthenaEditorTask; +import run.mone.ultraman.background.AthenaTask; +import run.mone.ultraman.bo.*; +import run.mone.ultraman.common.CodeUtils; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.common.TemplateUtils; +import run.mone.ultraman.manager.InlayHintManager; +import run.mone.ultraman.service.AiCodeService; +import run.mone.ultraman.service.AthenaCodeService; +import run.mone.ultraman.state.AthenaEvent; +import run.mone.ultraman.state.ProjectFsmManager; +import run.mone.ultraman.state.PromptAndFunctionProcessor; + +import java.util.*; +import java.util.stream.Collectors; + +import static com.xiaomi.youpin.tesla.ip.util.PromptUtils.*; + +/** + * @author goodjava@qq.com + * @author baoyu + * @date 2023/5/11 21:53 + *

+ * 这个类主要处理Prompt在Idea中的落地(写入编辑器) + */ +@Slf4j +public class PromptService { + + private static Gson gson = new Gson(); + + /** + * 动态执行 + * + * @param req + * @return + */ + public static String dynamicInvoke(GenerateCodeReq req) { + setReq(req); + switch (req.getPromptType()) { + case createClass -> createClass(req.getProject(), req.getModule().getName(), req.getPromptName()); + case createClass4 -> createClass4(req); + case createMethod -> createMethod(req); + case createMethod2 -> createMethod2(req); + case comment -> addComment(req); + case lineByLineComment -> lineByLineCommentOrCode(req.getPromptName(), req); + case createFile -> createFile(req.getPromptName(), req.getFileName(), req); + case modifyClass -> updateClass(req); + case modifyMethod -> modifyMethod(req); + case select -> select(req, req.getProject(), req.getModule(), req.getPromptInfo()); + case executeBot -> BotService.executeBot(req); + case removeComment -> removeComment(req.getProject()); + case showInfo -> showInfo(req); + case repleaceSelectContent -> repleaceSelectContent(req); + case testPrompt -> testPrompt(req); + case checkPomVersion -> checkPomVersion(req); + case generateBootStrapAnno -> generateAnnoForBootStrap(req.getPromptName(), req.getProject()); + case inlayHint -> inlayHint(req); + case genBizMethodCode -> genBizMethodCode(req); + case generateMethod -> generateMethod(req, req.getProject(), ""); + case bot -> RobotService.bot(req); + case generateTestMethod -> generateTestMethod(req); + case generateMiapiMethod -> generateMiapiMethod(req); + case generateInterface -> generateInterface(req); + case question -> question(req); + case createClass2 -> + createClass2(req.getProject(), req.getPromptName(), req.getShowDialog(), req.getParam()); + default -> { + return "UnSupport"; + } + } + return "ok"; + } + + + private static void createClass4(GenerateCodeReq req) { + String promptName = req.getPromptName(); + List> list = Lists.newArrayList(); + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + String prompt = promptInfo.getData(); + String code = getCode(req, new PromptContext()); + prompt = TemplateUtils.renderTemplate(prompt, ImmutableMap.of("code", code)); + list.add(AiChatMessage.builder().data(prompt).role(Role.user).build()); + List messageList = list.stream().map(it -> com.xiaomi.youpin.tesla.ip.bo.chatgpt.Message.builder().content(it.toString()).role(it.getRole().name()).build()).collect(Collectors.toList()); + Completions completions = Completions.builder() + .stream(false) + .response_format(Format.builder().build()).messages(messageList).build(); + JsonObject jsonObj = AiService.call(GsonUtils.gson.toJson(completions), Long.valueOf(promptInfo.getLabels().getOrDefault("timeout", "50000")), true); + System.out.println(jsonObj); + String className = jsonObj.get("name").getAsString(); + String generateCode = jsonObj.get("code").getAsString(); + String packageStr = jsonObj.get("package").getAsString(); + PsiClassUtils.createClass(req.getProject(), packageStr, className, generateCode); + } + + //ai会向你提问(绝大部分分多步的操作,ai问你更合适) + private static void question(GenerateCodeReq req) { + String projectName = req.getProjectName(); + ProjectFsmManager.map.get(projectName) + .getFsm() + .getEventQueue().add(AthenaEvent.builder() + .promptInfo(req.getPromptInfo()) + .project(req.getProjectName()) + .promptType(req.getPromptType()) + .build()); + } + + //后边代码尽量用这里获取的内容,editor中的内容放入到req中,避免后边的再次获取 + public static void setReq(GenerateCodeReq req) { + ApplicationManager.getApplication().runReadAction(() -> { + Safe.run(() -> { + Project project = req.getProject(); + req.setProjectName(project.getName()); + String moduleName = getModuleName(req); + //当前module的名字 + req.setModuleName(moduleName); + //所有module的列表 + req.setModuleNameList(ProjectUtils.listAllModules(project).stream().filter(it -> !it.equals(project.getName())).collect(Collectors.toList())); + Editor editor = CodeService.getEditor(project); + if (null != editor) { + req.setEditor(editor); + VirtualFile vf = editor.getVirtualFile(); + String fileName = vf.getName(); + req.setFileName(fileName); + PsiClass psiClass = CodeService.getPsiClass(project); + if (null != psiClass) { + req.setQualifiedName(psiClass.getQualifiedName()); + req.setClassPackage(getClassPackage(psiClass.getQualifiedName())); + req.setClassName(psiClass.getName()); + req.setClassCode(psiClass.getText()); + + //这个类的父类或者接口中已经实现的方法定义 + Set methodSet = PsiClassUtils.findInheritedNonPrivateNonStaticMethods(psiClass); + List inheritedMethods = methodSet.stream().map(it -> { + return PsiClassUtils.generateMethodSignature(it); + }).collect(Collectors.toList()); + req.setInheritedMethods(inheritedMethods); + } + PsiMethod psiMethod = CodeService.getMethod(project); + if (null != psiMethod) { + req.setPsiMethod(psiMethod); + req.setMethodCode(psiMethod.getText()); + req.setLineNumberedMethod(CodeService.getMethodAndLineNumbers(psiMethod)); + } + //选中的内容 + req.setSelectText(EditorUtils.getSelectedContentOrLine(editor, false)); + //当前行的内容 + req.setCurrentLine(EditorUtils.getCurrentLineContent(editor)); + Document document = FileDocumentManager.getInstance().getDocument(editor.getVirtualFile()); + if (null != document) { + //这里可能有多个class的内容 + String virtualFileText = document.getText(); + req.setVirtualFileText(virtualFileText); + } + req.setClassCode2(CodeService.getClassText2(project)); + + CaretModel caretModel = editor.getCaretModel(); + if (null != caretModel) { + int offset = caretModel.getOffset(); + req.setOffset(offset); + req.setClassCodeWithMark(replaceCaretWithCode(offset, document)); + } + // 如果是根据注释生成代码,且满足规则,则获取注释 + setCommentInParam(req, editor); + } + req.setSystemName(System.getProperty("os.name")); + req.setIdeaVersion(ApplicationInfo.getInstance().getBuild().asString()); + req.setPluginVersion(new Version().toString()); + }); + }); + } + + private static void setCommentInParam(GenerateCodeReq req, Editor editor){ + if(Action.GENERATE_CODE == ActionUtils.getActionByReq(req)){ + PsiComment comment = EditorUtils.getPsiComment(editor); + if(comment != null && EditorUtils.isCommentInsideClass(comment) + && EditorUtils.isNotClassHeaderComment(comment) + && EditorUtils.isNotMethodComment(comment)){ + Map param = req.getParam(); + if(param == null){ + param = new HashMap<>(); + param.put(Const.GENERATE_CODE_COMMENT, comment.getText().trim()); + req.setParam(param); + }else if (!param.containsKey(Const.GENERATE_CODE_COMMENT)){ + param.put(Const.GENERATE_CODE_COMMENT, comment.getText().trim()); + } + } + } + } + + // 根据传入的carte的位置和psiClass, 将psiClass中caret所在位置替换为"$$这里需要补全代码$$"并返回替换后的代码字符串,不要影响原来的psiClass + public static String replaceCaretWithCode(int caret, Document document) { + if (document == null) { + return ""; + } + String classText = document.getText(); + StringBuilder modifiedText = new StringBuilder(classText); + modifiedText.replace(caret, caret, "$$这里需要补全代码$$"); + return modifiedText.toString(); + } + + private static String getClassPackage(String qualifiedName) { + int lastDotIndex = qualifiedName.lastIndexOf('.'); + if (lastDotIndex >= 0) { + return qualifiedName.substring(0, lastDotIndex); + } + return ""; + } + + + //获取编辑器的注释信息 + private static String getComment(Editor editor) { + return getComment(editor, "//biz:"); + } + + private static String getComment(Editor editor, String str) { + String content = EditorUtils.getSelectContent(editor); + if (content.contains(str)) { + int index = content.indexOf(str) + str.length(); + return content.substring(index); + } + return content; + } + + + /** + * 生成业务方法 + * + * @param req + */ + public static void genBizMethodCode(GenerateCodeReq req) { + Editor editor = CodeService.getEditor(req.getProject()); + if (StringUtils.isEmpty(req.getComment())) { + req.setComment(getComment(editor)); + } + CodeService.moveCaretToEndOfLine(editor); + CodeService.writeCode(req.getProject(), "\n"); + Map m = new HashMap<>(); + m.put("comment", req.getComment()); + //添加代码 + addCode(req, m, new PromptContext()); + //添加上下文 + addContext(req, m, new PromptContext()); + ImportCode importCode = new ImportCode(); + importCode.setProject(req.getProject()); + importCode.setEditor(editor); + + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena:Biz", m, new MessageConsumer() { + @Override + public void onEvent(AiMessage message) { + importCode.append(message.getText()); + } + })); + + } + + private static String addCode(GenerateCodeReq req, Map m, PromptContext context) { + String code = getCode(req, context); + //如果class code 太大,这里需要筛选出需要的method + if (code.length() > AthenaCodeService.CLASS_MAX_LEN && "class".equals(context.getScope())) { + if (StringUtils.isNotEmpty(req.getChatComment())) { + List list = AthenaCodeService.getMethodCodeList(CodeReq.builder().code(code).requirement(req.getChatComment()).build()); + if (list.size() > 0) { + code = list.stream().collect(Collectors.joining("\n")); + } + } + } + m.put("code", code); + if (StringUtils.isNotEmpty(req.getMethodCode())) { + m.put("methodCode", req.getMethodCode()); + } + return code; + } + + + //添加上下文信息到映射中 + public static void addContext(GenerateCodeReq req, Map m, PromptContext promptContext) { + Mutable context = new MutableObject<>(); + String scope = req.getScope(); + if (!StringUtils.isEmpty(scope)) { + promptContext.setScope(scope); + //method不需要计算任何上下文 + if (scope.equals("method")) { + promptContext.setScope("method"); + m.put("context", ""); + return; + } + } + //可以粗略的认为是把@Resource的类导入到上下文 + processGenerateCodeReq(req, promptContext, context); + m.put("context", context.getValue()); + } + + private static void processGenerateCodeReq(GenerateCodeReq req, PromptContext promptContext, Mutable context) { + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "context")) { + ApplicationManager.getApplication().runReadAction(() -> { + PsiClass clazz = CodeService.getPsiClass(req.getProject()); + if (null == clazz) { + return; + } + List list = PsiClassUtils.findFieldsWithResourceAnnotation(clazz); + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "ai_context")) { + List resourceCode = list.stream().map(it -> it.getType().getCanonicalText()).toList(); + promptContext.setResourceCode(resourceCode); + //设置po列表信息 + setPoList(promptContext, list); + } else { + List classList = PsiClassUtils.getClassText(req.getProject(), list); + context.setValue(Joiner.on("\n").join(classList)); + } + + //用Service那种模式的Flex + setPoClassInfo(promptContext, clazz); + }); + } + } + + private static void setPoClassInfo(PromptContext promptContext, PsiClass clazz) { + String boCode = Flex.findAndProcessServiceImplWithGeneric(clazz); + if (StringUtils.isNotEmpty(boCode)) { + List polist = promptContext.getPoClassInfos(); + if (null == polist) { + polist = Lists.newArrayList(PoClassInfo.builder().code(boCode).name("").build()); + } else { + polist.add(PoClassInfo.builder().code(boCode).name("").build()); + } + promptContext.setPoClassInfos(polist); + } + } + + private static void setPoList(PromptContext promptContext, List list) { + Map map = Maps.newHashMap(); + list.stream().forEach(it -> { + if (it.getType() instanceof PsiClassType pct) { + PsiClass psiClass = pct.resolve(); + Pair pair = Flex.getBaseMapperGenericTypeNameAndText(psiClass); + if (StringUtils.isNotEmpty(pair.getKey())) { + map.put(pair.getKey(), pair.getValue()); + } + } + }); + promptContext.setPoClassInfos(map.entrySet().stream().map(it -> { + return PoClassInfo.builder().name(it.getKey()).code(it.getValue()).build(); + }).collect(Collectors.toList())); + } + + public static String getResourceFromAi(Project project, Map m, PromptContext promptContext, List resourceCode) { + List resouceList = new ArrayList<>(); + if (resourceCode.size() > 3 && AthenaContext.ins().gptModel().isOptimizeTokens()) { + // 用chatGpt分析一遍需要用到哪些resource下的内容 + Map resourceMap = new HashMap<>(); + resourceMap.put("beanList", gson.toJson(resourceCode)); + String comment = ""; + if (m.get("comment") == null) { + comment = m.get("code"); + } + resourceMap.put("comment", comment); + String res = CodeService.call("ai_context", resourceMap); + + if (StringUtils.isEmpty(res)) { + return ""; + } + List tmpList = gson.fromJson(res, new TypeToken>() { + }.getType()); + resouceList.addAll(tmpList); + } else { + resouceList.addAll(resourceCode); + } + + //如果resource里边已经有了,则module context就不需要再次引入了 + promptContext.setResourceBeanList(resouceList); + + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + String context = resouceList.stream().map(it -> { + String str = PsiClassUtils.getClassText(project, it); + return str; + }).collect(Collectors.joining("\n")); + return context; + }); + } + + + public static void inlayHint(GenerateCodeReq req) { + req.setFormat(false); + CodeService.insertCode(req.getProject(), "", false); + PromptInfo promptInfo = Prompt.getPromptInfo("hi2"); + PromptType promptType = Prompt.getPromptType(promptInfo); + Map m = new HashMap<>(); + Editor editor = CodeService.getEditor(req.getProject()); + //添加代码 + addCode(req, m, new PromptContext()); + //添加上下文 + addContext(req, m, new PromptContext()); + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena", m, new FinishConsumer() { + + @Override + public void end(AiMessage message) { + String content = getContent(); + ApplicationManager.getApplication().invokeLater(() -> { + String newLines = "\n".repeat(content.split("\n").length); + WriteCommandAction.runWriteCommandAction(req.getProject(), () -> { + editor.getDocument().insertString(offset, newLines); + PsiDocumentManager.getInstance(req.getProject()).commitDocument(editor.getDocument()); + }); + InlayHintManager.ins().addInlayHint(editor, offset, content); + }); + } + })); + } + + /** + * 测试prompt的接口 + * + * @param req + */ + public static void testPrompt(GenerateCodeReq req) { + //从aiproxy获取参数列表 + Map map = getParamsFromAiProxy(req.getPromptName(), req.getPromptInfo().getMeta()); + //输入prompt参数 + ParamTableDialog table = new ParamTableDialog(ParamDialogReq.builder().title("test prompt").build(), req.getProject(), map, ImmutableMap.of(), req.getPromptInfo()); + table.setConsumer(values -> { + Editor editor = EditorUtils.getOrOpenEditor(req.getProject(), "prompt.md", ""); + Map m = table.getValuesMap().entrySet().stream().collect(Collectors.toMap(it -> it.getKey(), it -> it.getValue().toString())); + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena", m, new CodeConsumer(editor, req))); + }); + table.show(); + } + + private static void repleaceSelectContent(GenerateCodeReq req) { + Editor editor = CodeService.getEditor(req.getProject()); + if (null == editor) { + HintUtils.show(req.getProjectName(), com.xiaomi.youpin.tesla.ip.bo.Message.selectTextMsg, true); + return; + } + String text = getCode(req, new PromptContext()); + if (StringUtils.isNotEmpty(text)) { + SelectionModel selectionModel = editor.getSelectionModel(); + if (selectionModel.hasSelection()) { + int start = selectionModel.getSelectionStart(); + int end = selectionModel.getSelectionEnd(); + Document document = CodeService.getDocument(req.getProject()); + AthenaEditorTask task = new AthenaEditorTask(req, "Athena", ImmutableMap.of("code", text), new MessageConsumer() { + private StringBuilder sb = new StringBuilder(); + + @Override + public void onEvent(AiMessage message) { + sb.append(message.getText()); + } + + @Override + public void end(AiMessage message) { + WriteCommandAction.runWriteCommandAction(req.getProject(), () -> { + document.replaceString(start, end, sb.toString()); + PsiDocumentManager.getInstance(req.getProject()).commitDocument(document); + }); + } + }); + AthenaEditorTask.start(task); + } + } + } + + @NotNull + private static String getModuleName(GenerateCodeReq req) { + String moduleName = ""; + if (null == req.getModule()) { + Module module = ProjectUtils.getCurrentModule(req.getProject()); + if (null != module) { + req.setModule(module); + moduleName = module.getName(); + } + } else { + moduleName = req.getModule().getName(); + } + return moduleName; + } + + /** + * 在聊天窗口显示信息 + * + * @param req + */ + public static void showInfo(GenerateCodeReq req) { + //不需要格式化代码 + req.setFormat(false); + //在聊天框显示 + req.setTaskType("chat"); + generateMethod(req); + } + + + public static void generateMethod(Project project, String content) { + ClientData clientData = AthenaContext.ins().getClientData(project.getName()); + GenerateCodeReq req = AiCodeService.getGenerateCodeReq(project, clientData.getScope(), content); + req.setEditor(CodeService.getEditor(project)); + req.setModule(ProjectUtils.getCurrentModule(project)); + req.setTaskType("edit"); + PromptService.setReq(req); + PromptService.generateMethod(req); + //添加到聊天框 + ChromeUtils.call(req.getProject().getName(), content, 0); + } + + + public static void generateMethod(GenerateCodeReq req) { + generateMethod(req, true); + } + + + //创建方法都收口在这里了 + public static AthenaTask generateMethod(GenerateCodeReq req, boolean startTask) { + Project project = req.getProject(); + String promptName = req.getPromptName(); + Map aiReqMap = new HashMap<>(); + initAiReqMap(req, aiReqMap); + //如果是chat,这里拿到的会是注释 + PromptContext context = new PromptContext(); + context.setProject(project.getName()); + context.setModule(req.getModule().getName()); + context.setEditor(req.getEditor()); + String code = addCode(req, aiReqMap, context); + + if (StringUtils.isEmpty(code) && req.getPromptInfo().open("needCode")) { + log.info("code is empty prompt name:{}", promptName); + return null; + } + + AthenaTask task = new AthenaTask(project, "Athena", promptName, code, aiReqMap); + //在这里的都是异步执行 + task.setInitRunnable(() -> { + if (StringUtils.isNotEmpty(req.getUserSettingScope())) { + req.setScope(req.getUserSettingScope()); + } else { + //自动分析scope + if (req.getPromptInfo().open("analysis_scope") && AthenaContext.ins().gptModel().isSupportJsonResponse()) { + analysisScope(req, context); + } else { + req.setScope("class"); + } + } + addContext(req, aiReqMap, context); + addClass(req, aiReqMap, context); + addField(req, aiReqMap); + addInheritedMethods(req, aiReqMap, context); + }); + + task.setReq(req); + task.setFormat(req.isFormat()); + task.setPromptContext(context); + task.setType(req.getTaskType()); + if (startTask) { + AthenaTask.start(task); + } + return task; + } + + //添加抽象类或interface中已经实现的方法定义 + public static void addInheritedMethods(GenerateCodeReq req, Map aiReqMap, PromptContext context) { + if (null == req.getInheritedMethods()) { +// NotificationCenter.notice(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE, NotificationType.ERROR); +// throw new RuntimeException(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE); + log.error(ErrorMessage.ERR_NOT_IN_CLASS_SCOPE); + } else { + aiReqMap.put("inheritedMethods", req.getInheritedMethods().stream().collect(Collectors.joining("\n\n\n"))); + } + } + + private static void initAiReqMap(GenerateCodeReq req, Map aiReqMap) { + aiReqMap.put("current_module_name", req.getModuleName()); + aiReqMap.put("project_module_list", req.getModuleNameList().stream().collect(Collectors.joining(","))); + } + + public static void analysisScope(GenerateCodeReq req, PromptContext context) { + Map m = new HashMap<>(); + m.put("class", req.getClassCode()); + //获取方法签名(代码补全的时候) + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "method_info")) { + m.put("code", req.getMethodCode()); + } else { + //获取注释 + String comment = req.getParam().getOrDefault(Const.GENERATE_CODE_COMMENT, req.getChatComment()); + if (StringUtils.isEmpty(comment)) { + comment = req.getCurrentLine(); + } + if (StringUtils.isEmpty(comment)) { + context.setScope("class"); + req.setScope("class"); + return; + } + m.put("code", comment); + String scope = com.xiaomi.youpin.tesla.ip.common.StringUtils.extractEndingKeyword(comment); + //不再计算scope + if (StringUtils.isNotEmpty(scope)) { + context.setScope(scope); + req.setScope(scope); + return; + } + } + initAiReqMap(req, m); + PromptInfo promptInfo = Prompt.getPromptInfo("analysis_scope"); + JsonObject obj = PromptAndFunctionProcessor.callPrompt(req.getProject(), promptInfo, m); + String scope = obj.get("scope").getAsString(); + context.setScope(scope); + req.setScope(scope); + } + + //计算两数和 + + public static void addField(GenerateCodeReq req, Map map) { + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "select_field")) { + map.put("field", CodeService.getPsiField(req.getProject()).getName()); + } + } + + public static void addClass(GenerateCodeReq req, Map map, PromptContext context) { + map.put("lang", "java"); // HINT: 标记来源 + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "add_class") && !"method".equals(context.getScope())) { + List list = AthenaCodeService.parseMethodCode(req.getClassCode()); + List fieldList = AthenaCodeService.parseFieldCode(req.getClassCode()); + //通过需求生成的代码,class不能用全部的,不然会超过预期 + if (StringUtils.isNotEmpty(context.getComment())) { + //后边异步计算 + context.setMethodCodeList(list); + context.setFieldCodeList(fieldList); + context.setClazzName(req.getClassName()); // HINT: class如果使用FQCN则不能被parse + } + + //完成脱敏 + String classCode = AiCodeService.desensitizeCode(req.getClassCode()); + log.info("desensitize code class:{}", classCode); + map.put("class", classCode); + map.put("fqcn", req.getQualifiedName()); //HINT: FQCN单独传递, 在prompt模板中需要使用自定义函数 ${prompt_value('fqcn','')}来实现向下兼容 + } else { + map.put("class", ""); + } + } + + + public static String getCode(GenerateCodeReq req, PromptContext context) { + String text = ""; + if (req.getPromptInfo().open("selectComment")) { + text = req.getChatComment(); + context.setComment(text); + } + if (req.getPromptInfo().open("selectText")) { + text = req.getSelectText(); + if (StringUtils.isEmpty(text)) { + HintUtils.show(req.getEditor(), com.xiaomi.youpin.tesla.ip.bo.Message.selectTextMsg, true); + } + } + if (req.getPromptInfo().open("selectMethod")) { + context.setScope("method"); + text = req.getMethodCode(); + if (StringUtils.isEmpty(text)) { + HintUtils.show(req.getEditor(), com.xiaomi.youpin.tesla.ip.bo.Message.selectMethodMsg, true); + } + } + if (req.getPromptInfo().open("selectClass")) { + context.setScope("class"); + context.setProject(req.getProject().getName()); + context.setModule(!Objects.isNull(req.getModule()) ? req.getModule().getName() : ProjectUtils.getCurrentModule(req.getProject()).getName()); + text = req.getClassCode(); + } + + //选择整个java文件(里边有package信息) + if (req.getPromptInfo().open("selectFile")) { + text = req.getVirtualFileText(); + } + + if (req.getPromptInfo().open("selectClassName")) { + text = req.getQualifiedName(); + } + + if (req.getPromptInfo().open("commitFile")) { + text = GitUtils.getAffectedFileNames(req.getProject()).stream().collect(Collectors.joining("\n")); + } + + if (req.getPromptInfo().open("selectClass2")) { + text = req.getClassCode2(); + } + return text == null ? "" : text; + } + + /** + * 删除逐行注释 + * + * @param project + */ + private static void removeComment(Project project) { + PsiMethod psiMethod = CodeService.getMethod(project); + Editor editor = CodeService.getEditor(project); + if (null == psiMethod) { + HintUtils.show(editor, com.xiaomi.youpin.tesla.ip.bo.Message.selectMethodMsg, true); + return; + } + PsiMethodUtils.deleteCommentsFromMethod(project, psiMethod, comment -> comment.getText().startsWith("//Athena:")); + } + + /** + * 生成方法(在edit中) + * + * @param project + * @param text + */ + public static void generateMethod(GenerateCodeReq req, Project project, String text) { + Editor codeEditor = CodeService.getEditor(project); + if (StringUtils.isEmpty(text)) { + text = getComment(codeEditor, "//ai:"); + } + CodeService.moveCaretToEndOfLine(codeEditor); + CodeService.writeCode2(project, codeEditor, "\n"); + + req.setChatComment(text); + generateMethod(req); + } + + + private static void createMethod(GenerateCodeReq req) { + Project project = req.getProject(); + Editor editor = CodeService.getEditor(project); + CodeService.writeCode2(project, editor, "\n"); + CodeService.generateCodeWithAi2(project, req.getPromptName(), new String[]{req.getMeta()}, (p, code) -> CodeService.writeCode2(p, editor, code)); + } + + /** + * 创建方法2 + *

+ * 会打开两个表单 + * 1.填参数 + * 2.选中类和方法 + * + *

+ * 选择类和方法,然后插入代码 + *

+ * 可以用来生成Controller中的方法 + * + * @param req + */ + public static void createMethod2(GenerateCodeReq req) { + String promptName = req.getPromptName(); + Project project = req.getProject(); + PsiMethod pm = CodeService.getMethod(req.getProject()); + //没有选中方法(目前创建方法是根据某个已经选中的方法) + if (null == pm) { + HintUtils.show(CodeService.getEditor(req.getProject()), com.xiaomi.youpin.tesla.ip.bo.Message.selectMethodMsg, true); + return; + } + + String mn = pm.getName(); + + String methodCode = pm.getText(); + PsiClass pc = CodeService.getPsiClass(req.getProject()); + + String serviceName = pc.getQualifiedName(); + String shortServiceName = pc.getNameIdentifier().getText(); + + //选择类的label + String cmd = req.getPromptInfo().getLabels().get("cmd"); + String type = req.getPromptInfo().getLabels().get("type"); + String name = req.getPromptInfo().getLabels().get("name"); + + //获取需要填写那些参数 + Map map = getParamsFromAiProxy(promptName, req.getPromptInfo().getMeta()); + + setLabels(req, map); + map.put("methodName", mn); + map.put("serviceName", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, shortServiceName)); + + String reqPackage = LabelUtils.getLabelValue(req.getProject(), req.getPromptInfo(), Const.REQ_PACKAGE, Const.DEFAULT_REQ_PACKAGE); + List list = PackageUtils.getClassList(req.getProject(), reqPackage); + + ParamTableDialog table = new ParamTableDialog(ParamDialogReq.builder().title("param").build(), project, map, new HashMap<>(), req.getPromptInfo()); + table.setConsumer(cp -> { + Map m = table.getValuesMap(); + String reqClass = m.getOrDefault("reqClass", "").toString(); + + //用来获取要添加代码的Class和Method + Module module = req.getModule(); + SelectClassAndMethodDialog dialog = new SelectClassAndMethodDialog(project, DialogReq.builder().cmd(cmd).type(type).name(name).module(module).build()); + dialog.show(); + int exitCode = dialog.getExitCode(); + if (exitCode != DialogWrapper.OK_EXIT_CODE) { + return; + } + + DialogResult result = dialog.getResult(); + String methodName = result.getData().get("method"); + String className = result.getData().get("class"); + + + StringBuilder sb = new StringBuilder(); + + //打开PsiClass(需要更新的) + PsiClass psiClass = CodeService.openJavaClass(project, className); + Editor editor = CodeService.getEditor(req.getProject()); + //添加import + addImports(req, project, serviceName, reqClass, editor); + //添加字段 + addFields(project, serviceName, shortServiceName, psiClass, editor); + + //移动到合理的位置 + if (methodName.equals("New")) { + EditorUtils.moveToLastMethodEnd(psiClass, editor); + CodeService.writeCode2(project, editor, "\n"); + } else { + PsiMethod psiMethod = CodeService.getMethod(psiClass, methodName); + CodeService.deleteMethod(project, psiMethod); + } + + sb.append(req.getMeta()).append("\n"); + sb.append(methodCode).append("\n"); + String param = sb.toString(); + + Map params = Maps.newHashMap(); + m.put("code", param); + m.put("service", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, shortServiceName)); + m.put("reqClass", JavaClassUtils.getClassName(reqClass)); + + //修改Req(添加入字段) + modifyReq(req, pm, reqClass); + + //interface中添加方法(Dubbo中的interface需要同步更新) + addMethodToInterface(req, psiClass, pm, PsiClassUtils.findClassByName(req.getProject(), reqClass)); + + m.entrySet().forEach(entry -> params.put(entry.getKey(), entry.getValue().toString())); + + //生成方法代码 + CodeService.generateCodeWithAi3(req.getProject(), promptName, new String[]{}, params, (p, code) -> CodeService.writeCode2(p, editor, code)); + }); + table.show(); + + + } + + public static void addFields(Project project, String serviceName, String shortServiceName, PsiClass psiClass, Editor editor) { + CodeService.addField(project, editor.getDocument(), psiClass, String.format("@Resource\nprivate %s %s;", shortServiceName, CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, shortServiceName)), serviceName); + } + + public static void addImports(GenerateCodeReq req, Project project, String serviceName, String reqClass, Editor editor) { + addImports(req, project, serviceName, reqClass, editor, false, false, ""); + } + + public static void addImports(GenerateCodeReq req, Project project, String serviceName, String reqClass, Editor editor, boolean unitTest, boolean resource, String unitVersion) { + ArrayList importService = Lists.newArrayList(); + importService.add(serviceName); + if (null != reqClass) { + importService.add(reqClass); + } + importService.addAll(PromptUtils.getImportList(req.getPromptInfo())); + if (unitTest) { + importService.addAll(TestUtils.getImportList(unitVersion)); + } + if (resource) { + importService.addAll(ProjectUtils.getResourceImport(project)); + } + CodeService.addImport(project, editor, importService); + } + + /** + * 给interface中添加方法(返回值可能被包装要注意) + * + * @param psiClass + */ + private static void addMethodToInterface(GenerateCodeReq req, PsiClass psiClass, PsiMethod pm, PsiClass reqClass) { + boolean modifyReq = Boolean.valueOf(req.getPromptInfo().getLabels().getOrDefault("add_interface_method", "false")); + if (!modifyReq) { + return; + } + Safe.run(() -> { + Project project = req.getProject(); + PsiClass interfacePsiClass = PsiClassUtils.getInterface(psiClass); + PsiType type = PsiElementFactory.getInstance(project).createType(reqClass); + PsiType returnType = getReturnType(req, project, pm, interfacePsiClass); + List list = Lists.newArrayList(ParamInfo.builder().name(reqClass.getName()).psiType(type).build()); + WriteCommandAction.runWriteCommandAction(project, () -> PsiClassUtils.addMethod(project, interfacePsiClass, AddMethodConfig.builder().name(pm.getName()).returnType(returnType).isInterface(true).build(), list)); + }); + } + + + public static PsiType getReturnType(GenerateCodeReq req, Project project, PsiMethod psiMethod, PsiClass psiClass) { + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + String returnType = req.getPromptInfo().getLabels().getOrDefault("return_type", ""); + if (org.apache.commons.lang3.StringUtils.isNotEmpty(returnType)) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiClassUtils.addImport(psiClass, returnType); + }); + PsiClass resultClass = JavaPsiFacade.getInstance(project).findClass("com.xiaomi.youpin.infra.rpc.Result", GlobalSearchScope.allScope(project)); + @Nullable PsiType rt = psiMethod.getReturnType(); + if (rt instanceof PsiPrimitiveType) { + PsiPrimitiveType primitiveType = (PsiPrimitiveType) rt; + rt = primitiveType.getBoxedType(PsiManager.getInstance(project), GlobalSearchScope.allScope(project)); + } + PsiType[] typeArguments = {rt}; + PsiType psiType = factory.createType(resultClass, typeArguments); + return psiType; + } else { + return psiMethod.getReturnType(); + } + } + + + private static void modifyReq(GenerateCodeReq req, PsiMethod pm, String reqClass) { + //修改Req里边的参数 + boolean modifyReq = Boolean.valueOf(req.getPromptInfo().getLabels().getOrDefault("modify_req", "false")); + if (modifyReq) { + Safe.run(() -> { + List list = PsiMethodUtils.getParamInfoList(pm); + PsiClass reqPsiClass = PsiClassUtils.findClassByName(req.getProject(), reqClass); + WriteCommandAction.runWriteCommandAction(req.getProject(), () -> list.stream().forEach(it -> PsiClassUtils.addField(req.getProject(), reqPsiClass, it.getName(), it.getPsiType()))); + }); + } + } + + private static void setLabels(GenerateCodeReq req, Map map) { + Map labels = req.getPromptInfo().getLabels(); + if (null != labels) { + labels.entrySet().forEach(entry -> { + if (map.keySet().contains(entry.getKey())) { + map.put(entry.getKey(), entry.getValue()); + } + }); + } + } + + //暂时只生成接口引入 + public static void generateMiapiMethod(GenerateCodeReq req) { + Project project = req.getProject(); + Editor editor = req.getEditor(); + String requirement = getCode(req, new PromptContext()).replace("//", ""); + List list = AthenaCodeService.getCodeList(CodeReq.builder().requirement(requirement).fileTypeList(Arrays.asList("miapi")).build()); + if (CollectionUtils.isNotEmpty(list)) { + list.forEach(i -> { + log.info("miapi similarQuery rst:" + i.getContent()); + CodeService.writeCode2(project, editor, "\n"); + CodeService.generateCodeWithAi3(project, req.getPromptName(), new String[]{i.getContent()}, ImmutableMap.of("interfaceInfo", i.getContent()), (p, code) -> CodeService.writeCode2(p, editor, code)); + }); + } + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ProxyAiService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ProxyAiService.java new file mode 100644 index 000000000..a7835b1bf --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ProxyAiService.java @@ -0,0 +1,100 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.intellij.notification.NotificationType; +import com.xiaomi.youpin.tesla.ip.bo.ProxyAsk; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Completions; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Message; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.apache.commons.lang3.StringUtils; +import run.mone.ultraman.AthenaContext; + +import java.nio.charset.Charset; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author goodjava@qq.com + * @date 2023/12/5 22:13 + */ +@Slf4j +public class ProxyAiService { + + + private static Gson gson = new Gson(); + + public static JsonObject call(List messageList) { + return call(messageList, 50000); + } + + public static JsonObject call(String r, long time, boolean vip, boolean jsonResult) { + ProxyAsk pa = new ProxyAsk(); + if (StringUtils.isNotEmpty(AthenaContext.ins().getGptModel())) { + pa.setModel(AthenaContext.ins().getGptModel()); + } + pa.setZzToken(ConfigUtils.getConfig().getzToken()); + pa.setParams(new String[]{r}); + String req = gson.toJson(pa); + return call0(req, time, vip, jsonResult); + } + + //调用ai proxy (调用的是json接口,返回的数据一定是json格式) + public static JsonObject call0(String req, long time, boolean vip, boolean jsonResult) { + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(time, TimeUnit.MILLISECONDS) + .readTimeout(time, TimeUnit.MILLISECONDS) + .build(); + + String action = vip ? "/json" : "/json2"; + for (int i = 0; i < 3; i++) { + log.info("proxy ai call begin req:{} time:{}", req, i + 1); + MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); + Request request = new Request.Builder() + .url(ConfigUtils.getConfig().getAiProxy() + action) + .post(RequestBody.create(mediaType, req.getBytes(Charset.forName("utf8")))) + .build(); + + try (Response response = client.newCall(request).execute()) { + // 判断请求是否成功 + if (response.isSuccessful() && response.body() != null) { + String responseBody = response.body().string(); + log.info("proxy ai call finish res:{}", responseBody); + + if (jsonResult) { + JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class); + if (null != jsonObject.get("authCode")) { + NotificationCenter.notice("call ai error," + jsonObject.get("msg").getAsString(), NotificationType.ERROR); + return null; + } + return jsonObject; + } + JsonObject res = new JsonObject(); + res.addProperty("data", responseBody); + return res; + } else { + log.info("proxy ai call failure code:{}", response.code()); + } + } catch (Throwable e) { + log.info("proxy ai call error:{}", e.getMessage()); + e.printStackTrace(); + } + } + return null; + } + + public static JsonObject call(List messageList, long time) { + Completions completions = Completions.builder().messages(messageList).build(); + ProxyAsk pa = new ProxyAsk(); + if (StringUtils.isNotEmpty(AthenaContext.ins().getGptModel())) { + pa.setModel(AthenaContext.ins().getGptModel()); + } + pa.setParams(new String[]{gson.toJson(completions)}); + String req = gson.toJson(pa); + return call0(req, time, true, true); + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PsiMethodUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PsiMethodUtils.java new file mode 100644 index 000000000..39fdbeee2 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/PsiMethodUtils.java @@ -0,0 +1,176 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.gson.JsonObject; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.RefactoringFactory; +import com.intellij.refactoring.RenameRefactoring; +import com.intellij.util.IncorrectOperationException; +import com.xiaomi.youpin.tesla.ip.bo.ParamInfo; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2023/6/3 22:31 + */ +public class PsiMethodUtils { + + + /** + * 删除指定方法中的注释 + * + * @param psiMethod + */ + public static void deleteCommentsFromMethod(Project project, PsiMethod psiMethod, Predicate predicate) { + @NotNull Collection comments = PsiTreeUtil.collectElementsOfType(psiMethod, PsiComment.class); + WriteCommandAction.runWriteCommandAction(project, () -> { + for (PsiComment comment : comments) { + if (predicate.test(comment)) { + comment.delete(); + } + } + }); + } + + public static List getParamInfoList(PsiMethod psiMethod) { + return Arrays.stream(psiMethod.getParameterList().getParameters()).map(it -> { + String name = it.getName(); + String type = it.getType().getCanonicalText(); + return ParamInfo.builder().name(name).type(type).psiType(it.getType()).build(); + }).collect(Collectors.toList()); + } + + + /** + * 修改方法名 + * + * @param project 项目对象 + * @param document 文档对象 + * @param method 方法对象 + * @param newName 新方法名 + */ + public static void modifyMethodName(Project project, Document document, PsiMethod method, String newName) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiIdentifier identifier = method.getNameIdentifier(); + int startOffset = identifier.getTextRange().getStartOffset(); + int endOffset = identifier.getTextRange().getEndOffset(); + document.replaceString(startOffset, endOffset, newName); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + } + + + /** + * Renames the specified method within the given project to the new name using a rename refactoring process wrapped in a write command action. + */ + public static void renameMethod(Project project, PsiMethod method, String newName) { + ApplicationManager.getApplication().invokeLater(() -> { + RenameRefactoring renameRefactoring = RefactoringFactory.getInstance(project) + .createRename(method, newName); + renameRefactoring.setSearchInComments(false); + renameRefactoring.setSearchInNonJavaFiles(false); + renameRefactoring.run(); + }); + } + + //replace PsiMethod整体的信息,参数是一个String method code(class) + public static void replacePsiMethod(Project project, PsiMethod psiMethod, String methodCode) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + PsiMethod newMethod = elementFactory.createMethodFromText(methodCode.trim(), psiMethod.getContainingFile()); + psiMethod.replace(newMethod); + }); + } + + + /** + * 在指定项目中重命名给定的参数。 + * + * @param project 当前工作的项目对象。 + * @param parameter 要重命名的参数。 + * @param newName 参数的新名称。 + */ + public static void renameParameter(Project project, PsiParameter parameter, String newName) { + ApplicationManager.getApplication().invokeLater(() -> { + // 确保我们在写操作允许的上下文中执行重命名 + CommandProcessor.getInstance().executeCommand(project, () -> { + try { + // 使用重构 API 创建一个重命名重构动作 + RenameRefactoring renameRefactoring = RefactoringFactory.getInstance(project) + .createRename(parameter, newName); + renameRefactoring.setSearchInComments(false); + renameRefactoring.setSearchInNonJavaFiles(false); + renameRefactoring.run(); + } catch (IncorrectOperationException e) { + // 处理可能的异常 + } + }, "Rename Parameter", null); + }); + } + + // 通过getFirstChild迭代,获取PsiMethod的第一叶子节点 + public static PsiElement getFirstLeafNode(PsiMethod psiMethod) { + PsiElement element = psiMethod.getFirstChild(); + while (element != null && element.getFirstChild() != null) { + element = element.getFirstChild(); + } + return element; + } + + + public static JsonObject extractMethodCallParts(@NotNull Project project, @NotNull Editor editor) { + JsonObject res = new JsonObject(); + // 获取当前 PsiFile + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); + PsiFile psiFile = psiDocumentManager.getPsiFile(editor.getDocument()); + if (psiFile == null) return res; + + // 获取当前光标位置的 PsiElement + int offset = editor.getCaretModel().getOffset(); + PsiElement elementAtCursor = psiFile.findElementAt(offset); + if (elementAtCursor == null) return res; + + // 向上遍历 PSI 树,直到找到方法调用表达式 + PsiElement parent = PsiTreeUtil.getParentOfType(elementAtCursor, PsiMethodCallExpression.class); + if (parent instanceof PsiMethodCallExpression) { + PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) parent; + + // 获取方法名 + PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + String methodName = methodExpression.getReferenceName(); + System.out.println("Method name: " + methodName); + + String methodCode = methodExpression.resolve().getText(); + res.addProperty("methodCode", methodCode); + res.addProperty("methodName", methodName); + + + // 获取调用对象 + PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (qualifier instanceof PsiReferenceExpression) { + PsiReferenceExpression referenceExpression = (PsiReferenceExpression) qualifier; + PsiElement resolved = referenceExpression.resolve(); + if (resolved instanceof PsiVariable) { + System.out.println("Referenced variable: " + ((PsiVariable) resolved).getName()); + PsiVariable pv = (PsiVariable) resolved; + res.addProperty("className", pv.getType().getCanonicalText()); + } + } + } + return res; + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/QuickFixInvokeUtil.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/QuickFixInvokeUtil.java new file mode 100644 index 000000000..60863281c --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/QuickFixInvokeUtil.java @@ -0,0 +1,210 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.InspectionProfileImpl; +import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.codeInspection.ex.Tools; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author HawickMason@xiaomi.com + * @aythor goodjava@qq.com + * @date 4/18/24 15:00 + */ +@Slf4j +public class QuickFixInvokeUtil { + + @Deprecated + public static void applyQuickFixes(@NotNull Project project, @NotNull PsiFile file) { + InspectionManager inspectionManager = InspectionManager.getInstance(project); + InspectionProfileImpl inspectionProfile = InspectionProjectProfileManager.getInstance(project).getCurrentProfile(); + + // 获取所有启用的检查工具 + List inspectionTools = inspectionProfile.getAllEnabledInspectionTools(project); + + for (Tools toolWrapper : inspectionTools) { + if (toolWrapper instanceof LocalInspectionToolWrapper) { + LocalInspectionTool localInspectionTool = ((LocalInspectionToolWrapper) toolWrapper).getTool(); + ProblemsHolder problemsHolder = new ProblemsHolder(inspectionManager, file, false); + PsiElementVisitor visitor = localInspectionTool.buildVisitor(problemsHolder, true); + file.accept(visitor); + + List problems = problemsHolder.getResults(); + for (ProblemDescriptor problem : problems) { + // 获取问题描述符的 Quick Fixes + QuickFix[] fixes = problem.getFixes(); + if (fixes != null) { + for (QuickFix fix : fixes) { + // 应用第一个可用的 Quick Fix + applyQuickFix(project, problem, fix); + break; // 只应用一个 Quick Fix,如果需要应用多个,移除这个 break + } + } + } + } + } + } + + public static List problems(@NotNull Project project, @NotNull PsiFile file, PsiClass pc) { + InspectionManager inspectionManager = InspectionManager.getInstance(project); + InspectionProfileImpl inspectionProfile = InspectionProjectProfileManager.getInstance(project).getCurrentProfile(); + // 获取所有启用的检查工具 + List inspectionTools = inspectionProfile.getAllEnabledInspectionTools(project); + List res = new ArrayList<>(); + + + Task.Backgroundable task = new Task.Backgroundable(project, "Running Task", true) { + public void run(@NotNull ProgressIndicator indicator) { + // 设置进度指示器的初始文本 + indicator.setText("Running task..."); + + for (Tools toolWrapper : inspectionTools) { + InspectionToolWrapper t = toolWrapper.getTool(); + InspectionProfileEntry e = t.getTool(); + if (e instanceof LocalInspectionTool lt) { + res.addAll(lt.processFile(file,inspectionManager)); + } + } + + System.out.println(res); + + } + }; + + ProgressManager.getInstance().run(task); + + return res; + + } + + private static void applyQuickFix(@NotNull Project project, @NotNull ProblemDescriptor problem, @NotNull QuickFix quickFix) { + // 在写操作中应用 Quick Fix + WriteCommandAction.runWriteCommandAction(project, () -> quickFix.applyFix(project, problem)); + } + + + public static void a(Project project,PsiFile file) { + DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(project); + if (analyzer instanceof DaemonCodeAnalyzerImpl ex) { + @Nullable Document document = PsiDocumentManager.getInstance(project).getDocument(file); + ex.restart(file); + TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(CodeService.getEditor(project)); + @NotNull List list = ex.getFileLevelHighlights(project, file); + System.out.println(list); + } + } + + @Deprecated + public static void performQuickFix(@NotNull Project project, @NotNull PsiFile file) { + DaemonCodeAnalyzer.getInstance(project).restart(file); + Editor editor = openClassAndGetEditor(project, file); + if (editor == null) { + log.warn("Failed to open file:{} will not perform quick fix...", file); + return; + } + + ApplicationManager.getApplication().runReadAction(() -> { + ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo(); + ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1); + + // 遍历错误意图并尝试应用第一个 + // TODO mason: 目前这里拿到errorFixesToShow为空(不是null,但没有内容...) + for (HighlightInfo.IntentionActionDescriptor actionDes : intentions.errorFixesToShow) { + try { + IntentionAction action = actionDes.getAction(); + if (action.isAvailable(project, editor, file)) { + action.invoke(project, editor, file); + break; // 应用了第一个可用的修复后退出循环 + } + } catch (IncorrectOperationException ex) { + log.error("Error while try to quick fix:{} of project:{}", file, project); + } + } + }); + } + + public static Editor openClassAndGetEditor(@NotNull Project project, @NotNull PsiFile file) { + return ReadAction.compute(() -> { + if (!ApplicationManager.getApplication().isReadAccessAllowed()) { + log.error("Read access is not allowed"); + return null; + } + FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + fileEditorManager.openFile(file.getVirtualFile(), true); + Editor editor = fileEditorManager.getSelectedTextEditor(); + if (editor != null && editor.getDocument() == PsiDocumentManager.getInstance(project).getDocument(file)) { + // 此时 editor 是打开的 PsiFile 对应的 Editor + return editor; + } else { + // 如果没有找到对应的 Editor,可能是文件没有正确打开 + return null; + } + }); + } + + public static void quickFix2(Project project, PsiFile psiFile) { + Editor editor = openClassAndGetEditor(project, psiFile); + if (editor == null) { + log.warn("Failed to open file:{} will not perform quick fix...", psiFile); + return; + } + + // 获取所有错误 + DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(project); + List errors = DaemonCodeAnalyzerImpl.getHighlights(psiFile.getViewProvider().getDocument(), HighlightSeverity.ERROR, project); + for (HighlightInfo error : errors) { + if (error.getSeverity() == HighlightSeverity.ERROR) { + // 获取并尝试执行快速修复 + List quickFixes = error.quickFixActionRanges.stream() + .map(range -> range.getFirst().getAction()) + .toList(); + for (IntentionAction quickFix : quickFixes) { + if (quickFix.isAvailable(project, editor, psiFile)) { + quickFix.invoke(project, editor, psiFile); + break; // 只执行第一个可用的快速修复 + } + } + } + } + } + + public static List findAllErrors(Project project, PsiFile psiFile) { + Editor editor = openClassAndGetEditor(project, psiFile); + if (editor == null) { + log.warn("Failed to open file:{} will not perform quick fix...", psiFile); + return Collections.emptyList(); + } + return DaemonCodeAnalyzerImpl.getHighlights(psiFile.getViewProvider().getDocument(), HighlightSeverity.ERROR, project); + } +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/RobotService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/RobotService.java similarity index 59% rename from athena-all/src/main/java/run/mone/m78/ip/service/RobotService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/RobotService.java index 3c2b0070e..7db1db631 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/RobotService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/RobotService.java @@ -1,28 +1,39 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.gson.Gson; +import com.google.gson.JsonObject; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.ui.Messages; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.RobotContext; +import com.xiaomi.youpin.tesla.ip.bo.RobotReq; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.client.MyHttpClient; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.util.*; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.mutable.Mutable; import org.apache.commons.lang.mutable.MutableObject; import org.jetbrains.annotations.NotNull; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.RobotContext; -import run.mone.m78.ip.bo.RobotReq; -import run.mone.m78.ip.common.ChromeUtils; -import run.mone.m78.ip.util.*; +import run.mone.ultraman.AthenaContext; import run.mone.ultraman.background.AthenaTask; import run.mone.ultraman.common.GitProjectOpener; +import run.mone.ultraman.http.HttpClient; import run.mone.ultraman.service.AthenaCodeService; import java.io.IOException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -93,6 +104,7 @@ public static String createPackage(RobotContext context, RobotReq req) { public static String generateMoonHandler(RobotContext context, RobotReq req) { ApplicationManager.getApplication().invokeLater(() -> { + // todo 具体的业务逻辑用req中用户的定义 CodeService.generateMoonHandler(ProjectUtils.projectFromManager()); }); return "ok"; @@ -219,7 +231,6 @@ public static void terminal(RobotContext context, RobotReq req) { ApplicationManager.getApplication().invokeLater(() -> TerminalUtils.send(req.getProject(), req.getParam())); } - //同声翻译 public static void translate(RobotContext context, RobotReq req) { ApplicationManager.getApplication().invokeLater(() -> { @@ -234,7 +245,14 @@ public static void translate(RobotContext context, RobotReq req) { //官网检索 public static void web123(RobotContext context, RobotReq req) { - + ApplicationManager.getApplication().invokeLater(() -> { + Map map = new HashMap<>(); + map.put("code", req.getParam()); + String res = AthenaCodeService.callProxy(req.getProject(), map, "web123", 10).value(); + System.out.println(res); + ChromeUtils.call(req.getProject().getName(), res, 0); + } + ); } @@ -249,16 +267,34 @@ public static void openApp(RobotContext context, RobotReq req) { //错误分析 public static void troubleshoot(RobotContext context, RobotReq req) { + ApplicationManager.getApplication().invokeLater(() -> { + String promptName = "other"; + String troubleshootType = getTroubleshootType(context, req); + if (troubleshootType.contains("dubbo")) { + promptName = "dubbo_troubleshoot"; + } /*else if (troubleshootType.contains("nacos")){ + promptName = "nacos_troubleshoot"; + }*/ else { + promptName = "troubleshoot"; + } + Map map = new HashMap<>(); + map.put("errorMsg", req.getParam()); + String res = AthenaCodeService.callProxy(req.getProject(), map, promptName, 10).value(); + System.out.println(promptName + ":" + res); + ChromeUtils.call(req.getProject().getName(), res, 0); + }); } public static String getTroubleshootType(RobotContext context, RobotReq req) { - return ""; + Map map = new HashMap<>(); + map.put("errorMsg", req.getParam()); + return AthenaCodeService.callProxy(req.getProject(), map, "type_troubleshoot", 10).value(); } public static String getPromptCmd(String cmd) { - return ""; + return CodeService.call("bot", ImmutableMap.of("code", cmd)).trim(); } @@ -268,27 +304,107 @@ public static String getPromptCmd(String cmd) { * @param req */ private static void bot0(GenerateCodeReq req) { + try { + String res = CodeService.call(req.getPromptName(), req.getParam()).trim(); + UltramanConsole.append(req.getProject(), "bot:\n" + res + "\n"); + + if (res.equals("scroll")) { + RobotService.scroll(null, RobotReq.builder().project(req.getProject()).build()); + } + + if (res.startsWith("translate")) { + RobotService.translate(null, RobotReq.builder().project(req.getProject()).param(res.substring(10)).build()); + } + + if (res.startsWith("web123")) { + RobotService.web123(null, RobotReq.builder().project(req.getProject()).param(res.substring(7)).build()); + } + + if (res.equals("generate interface")) { + dynamicCallPrompt(req, "generateInterface"); + } + //执行脚本(所有代码存储在z平台) + if (res.startsWith("run script")) { + Map map = Maps.newHashMap(); + setKV(map, req); + Object r = runScript(map, res); + if (null != r) { + if (r instanceof Throwable t) { + ChromeUtils.call(req.getProject().getName(), "error:" + t.getMessage(), "", 0); + } else if (r instanceof AiChatMessage am) { + ChromeUtils.call(req.getProject().getName(), am); + } else { + ChromeUtils.call(req.getProject().getName(), r.toString(), "", 0); + } + } + return; + } + + + if (res.equals("unsupport")) { + ChromeUtils.call(req.getProject().getName(), "这个指令不支持", "", 0); + } else { + if (req.getParam().get("code").equals("帮助")) { + ChromeUtils.call(req.getProject().getName(), res, "", 0); + } else { + ChromeUtils.call(req.getProject().getName(), "指令:" + res + "执行成功", "", 0); + } + } + } catch (Throwable ex) { + String message = ex.getMessage(); + ChromeUtils.call(req.getProject().getName(), "调用指令的时候发生错误:" + message, "", 0); + log.error(ex.getMessage(), ex); + } } //执行脚本 public static Object runScript(Map map, String promptCmd) { - return null; + String[] ss = promptCmd.split("\\$\\$"); + Arrays.stream(ss).forEach(it -> { + String[] kv = it.split("#"); + if (kv.length == 2) { + map.put(kv[0], kv[1]); + } + }); + if (ss.length == 1) { + map.put("methodName", ss[0]); + } + log.info("map:{}", map); + String methodName = map.get("methodName").toString(); + String httpRes = HttpClient.get(AthenaContext.ins().getZAddr() + "/api/z/open/function/query?name=" + methodName); + JsonObject jsonObject = new Gson().fromJson(httpRes, JsonObject.class); + String functionCode = jsonObject.getAsJsonObject("data").get("scriptContent").getAsString(); + Object r = ScriptService.ins().invoke(functionCode, "call", makeBindMap(), map); + return r; } public static Object runScriptMethod(Map map, String methodName) { - return null; + String httpRes = HttpClient.get(AthenaContext.ins().getZAddr() + "/api/z/open/function/query?name=" + methodName); + JsonObject jsonObject = new Gson().fromJson(httpRes, JsonObject.class); + String functionCode = jsonObject.getAsJsonObject("data").get("scriptContent").getAsString(); + Object r = ScriptService.ins().invoke(functionCode, "call", makeBindMap(), map); + return r; } private static Map makeBindMap() { return ImmutableMap.of( "log", log, - "gson", gson + "gson", gson, + "zAddr", Prompt.getzAddr(), + "ztoken", ConfigUtils.getConfig().getzToken(), + "okHttpClient", MyHttpClient.getInstance() ); } private static void setKV(Map map, GenerateCodeReq req) { - + map.put("classCode", req.getClassCode()); + map.put("methodCode", req.getMethodCode()); + map.put("fileText", req.getVirtualFileText()); + map.put("project", req.getProject()); + map.put("req", req); + map.put("editor", req.getEditor()); + map.put("zToken", ConfigUtils.getConfig().getzToken()); } @@ -305,7 +421,16 @@ public void run(@NotNull ProgressIndicator indicator) { } public static void dynamicCallPrompt(GenerateCodeReq req, String promptName) { - + ApplicationManager.getApplication().invokeLater(() -> { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + PromptType promptType = Prompt.getPromptType(promptInfo); + PromptService.dynamicInvoke(GenerateCodeReq.builder() + .project(req.getProject()) + .promptName(promptInfo.getPromptName()) + .promptInfo(promptInfo) + .promptType(promptType) + .build()); + }); } diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ScriptService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ScriptService.java similarity index 64% rename from athena-all/src/main/java/run/mone/m78/ip/service/ScriptService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ScriptService.java index f2a4b4d18..39f9bafb7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ScriptService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/ScriptService.java @@ -14,11 +14,14 @@ * limitations under the License. */ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.Prompt; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import java.util.Map; @@ -41,7 +44,11 @@ private ScriptService() { @SneakyThrows public static String getScript(String name) { - return ""; + PromptInfo info = Prompt.getPrompt(69, name); + if (null == info || null == info.getData()) { + throw new RuntimeException("No corresponding prompt found."); + } + return info.getData(); } private static final class LazyHolder { @@ -53,7 +60,16 @@ public static ScriptService ins() { } public Object invoke(String script, String functionName, Map bindValues, Object... args) { - return null; + try { + bindValues.entrySet().stream().forEach(it -> engine.put(it.getKey(), it.getValue())); + engine.eval(script); + Object res = ((Invocable) engine).invokeFunction(functionName, args); + log.info("invoke res:" + res); + return res; + } catch (Throwable e) { + log.error("invoke script error:" + e.getMessage(), e); + return e; + } } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/SpiderService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/SpiderService.java similarity index 57% rename from athena-all/src/main/java/run/mone/m78/ip/service/SpiderService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/SpiderService.java index 3333e3030..42b6a26d4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/SpiderService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/SpiderService.java @@ -14,12 +14,17 @@ * limitations under the License. */ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.google.gson.Gson; -import run.mone.m78.ip.bo.SpiderUrl; +import com.xiaomi.youpin.tesla.ip.bo.SpiderUrl; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ApiRes; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @Author goodjava@qq.com @@ -30,7 +35,12 @@ public class SpiderService { private Gson gson = new Gson(); public List list(String name) { - return null; + ApiCall call = new ApiCall(); + Map m = new HashMap<>(); + m.put("name", name); + String res = call.postCall(ApiCall.SPIDER_API, gson.toJson(m), 3000); + List list = gson.fromJson(res, ApiRes.class).getData(); + return list.stream().map(it -> gson.fromJson(it, SpiderUrl.class)).collect(Collectors.toList()); } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ImageService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TaskService.java similarity index 52% rename from athena-all/src/main/java/run/mone/m78/ip/service/ImageService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TaskService.java index 68340dba9..4127368a5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ImageService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TaskService.java @@ -14,35 +14,29 @@ * limitations under the License. */ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.diagnostic.Logger; -import run.mone.m78.ip.common.Context; +import com.google.gson.Gson; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ApiRes; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @Author goodjava@qq.com - * @Date 2021/11/6 20:23 + * @Date 2021/11/9 14:04 */ -public class ImageService extends AbstractService { - - private static final Logger log = Logger.getInstance(ImageService.class); - - /** - * 使用ide 打开图片 - */ - public void open(String t) { - - } - +public class TaskService { - public void openImage(String url) { + public List tasks(String name) { + ApiCall call = new ApiCall(); + Map m = new HashMap<>(1); + m.put("user", name); + String str = call.postCall(ApiCall.TASK_API, new Gson().toJson(m), 5000); + return new Gson().fromJson(str, ApiRes.class).getData(); } - @Override - public void execute(Context context, AnActionEvent e) { - - this.next(context, e); - } } diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TextService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TextService.java new file mode 100644 index 000000000..1529c32f1 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/TextService.java @@ -0,0 +1,106 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + + +/** + * @author goodjava@qq.com + * @date 2023/5/17 15:46 + */ +@Slf4j +public class TextService { + + + public static void writeContent(Project project, String fileName, String moduleName, Runnable runnable) { + writeContent(project, fileName, moduleName, runnable, null); + } + + + public static String readContent(Project project, String module, String fileName) { + PsiDirectory directory = getPsiDirectory(project, module); + if (null == directory) { + return ""; + } + PsiFile file = directory.findFile(fileName); + if (null == file) { + return ""; + } + return file.getText(); + } + + + public static void writeContent(Project project, String fileName, String moduleName, Runnable runnable, String content) { + String fileContent = getFileContent(content); + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project); + PsiFile psiFile = psiFileFactory.createFileFromText( + fileName, PlainTextFileType.INSTANCE, fileContent); + + PsiDirectory directory = getPsiDirectory(project, moduleName); + if (null == directory) { + log.info("directory is null moduleName:{}", moduleName); + return; + } + + @Nullable PsiFile file = directory.findFile(fileName); + if (null != file) { + file.delete(); + } + + PsiElement addedFile = directory.add(psiFile); + if (addedFile instanceof PsiFile) { + VirtualFile virtualFile = ((PsiFile) addedFile).getVirtualFile(); + if (virtualFile != null) { + FileEditorManager.getInstance(project).openFile(virtualFile, true); + if (StringUtils.isEmpty(content)) { + runnable.run(); + } + } + } + }); + } + + @NotNull + private static String getFileContent(String content) { + String fileContent = " "; + if (StringUtils.isNotEmpty(content)) { + fileContent = content; + } + return fileContent; + } + + + private static PsiDirectory getPsiDirectory(Project project, String moduleName) { + PsiDirectory directory = PsiClassUtils.getSourceDirectory(project, moduleName); + if (null == directory) { + return null; + } + PsiDirectory resourcesDir = directory.findSubdirectory("resources"); + if (null == resourcesDir) { + directory = directory.createSubdirectory("resources"); + } else { + directory = resourcesDir; + } + PsiDirectory subdirectory = directory.findSubdirectory("athena"); + if (subdirectory != null) { + return subdirectory; + } else { + return directory.createSubdirectory("athena"); + } + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/UltramanService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanService.java similarity index 75% rename from athena-all/src/main/java/run/mone/m78/ip/service/UltramanService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanService.java index 2741f8024..13a7e39a4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/UltramanService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanService.java @@ -1,7 +1,6 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.intellij.openapi.components.ServiceManager; -import run.mone.m78.ip.client.GrpcClient; /** * @Author goodjava@qq.com @@ -16,5 +15,4 @@ static UltramanService getInstance() { void init(); - GrpcClient client(); } diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/UltramanServiceImpl.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanServiceImpl.java similarity index 52% rename from athena-all/src/main/java/run/mone/m78/ip/service/UltramanServiceImpl.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanServiceImpl.java index bd84bb934..ab52b867b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/UltramanServiceImpl.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UltramanServiceImpl.java @@ -1,6 +1,7 @@ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; -import run.mone.m78.ip.client.GrpcClient; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import lombok.Data; import lombok.extern.slf4j.Slf4j; /** @@ -8,18 +9,13 @@ * @Date 2021/11/5 12:38 */ @Slf4j +@Data public class UltramanServiceImpl implements UltramanService { - private GrpcClient grpcClient; private boolean openHttpServer = false; - public UltramanServiceImpl() { - grpcClient = new GrpcClient(); - } - - @Override public void run() { log.info("athena run"); @@ -28,15 +24,14 @@ public void run() { @Override public void init() { log.info("athena service init"); - + ScriptService.ins(); + new Thread(() -> { + try { + Prompt.init(); + } catch (Throwable ex) { + ex.printStackTrace(); + } + }).start(); } - private static void openHttpServer() throws Exception { - - } - - @Override - public GrpcClient client() { - return grpcClient; - } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/UserService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UserService.java similarity index 54% rename from athena-all/src/main/java/run/mone/m78/ip/service/UserService.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UserService.java index bab7d6118..cbc9b0f0e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/service/UserService.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/UserService.java @@ -14,15 +14,21 @@ * limitations under the License. */ -package run.mone.m78.ip.service; +package com.xiaomi.youpin.tesla.ip.service; import com.google.gson.Gson; import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.bo.UserBo; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.Context; +import com.xiaomi.youpin.tesla.ip.bo.UserBo; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ApiRes; +import com.xiaomi.youpin.tesla.ip.common.Context; +import com.xiaomi.youpin.tesla.ip.common.Events; +import com.xiaomi.youpin.tesla.ip.common.UltramanEvent; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @Author goodjava@qq.com @@ -40,7 +46,12 @@ public List users() { public List userBoList() { - return null; + ApiCall apiCall = new ApiCall(); + Map m = new HashMap<>(1); + m.put("cmd","getMembers"); + String res = apiCall.postCall(ApiCall.TASK_API, gson.toJson(m), 5000); + ApiRes ar = gson.fromJson(res,ApiRes.class); + return ar.getData().stream().map(it-> gson.fromJson(it,UserBo.class)).collect(Collectors.toList()); } @@ -49,4 +60,9 @@ public void execute(Context context, AnActionEvent e) { this.next(context, e); } + public static void main(String... args) { + UserService us = new UserService(); + List list = us.userBoList(); + System.out.println(list); + } } diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/XmlService.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/XmlService.java new file mode 100644 index 000000000..1eb0daf4d --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/XmlService.java @@ -0,0 +1,147 @@ +package com.xiaomi.youpin.tesla.ip.service; + +import com.google.common.collect.Maps; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.XmlElementFactory; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.xiaomi.youpin.tesla.ip.dialog.SelectModuleDialog; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @author goodjava@qq.com + * @date 2023/5/21 22:07 + */ +public class XmlService { + + /** + * 方便操纵xml,这里的作用是修改maven 中的 pom 加入依赖 + * + * @param project + * @param moduleName + * @param dependency + */ + public static void openMavenPomAndModify(Project project, String moduleName, String dependency) { + String pomFilePath = project.getBasePath() + File.separator + moduleName + File.separator + "pom.xml"; + VirtualFile pomFile = LocalFileSystem.getInstance().findFileByPath(pomFilePath); + if (pomFile != null && !pomFile.isDirectory()) { + OpenFileDescriptor descriptor = new OpenFileDescriptor(project, pomFile); + if (descriptor.canNavigate()) { + descriptor.navigate(true); + } + PsiManager psiManager = PsiManager.getInstance(project); + XmlFile xmlFile = (XmlFile) psiManager.findFile(pomFile); + XmlTag dependenciesTag = xmlFile.getRootTag().findFirstSubTag("dependencies"); + XmlElementFactory factory = XmlElementFactory.getInstance(project); + XmlTag dependencyTag = factory.createTagFromText(dependency); + WriteCommandAction.runWriteCommandAction(project, () -> { + dependenciesTag.addSubTag(dependencyTag, false); + }); + } + + + } + + public static Pair checkPomVersion(Project project, String groupId, String artifactId, String version) { + List modules = ProjectUtils.listAllModules(project).stream().filter(m -> !project.getName().equals(m)).toList(); + Map modulePathMap = Maps.newHashMap(); + modules.forEach(i -> modulePathMap.put(i, project.getBasePath() + File.separator + i + File.separator + "pom.xml")); + // 根目录单独处理一下 + modulePathMap.put(Arrays.stream(project.getBasePath().split("/")) + .reduce((first, second) -> second) + .orElse(""), project.getBasePath() + File.separator + "pom.xml"); + List files = modulePathMap.values().stream().map(File::new).toList(); + for (File pomFile : files) { + try { + MavenXpp3Reader reader = new MavenXpp3Reader(); + Model model = reader.read(new FileReader(pomFile)); + List dependencies = model.getDependencies(); + for (Dependency dependency : dependencies) { + if (dependency.getGroupId().equals(groupId) && + dependency.getArtifactId().equals(artifactId)) { + if (dependency.getVersion().equals(version)) { + // true + return Pair.of(0, "success"); + } + // 修改版本 + dependency.setVersion(version); + Pair writeRes = writeDependency(model, pomFile); + ProjectUtils.openFileByPath(project, pomFile.getPath()); + return writeRes.getKey() == 0 ? Pair.of(0, "您好,您的项目已经添加过miapi的maven包,但它不是最新版本,已为您升级到最新版本\n" + + buildDependencyString(groupId, artifactId, version)) : writeRes; + } + } + // 没有引入 + return insertDependency(project, groupId, artifactId, version, modulePathMap); + } catch (Exception e) { + e.printStackTrace(); + return Pair.of(500, e.getMessage()); + } + } + return Pair.of(0, "success"); + } + + @NotNull + private static Pair insertDependency(Project project, String groupId, String artifactId, String version, Map modulePathMap) throws IOException, XmlPullParserException { + SelectModuleDialog dialog = new SelectModuleDialog(project, ProjectUtils.listAllModules(project)); + dialog.show(); + if (dialog.getExitCode() != 0) { + return Pair.of(0, "success"); + } + MavenXpp3Reader reader = new MavenXpp3Reader(); + String selectedModule = dialog.getSelectedModule(); + String pomFilePath = modulePathMap.get(selectedModule); + Model insertModel = reader.read(new FileReader(pomFilePath)); + Dependency dependency = new Dependency(); + dependency.setVersion(version); + dependency.setArtifactId(artifactId); + dependency.setGroupId(groupId); + insertModel.getDependencies().add(dependency); + Pair writeRes = writeDependency(insertModel, new File(pomFilePath)); + ProjectUtils.openFileByPath(project, pomFilePath); + return writeRes.getKey() == 0 ? Pair.of(0, "您好,您的项目之前没有添加过miapi的maven包,我已经为您添加了,下面是我添加的包\n" + + buildDependencyString(groupId, artifactId, version)) : writeRes; + } + + private static Pair writeDependency(Model model, File pomFile) { + try (FileWriter writer = new FileWriter(pomFile)) { + new MavenXpp3Writer().write(writer, model); + return Pair.of(0, "success"); + } catch (IOException ex) { + ex.printStackTrace(); + return Pair.of(500, ex.getMessage()); + } + } + + private static String buildDependencyString(String groupId, String artifactId, String version) { + return String.format("```\n" + + "\n" + + " \t%s\n" + + " \t%s\n" + + " \t%s\n" + + "", groupId, artifactId, version); + + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/consumer/BotMsgConsumer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/consumer/BotMsgConsumer.java new file mode 100644 index 000000000..621832b44 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/service/consumer/BotMsgConsumer.java @@ -0,0 +1,107 @@ +package com.xiaomi.youpin.tesla.ip.service.consumer; + +import com.google.common.base.Stopwatch; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; +import com.xiaomi.youpin.tesla.ip.bo.Action; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.AiMessageType; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.M78CodeGenerationInfo; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.LocalAiService; +import com.xiaomi.youpin.tesla.ip.util.ActionUtils; +import run.mone.ultraman.common.CodeUtils; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.listener.event.TaskEvent; + +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +/** + * @author goodjava@qq.com + * @date 2024/6/18 09:51 + */ +public class BotMsgConsumer implements Consumer { + + private GenerateCodeReq req; + private String out; + private ImportCode importCode; + private Stopwatch sw; + + private StringBuilder sb = new StringBuilder(); + + public BotMsgConsumer(GenerateCodeReq req, String out, ImportCode importCode, Stopwatch sw) { + this.req = req; + this.out = out; + this.importCode = importCode; + this.sw = sw; + } + + @Override + public void accept(AiMessage msg) { + if (out.equals("athena")) { + // 发到Athena + LocalAiService.sendMsg(msg, req.getProject().getName()); + } + if (out.equals("athena_chat")) { + // 发到Athena,非代码,纯聊天 + msg.setCode(false); + LocalAiService.sendMsg(msg, req.getProject().getName()); + } + //实现打字机效果 + if (out.equals("editor")) { + //输出到编辑器 + if (msg.getType().equals(AiMessageType.begin)) { + ApplicationManager.getApplication().getMessageBus().syncPublisher(TaskEvent.TOPIC).onEvent(TaskEvent.builder().message("begin").build()); + ApplicationManager.getApplication().invokeLater(() -> { + if (req.getPromptInfo().getLabelValue(Const.PROMPT_LABEL_TYPE, "comment").equals("comment")) { + //为生成注释做好准备 + CodeService.moveToMethodAndInsertLine(req.getProject()); + } + if (req.getPromptInfo().getLabelValue(Const.PROMPT_LABEL_TYPE, "").equals("method")) { + //不再插入回车 + if (req.getParam().containsKey("__skip_enter")) { + return; + } + //为插入方法做准备(挪动到行尾,然后插入一个回车) + CodeService.moveCaretToEndOfLine(req.getEditor()); + CodeService.writeCode2(req.getProject(), req.getEditor(), "\n"); + } + }); + } + + //这里会插入ide中 + if (msg.getType().equals(AiMessageType.process)) { + importCode.append(msg.getText()); + sb.append(msg.getText()); + } + + //生成代码结束了 + if (msg.getType().equals(AiMessageType.success)) { + ApplicationManager.getApplication().getMessageBus().syncPublisher(TaskEvent.TOPIC).onEvent(TaskEvent.builder().message("end").time(sw.elapsed(TimeUnit.SECONDS)).build()); + if (Action.GENERATE_CODE == ActionUtils.getActionByReq(req)) { + CodeUtils.uploadCodeGenInfo(sb.toString(), getComment(), this.req.getProject().getName(), this.req.getClassName()); + } + } + + //发生了错误 + if (msg.getType().equals(AiMessageType.failure)) { + NotificationCenter.notice(msg.getText(), NotificationType.ERROR); + } + } + } + + private String getComment() { + String comment = ""; + if (null != req.getParam().get(Const.GENERATE_CODE_COMMENT)) { + comment = req.getParam().get(Const.GENERATE_CODE_COMMENT); + }else{ + comment = this.req.getCurrentLine(); + } + return comment; + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.form index d3e5c1ca3..07d3d8778 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.form @@ -1,5 +1,5 @@ -

+ diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.java index f86d2eb85..25659fd45 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/BuildUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/BuildUi.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; -import run.mone.m78.ip.bo.IdeaPluginInfoBo; -import run.mone.m78.ip.bo.PluginDeleteParam; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.util.XmlUtils; +import com.xiaomi.youpin.tesla.ip.bo.IdeaPluginInfoBo; +import com.xiaomi.youpin.tesla.ip.bo.PluginDeleteParam; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.util.XmlUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableInt; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.form similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.form index c039b60fd..6227db5e6 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.java similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.java index a1a5b9723..396d4af6b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/ChatUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ChatUi.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.LangDataKeys; @@ -25,10 +25,10 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import run.mone.m78.ip.bo.Response; -import run.mone.m78.ip.bo.UserVo; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.common.MessageQueue; +import com.xiaomi.youpin.tesla.ip.bo.Response; +import com.xiaomi.youpin.tesla.ip.bo.UserVo; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.MessageQueue; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.form index bbec0e6b1..c8584d9c8 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.java index 377e5c8c4..ffa1d2191 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/CodeGeneratorUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CodeGeneratorUi.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import run.mone.m78.ip.generator.ClassGenerator; -import run.mone.m78.ip.generator.DirectoryGenerator; -import run.mone.m78.ip.generator.FileGenerator; -import run.mone.m78.ip.generator.PomGenerator; +import com.xiaomi.youpin.tesla.ip.generator.ClassGenerator; +import com.xiaomi.youpin.tesla.ip.generator.DirectoryGenerator; +import com.xiaomi.youpin.tesla.ip.generator.FileGenerator; +import com.xiaomi.youpin.tesla.ip.generator.PomGenerator; import org.apache.commons.lang3.StringUtils; import javax.swing.*; @@ -236,6 +236,7 @@ private void generateServicePom(String projectPath, String projectName, String g smpom.put("author", author); smpom.put("plugin", projectName); smpom.put("plugin_url", url); + smpom.put("plugin_class", "com.xiaomi.youpin.tesla.plug.TeslaPlugin"); servicePomGenerator.generator(smpom); } diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.form similarity index 67% rename from athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.form index cd7d4e7c6..5177bdfe5 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.form @@ -1,6 +1,6 @@ - - + + @@ -8,7 +8,7 @@ - + @@ -16,104 +16,82 @@ - - - - - - - - - - - + - + - + - + - + - + - - - + - + - + - - - + - + + + - + - + - + - + - - - + - + + + - + - - - + - + - + - + - + - + - - - - - - - - - + @@ -128,15 +106,6 @@ - - - - - - - - - diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.java similarity index 52% rename from athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.java index 3a2f27b43..ef43b269e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/ConfigUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/ConfigUi.java @@ -14,21 +14,25 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; - -import run.mone.m78.ip.bo.ZAddrRes; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.bo.TeslaPluginConfig; -import run.mone.m78.ip.common.ConfigUtils; +package com.xiaomi.youpin.tesla.ip.ui; + +import com.google.common.collect.Lists; +import com.xiaomi.youpin.tesla.ip.bo.ModelRes; +import com.xiaomi.youpin.tesla.ip.bo.TeslaPluginConfig; +import com.xiaomi.youpin.tesla.ip.bo.ZAddrRes; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; import lombok.Getter; import org.apache.commons.lang3.mutable.MutableBoolean; +import run.mone.ultraman.listener.bo.CompletionEnum; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.event.*; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * @author goodjava@qq.com @@ -38,20 +42,23 @@ public class ConfigUi extends JDialog { private JPanel contentPane; - private JTextField dashServerTextField; - private JTextField nickNameTextField; private JPasswordField zTokenPassword; @Getter - private JTextField aiProxyTextField; + private JComboBox chatModelComboBox; - @Getter - private JComboBox modelComboBox; private JButton refreshButton; + @Getter + private JComboBox completionMode; + @Getter + private JComboBox noChatModelComboBox; private MutableBoolean modified; + private static final List COMP_MODE_LIST = CompletionEnum.getDisplayList(); + + public ConfigUi(MutableBoolean modified) { this.modified = modified; setContentPane(contentPane); @@ -76,20 +83,28 @@ public void windowClosing(WindowEvent e) { } private void addListener() { - dashServerTextField.getDocument().addDocumentListener(listener); - nickNameTextField.getDocument().addDocumentListener(listener); this.zTokenPassword.getDocument().addDocumentListener(listener); - this.aiProxyTextField.getDocument().addDocumentListener(listener); - this.modelComboBox.addItemListener(itemEvent -> modified.setTrue()); + this.chatModelComboBox.addItemListener(itemEvent -> modified.setTrue()); + this.noChatModelComboBox.addItemListener(itemEvent -> modified.setTrue()); + this.completionMode.addItemListener(itemEvent -> modified.setTrue()); this.refreshButton.addActionListener(actionEvent -> { ZAddrRes res = Prompt.zAddrRes(); - this.dashServerTextField.setText(res.getAthenaDashServer().trim()); - List list = res.getModels().stream().map(it -> it.getValue()).collect(Collectors.toList()); - ComboBoxModel model = new DefaultComboBoxModel<>(list.toArray(String[]::new)); - this.modelComboBox.setModel(model); - if (list.size() > 0) { - this.modelComboBox.setSelectedItem(list.get(0)); + List list = res.getModels().stream().map(ModelRes::getValue).toList(); + ArrayList models = new ArrayList<>(list); + if (!models.contains(Const.USE_BOT_MODEL)) { + models.add(Const.USE_BOT_MODEL); } + ComboBoxModel chatModel = new DefaultComboBoxModel<>(models.toArray(String[]::new)); + ComboBoxModel noChatModel = new DefaultComboBoxModel<>(models.toArray(String[]::new)); + ComboBoxModel compMode = new DefaultComboBoxModel<>(COMP_MODE_LIST.toArray(String[]::new)); + this.chatModelComboBox.setModel(chatModel); + this.noChatModelComboBox.setModel(noChatModel); + if (!models.isEmpty()) { + this.chatModelComboBox.setSelectedItem(models.get(0)); + this.noChatModelComboBox.setSelectedItem(models.get(0)); + } + this.completionMode.setModel(compMode); + this.completionMode.setSelectedItem(COMP_MODE_LIST.get(0)); modified.setTrue(); }); } @@ -116,18 +131,29 @@ public void changedUpdate(DocumentEvent e) { private void init() { try { TeslaPluginConfig config = ConfigUtils.getConfig(); - this.dashServerTextField.setText(config.getDashServer()); - this.nickNameTextField.setText(config.getNickName()); this.zTokenPassword.setText(config.getzToken()); - this.aiProxyTextField.setText(config.getAiProxy()); List list = config.getModelList(); - String model = config.getModel(); - if (null != list && null != model) { - this.modelComboBox.setModel(new DefaultComboBoxModel(list.toArray(String[]::new))); - this.modelComboBox.setSelectedItem(model); + + // 聊天模型设置 + String chatModel = config.getModel(); + if (null != list && null != chatModel) { + if (!list.contains(Const.USE_BOT_MODEL)) { + list.add(Const.USE_BOT_MODEL); + } + this.chatModelComboBox.setModel(new DefaultComboBoxModel(list.toArray(String[]::new))); + this.chatModelComboBox.setSelectedItem(chatModel); } + // 非聊天模型设置 + String noChatModel = config.getNoChatModel(); + if (null != list && null != noChatModel) { + this.noChatModelComboBox.setModel(new DefaultComboBoxModel(list.toArray(String[]::new))); + this.noChatModelComboBox.setSelectedItem(noChatModel); + } + this.completionMode.setModel(new DefaultComboBoxModel<>(COMP_MODE_LIST.toArray(String[]::new))); + this.completionMode.setSelectedItem(config.getCompletionMode().getDesc()); + } catch (Exception ignore) { } @@ -149,18 +175,6 @@ public MutableBoolean getModified() { } - public JTextField getDashServerTextField() { - return dashServerTextField; - } - - public void setDashServerTextField(JTextField dashServerTextField) { - this.dashServerTextField = dashServerTextField; - } - - public JTextField getNickNameTextField() { - return nickNameTextField; - } - public JPasswordField getzTokenPassword() { return zTokenPassword; } diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.form index a0f99da4f..7e9a348bb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.java index 96a901e5c..66f490059 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/CreateClassUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/CreateClassUi.java @@ -1,11 +1,11 @@ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import run.mone.m78.ip.bo.CreateClassRes; -import run.mone.m78.ip.util.PsiClassUtils; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.bo.CreateClassRes; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import lombok.Getter; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.form index e15e3e649..39eb94311 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.java index 665493066..6bf213fbd 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/FilterUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/FilterUi.java @@ -14,18 +14,19 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import run.mone.m78.ip.generator.ClassGenerator; -import run.mone.m78.ip.generator.DirectoryGenerator; -import run.mone.m78.ip.generator.FileGenerator; -import run.mone.m78.ip.generator.PomGenerator; +import com.xiaomi.youpin.tesla.ip.generator.ClassGenerator; +import com.xiaomi.youpin.tesla.ip.generator.DirectoryGenerator; +import com.xiaomi.youpin.tesla.ip.generator.FileGenerator; +import com.xiaomi.youpin.tesla.ip.generator.PomGenerator; import org.apache.commons.lang3.StringUtils; import javax.swing.*; import java.awt.event.*; +import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.form index 1dd308bb3..1d1133e2b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.java similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.java index cd0e53ebd..7999c5942 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/NaviUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/NaviUi.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.form similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.form index 88be74103..df120e75a 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.java index a07ff7e60..af4817579 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/SelectUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SelectUi.java @@ -1,7 +1,7 @@ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.ui.Messages; -import run.mone.m78.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; import javax.swing.*; import java.awt.*; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.form similarity index 99% rename from athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.form index aeb5e2e35..45b6cfe8c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.java index d464e2d8a..666acd6ba 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/SpringBootProGenerator.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/SpringBootProGenerator.java @@ -14,17 +14,13 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.xiaomi.youpin.tesla.ip.common.FileUtils; +import com.xiaomi.youpin.tesla.ip.generator.*; import org.apache.commons.lang3.StringUtils; -import run.mone.m78.ip.common.ColorEggUtils; -import run.mone.m78.ip.common.FileUtils; -import run.mone.m78.ip.generator.ClassGenerator; -import run.mone.m78.ip.generator.DirectoryGenerator; -import run.mone.m78.ip.generator.FileGenerator; -import run.mone.m78.ip.generator.PomGenerator; import javax.swing.*; import java.awt.event.*; @@ -176,7 +172,7 @@ private void onOK() { String str = FileUtils.renderTemplate(template, new HashMap<>()); FileUtils.writeFile(catAppdatas + File.separator + "client.xml", str); - colorEgg(projectPath, projectName, testPath, packagePath); +// colorEgg(projectPath, projectName, testPath, packagePath); if (null != project) { Messages.showMessageDialog(project, "Success", "Generate Success", null); @@ -373,23 +369,19 @@ private void generateDeploy(String projectPath, String projectName, String versi deployGenerator.generator(smpom); } - private void colorEgg(String projectPath, String projectName, String testPath, String packagePath) { - String data = ""; - - String str = ColorEggUtils.parseByte2HexStr(ColorEggUtils.encrypt(data, "xiaomiYP")); - - - FileGenerator mdGenerator = new FileGenerator(projectPath, projectName, projectName + "-api" + - File.separator + testPath + File.separator + packagePath + File.separator + "test" + File.separator + ".des", "springboot_color_egg.tml"); - Map smpom = new HashMap<>(); - smpom.put("data", str); - mdGenerator.generator(smpom); - } - - private void onCancel() { dispose(); } + public static void main(String[] args) { + SpringBootProGenerator dialog = new SpringBootProGenerator(null); + dialog.pack(); + // 设置对话框大小是否可改变 + dialog.setResizable(true); + dialog.setSize(500, 400); + dialog.setVisible(true); + System.exit(0); + + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.form similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.form index f2e836a88..6c3aacf86 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.java similarity index 90% rename from athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.java index c70f457ad..685f8d54f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/TaskCreateUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/TaskCreateUi.java @@ -1,10 +1,10 @@ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.google.gson.Gson; -import run.mone.m78.ip.bo.UserBo; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.service.UserService; +import com.xiaomi.youpin.tesla.ip.bo.UserBo; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.service.UserService; import javax.swing.*; import java.awt.event.ActionEvent; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.form similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.form index 8e9b94cee..57e50fcfb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.java similarity index 98% rename from athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.java index fb405668c..1bcd316cb 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanConsoleUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanConsoleUi.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.form similarity index 97% rename from athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.form index 8aad5a470..3e10bcccf 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.form @@ -1,5 +1,5 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.java similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.java index 73e5bb301..4724ae570 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanTreeUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/UltramanTreeUi.java @@ -1,13 +1,12 @@ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; import com.google.gson.Gson; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.TbTask; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.listener.TreeMouseClickedListener; -import run.mone.m78.ip.listener.UltrmanTreeKeyAdapter; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.bo.TbTask; +import com.xiaomi.youpin.tesla.ip.common.ApiCall; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.listener.UltrmanTreeKeyAdapter; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import run.mone.ultraman.AthenaContext; import javax.swing.*; @@ -80,7 +79,6 @@ public void windowClosing(WindowEvent e) { ui.requestFocus(); }); - tree1.addMouseListener(new TreeMouseClickedListener(tree1, textField1, popupMenu)); UltrmanTreeKeyAdapter adapter = new UltrmanTreeKeyAdapter(this.project, textField1, tree1, this.webPannel, this.treePannel); AthenaContext.ins().setAthenaTreeKeyAdapter(adapter); textField1.addKeyListener(adapter); diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.form b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.form similarity index 89% rename from athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.form rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.form index fb591a721..d8cc633c2 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.form +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.form @@ -1,9 +1,9 @@ - + - + @@ -31,7 +31,7 @@ - + diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.java index 2ca8886e7..9b199b46b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/VersionUi.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/ui/VersionUi.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package run.mone.m78.ip.ui; +package com.xiaomi.youpin.tesla.ip.ui; -import run.mone.m78.ip.util.ScreenSizeUtils; +import com.xiaomi.youpin.tesla.ip.util.ScreenSizeUtils; import javax.swing.*; import java.awt.event.*; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ActionUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ActionUtils.java new file mode 100644 index 000000000..325199dbc --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ActionUtils.java @@ -0,0 +1,28 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.xiaomi.youpin.tesla.ip.bo.Action; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.common.Const; + +public class ActionUtils { + + public static Action getActionByReq(GenerateCodeReq req){ + if (req.getPromptInfo().getLabels().getOrDefault("selectComment", "").equals("true")) { + return Action.GENERATE_CODE; + } else if (Const.ATHENA_CHAT.equals(req.getPromptInfo().getPromptName())) { + return Action.CHAT; + } else if (Const.GENERATE_UNIT_TEST.equals(req.getPromptInfo().getPromptName())) { + return Action.UNIT_TEST; + } else if (req.getPromptInfo().getLabels().containsKey("git_push")) { + return Action.GIT_PUSH; + } else if (req.getPromptInfo().getLabels().containsKey("modify_method_name")) { + return Action.SMART_NAMING; + } else if (req.getPromptInfo().getLabelValue("action", "").equals("bug_fix")) { + return Action.BUG_FIX; + } else if(Const.CODE_REVIEW.equals(req.getPromptInfo().getPromptName())) { + return Action.CODE_SUGGESTION; + }else{ + return Action.GENERATE_COMMENT; + } + } +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/AnnoUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/AnnoUtils.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/util/AnnoUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/AnnoUtils.java index 3344bee48..8387ad178 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/AnnoUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/AnnoUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -6,7 +6,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.AnnotatedElementsSearch; -import run.mone.m78.ip.bo.ClassInfo; +import com.xiaomi.youpin.tesla.ip.bo.ClassInfo; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -45,7 +45,7 @@ public static List findClassWithAnno(Project project, String name, St if (annotationClass != null && annotationClass.isAnnotationType()) { AnnotatedElementsSearch.searchPsiClasses(annotationClass, scope).forEach(psiClass -> { Module module = PsiClassUtils.getModule(project, psiClass); - ClassInfo classInfo = ClassInfo.builder().className(psiClass.getQualifiedName()).moduleName(module.getName()).build(); + ClassInfo classInfo = ClassInfo.builder().className(psiClass.getQualifiedName()).simpleName(psiClass.getName()).moduleName(module.getName()).build(); result.add(classInfo); }); } diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/EditorUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/EditorUtils.java new file mode 100644 index 000000000..01b47868a --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/EditorUtils.java @@ -0,0 +1,350 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.search.FilenameIndex; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.testFramework.LightVirtualFile; +import com.xiaomi.youpin.tesla.ip.common.Const; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author goodjava@qq.com + * @date 2023/4/18 00:13 + */ +public class EditorUtils { + + public static void scroll(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + editor.getScrollingModel().scrollToCaret(ScrollType.CENTER_DOWN); // 翻到下一页 + } + + public static String getSelectContent(Editor editor) { + return getSelectedContentOrLine(editor, true); + } + + + //获取当前行内容(class) + public static String getCurrentLineContent(Editor editor) { + if (editor == null) { + return ""; + } + Document document = editor.getDocument(); + int caretOffset = editor.getCaretModel().getOffset(); + int lineNumber = document.getLineNumber(caretOffset); + int lineStartOffset = document.getLineStartOffset(lineNumber); + int lineEndOffset = document.getLineEndOffset(lineNumber); + return document.getText(new TextRange(lineStartOffset, lineEndOffset)).trim(); + } + + /** + * 获取编辑器选中内容或者当前行 + */ + public static String getSelectedContentOrLine(Editor editor, boolean selectLine) { + try { + Document document = editor.getDocument(); + final SelectionModel selectionModel = editor.getSelectionModel(); + final int start = selectionModel.getSelectionStart(); + final int end = selectionModel.getSelectionEnd(); + TextRange range = new TextRange(start, end); + String selectTxt = document.getText(range); + + //没有选中任何东西,则选中那一行 + if (StringUtils.isEmpty(selectTxt) && selectLine) { + selectionModel.selectLineAtCaret(); + final int start1 = selectionModel.getSelectionStart(); + final int end1 = selectionModel.getSelectionEnd(); + TextRange range1 = new TextRange(start1, end1); + selectTxt = document.getText(range1); + if (null != selectTxt) { + return selectTxt.trim(); + } + } + return selectTxt; + } catch (Throwable ignore) { + return ""; + } + } + + public static Editor getEditorFromPsiClass(Project project, PsiClass psiClass) { + PsiFile psiFile = psiClass.getContainingFile(); + if (psiFile != null) { + String fileName = psiFile.getName(); + PsiFile[] files = FilenameIndex.getFilesByName(project, fileName, GlobalSearchScope.allScope(project)); + for (PsiFile file : files) { + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile != null) { + FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + return fileEditorManager.openTextEditor(new OpenFileDescriptor(project, virtualFile), true); + } + } + } + return null; + } + + /** + * 移动到最后一个方法的最后部 + * + * @param psiClass + * @param editor + */ + public static void moveToLastMethodEnd(PsiClass psiClass, Editor editor) { + PsiMethod @NotNull [] methods = psiClass.getMethods(); + int offset = 0; + if (methods.length == 0) { + offset = psiClass.getTextRange().getEndOffset() - 1; + } else { + PsiMethod psiMethod = methods[methods.length - 1]; + offset = psiMethod.getTextRange().getEndOffset(); + } + editor.getCaretModel().moveToOffset(offset); + } + + public static void closeEditor(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (null != editor) { + FileEditorManager manager = FileEditorManager.getInstance(project); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + manager.closeFile(psiFile.getVirtualFile()); + } + } + + public static void openEditor(Project project, String content, String name) { + VirtualFile virtualFile = new LightVirtualFile(name, content); + virtualFile.putUserData(Const.T_KEY, name); + ApplicationManager.getApplication().runWriteAction((Computable) () -> { + Document document = FileDocumentManager.getInstance().getDocument(virtualFile); + if (document != null) { + document.setText(content); + } + return FileEditorManager.getInstance(project).openFile(virtualFile, true); + }); + } + + public static Editor getEditor(Project project) { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + return editor; + } + + + /** + * 获取或打开指定名称和内容的编辑器。 + * 如果已经存在打开的编辑器,则返回该编辑器,否则打开一个新的编辑器。 + * 如果打开的文件扩展名为"md",则返回该编辑器。 + * + * @param project 项目对象 + * @param name 文件名称 + * @param content 文件内容 + * @return 编辑器对象 + */ + public static Editor getOrOpenEditor(Project project, String name, String content) { + Editor editor = getEditor(project); + if (null == editor || !FileDocumentManager.getInstance().getFile(editor.getDocument()).equals("md")) { + openEditor(project, content, name); + } else { + return editor; + } + return getEditor(project); + } + + + public static int moveCursorToMethodEndIfOutside(Editor editor, PsiMethod method, int cursorOffset) { + // 获取当前编辑器 + if (editor == null) { + return cursorOffset; + } + + // 获取方法体的起始和结束偏移量 + PsiElement methodBody = method.getBody(); + if (methodBody == null) { + return cursorOffset; + } + int methodStartOffset = methodBody.getTextRange().getStartOffset(); + int methodEndOffset = methodBody.getTextRange().getEndOffset() - 1; + + // 检查光标是否在方法体内 + if (cursorOffset < methodStartOffset || cursorOffset > methodEndOffset) { + // 光标不在方法体内,移动光标到方法体最后一个字符后面 + ApplicationManager.getApplication().invokeAndWait(() -> { + editor.getCaretModel().moveToOffset(methodEndOffset); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + }); + return methodEndOffset; + } + + Document document = editor.getDocument(); + // 获取当前行号 + int currentLineNumber = document.getLineNumber(cursorOffset); + + int lineStartOffset = document.getLineStartOffset(currentLineNumber); + // 获取当前行的结束偏移量 + int lineEndOffset = document.getLineEndOffset(currentLineNumber); + + // 检查cursorOffset前面是否有字符 + boolean hasCharactersBeforeCursor = cursorOffset > lineStartOffset; + + // 没有在行尾 + if (cursorOffset <= lineEndOffset) { + int num = hasCharactersBeforeCursor ? 1 : 0; + ApplicationManager.getApplication().invokeAndWait(() -> { + if (hasCharactersBeforeCursor) { + WriteCommandAction.runWriteCommandAction(editor.getProject(), () -> editor.getDocument().insertString(lineEndOffset, "\n")); + } + editor.getCaretModel().moveToOffset(lineEndOffset + num); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + }); + return lineEndOffset + num; + } + + return cursorOffset; + } + + public static String getFirstClassName(PsiFile psiFile) { + PsiClass psiClass = PsiTreeUtil.findChildOfType(psiFile, PsiClass.class); + if (psiClass != null) { + return psiClass.getName(); + } + return null; + } + + //鼠标移动到注释末尾 + public static void moveCaretToCommentEnd(@NotNull Project project, @NotNull PsiComment comment) { + // 获取编辑器 + PsiFile file = comment.getContainingFile(); + if (file == null) return; + + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null) return; + + // 获取注释的结束偏移量 + int endOffset = comment.getTextRange().getEndOffset(); + + // 移动光标到注释的末尾 + editor.getCaretModel().moveToOffset(endOffset); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + } + + //基于鼠标位置判断是否是注释,并将光标移动到注释末尾 + public static void moveCaretToCommentEnd(Editor editor) { + // 获取光标的逻辑位置 + LogicalPosition logicalPosition = editor.getCaretModel().getLogicalPosition(); + int offset = editor.logicalPositionToOffset(logicalPosition); + // 获取当前文件 + Document document = editor.getDocument(); + // 检查光标是否在多行注释中 + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(document); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiComment comment = PsiTreeUtil.getParentOfType(elementAtCaret, PsiComment.class); + + if (null != comment) { + EditorUtils.moveCaretToCommentEnd(editor.getProject(), comment); + } + } + + public static boolean isNotClassHeaderComment(@NotNull PsiComment comment) { + PsiElement parent = comment.getParent(); + if (parent instanceof PsiClass) { + PsiClass psiClass = (PsiClass) parent; + PsiElement firstElement = psiClass.getFirstChild(); + if (firstElement instanceof PsiComment && firstElement == comment) { + return false; + } + } + return true; + } + + + // PsiComment是否在方法体内 + public static boolean isCommentInsideMethod(@NotNull PsiComment comment) { + PsiMethod psiMethod = PsiTreeUtil.getParentOfType(comment, PsiMethod.class); + return psiMethod != null; + } + + public static boolean isNotLicenseComment(@NotNull PsiComment comment) { + PsiFile file = comment.getContainingFile(); + if (file != null) { + PsiElement firstElement = file.getFirstChild(); + if (firstElement instanceof PsiComment && firstElement == comment) { + return false; + } + } + return true; + } + + //PsiComment是否在class范围内 + public static boolean isCommentInsideClass(@NotNull PsiComment comment) { + PsiClass psiClass = PsiTreeUtil.getParentOfType(comment, PsiClass.class); + return psiClass != null; + } + + //判断当前光标是否在注释上 + public static boolean isCursorInComment(PsiMethod psiMethod) { + Project project = psiMethod.getProject(); + // 获取编辑器 + PsiFile file = psiMethod.getContainingFile(); + if (file == null) return false; + //获取editor + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null) return false; + + int offset = editor.getCaretModel().getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + if (null == elementAtCaret) { + return false; + } + PsiComment comment = PsiTreeUtil.getParentOfType(elementAtCaret, PsiComment.class); + return null != comment; + } + + + + public static boolean isNotMethodComment(@NotNull PsiComment comment) { + return !(comment.getParent() instanceof PsiMethod); + } + + // 判断当前光标位置是否是在注释上,如果是,获取当前PsiComment并返回,如果当前行为空,则获取前一行的PsiComment + public static PsiComment getPsiComment(Editor editor) { + int offset = editor.getCaretModel().getOffset(); + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument()); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiComment comment = PsiTreeUtil.getParentOfType(elementAtCaret, PsiComment.class); + if(comment == null){ + comment = getPreviousLinePsiComment(editor); + } + return comment; + } + + // 获取当前光标前一行的PsiComment + public static PsiComment getPreviousLinePsiComment(Editor editor) { + if (editor == null) { + return null; + } + Document document = editor.getDocument(); + int caretOffset = editor.getCaretModel().getOffset(); + int lineNumber = document.getLineNumber(caretOffset); + if (lineNumber == 0) { + return null; // 光标在第一行,没有前一行 + } + int previousLineStartOffset = document.getLineStartOffset(lineNumber - 1); + PsiFile psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(document); + PsiElement elementAtPreviousLine = psiFile.findElementAt(previousLineStartOffset); + return PsiTreeUtil.getParentOfType(elementAtPreviousLine, PsiComment.class); + } +} + +// 快排 diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/FileUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FileUtils.java similarity index 94% rename from athena-all/src/main/java/run/mone/m78/ip/util/FileUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FileUtils.java index 88d005ac7..d31478b03 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/FileUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FileUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import lombok.SneakyThrows; @@ -29,7 +29,7 @@ */ public class FileUtils { - private static String serverUrl = ""; + private static String serverUrl = "http://127.0.0.1:9999"; public static void upload(String name, String path) throws IOException { System.out.println("upload:" + name); diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FixCodeUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FixCodeUtils.java new file mode 100644 index 000000000..f5a42048e --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/FixCodeUtils.java @@ -0,0 +1,103 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.service.AthenaCodeService; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Slf4j +public class FixCodeUtils { + + private static final Map BASIC_CLASSES = new HashMap<>(); + + private static final Pattern BO_PATTERN = Pattern.compile("$.\\.bo\\."); + + static { + // 初始化 Java 基础类集合 + BASIC_CLASSES.put("ArrayList", "java.util.ArrayList"); + BASIC_CLASSES.put("List", "java.util.List"); + BASIC_CLASSES.put("Map", "java.util.Map"); + BASIC_CLASSES.put("HashMap", "java.util.HashMap"); + BASIC_CLASSES.put("Serializable", "java.io.Serializable"); + } + + public static boolean isBO(String fqcn) { + Matcher matcher = BO_PATTERN.matcher(fqcn); + return matcher.matches(); + } + + public static String addDataAnnotationForClass(String code, AthenaClassInfo athenaClassInfo) { + //检查import里有没有lombok.Data, 没有则添加import lombok.Data; + if (athenaClassInfo.getImports() != null + && !athenaClassInfo.getImports().contains("lombok.Data")) { + code = addImportStatements(code, Arrays.asList("import lombok.Data;")); + } + + //检查annotations里有没有Data, 没有则添加@Data + if (athenaClassInfo.getAnnoList() != null + && !athenaClassInfo.getAnnoList().contains("Data")) { + code = addAnnotationStatements(code, Arrays.asList("@Data")); + } + + return code; + } + + public static String addBasicImportForClass(String code, AthenaClassInfo athenaClassInfo) { + List existImports = (athenaClassInfo.getImports() == null) ? new ArrayList<>() : athenaClassInfo.getImports(); + List needImports = analyzeBasicClassesUsed(code); + + List importStatements = needImports.stream().filter(it -> !existImports.contains(it)).map(it -> { + return "import " + it + ";"; + }).collect(Collectors.toList()); + + return addImportStatements(code, importStatements); + } + + private static List analyzeBasicClassesUsed(String code) { + return BASIC_CLASSES.entrySet().stream().filter(it -> code.contains(it.getKey())).map(Map.Entry::getValue).collect(Collectors.toList()); + } + + private static String addImportStatements(String code, List importStatements) { + if (importStatements == null || importStatements.size() == 0) { + return code; + } + + int packageIndex = code.indexOf("package "); + int importIndex = code.indexOf("import "); + String tmpImport = importStatements.stream() + .map(importStatement -> importStatement + "\n") + .collect(Collectors.joining()); + // 如果已经存在 import 语句,则将 import 语句插入到第一个 import 语句之前 + if (importIndex != -1) { + return code.substring(0, importIndex) + tmpImport + code.substring(importIndex); + } else if (packageIndex != -1) { + // 如果不存在 import 语句但存在 package 语句,则将 import 语句插入到 package 语句的下一行 + int lineEndIndex = code.indexOf(';', packageIndex); + return code.substring(0, lineEndIndex + 1) + "\n" + tmpImport + code.substring(lineEndIndex + 1); + } else { + // 如果都不存在,则将 import 语句插入到最前面 + return tmpImport + code; + } + } + + private static String addAnnotationStatements(String code, List annotations) { + if (annotations == null || annotations.size() == 0) { + return code; + } + + String tmpAnnotation = annotations.stream() + .map(importStatement -> importStatement + "\n") + .collect(Collectors.joining()); + // 在类定义上方添加注解 + int index = code.indexOf("public class"); + if (index != -1) { + code = code.substring(0, index) + tmpAnnotation + code.substring(index); + } + return code; + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/GitUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/GitUtils.java new file mode 100644 index 000000000..6d2f7d764 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/GitUtils.java @@ -0,0 +1,125 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.google.common.base.Joiner; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import lombok.SneakyThrows; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2023/7/8 23:19 + */ +public class GitUtils { + + + /** + * 获取项目中受影响的文件名列表。 + * + * @param project 项目对象 + * @return 受影响的文件名列表 + */ + public static List getAffectedFileNames(Project project) { + ChangeListManager changeListManager = ChangeListManager.getInstance(project); + return changeListManager.getAffectedFiles().stream().map(it -> it.toString()).collect(Collectors.toList()); + } + + public static String getAffectedFileNamesStr(Project project) { + ChangeListManager changeListManager = ChangeListManager.getInstance(project); + List list = changeListManager.getAffectedFiles().stream().map(it -> it.toString()).collect(Collectors.toList()); + return list.stream().collect(Collectors.joining("\n")); + } + + + //获取git地址 + @SneakyThrows + public static String getGitAddress(Project project) { + try { + String path = project.getBasePath(); + path = Joiner.on(File.separator).join(path, ".git", "config"); + return Files.readAllLines(Paths.get(path)).stream().filter(it -> it.contains("url")).map(it -> (it.split("=")[1].trim())).findAny().get(); + } catch (Throwable ignore) { + + } + return ""; + } + + //获取最后一条commit记录 + @SneakyThrows + public static List getLastCommit(Project project) { + List res = new ArrayList<>(); + try { + String path = project.getBasePath(); + path = Joiner.on(File.separator).join(path, ".git"); + Process process = Runtime.getRuntime().exec("git --git-dir=" + path + " log -3 --pretty=format:\"%H\""); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + int commitCount = 0; + while ((line = reader.readLine()) != null) { + if (commitCount < 3) { + res.add(line); + } else { + break; + } + commitCount++; + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return res; + } + + public static String getCommitDiff(Project project) { + StringJoiner res = new StringJoiner(System.lineSeparator()); + try { + // 获取diff内容 + String path = project.getBasePath(); + path = Joiner.on(File.separator).join(path, ".git"); + Process diffProcess = Runtime.getRuntime().exec("git --git-dir=" + path + " --work-tree=" + project.getBasePath() + " diff HEAD"); + try (BufferedReader diffReader = new BufferedReader(new InputStreamReader(diffProcess.getInputStream()))) { + String line; + while ((line = diffReader.readLine()) != null) { + res.add(line); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return res.toString(); + } + + public static String getCurrentBranch(Project project) { + String branch = ""; + try { + // 执行git命令 + String path = project.getBasePath(); + path = Joiner.on(File.separator).join(path, ".git"); + Process process = Runtime.getRuntime().exec("git --git-dir=" + path + " --work-tree=" + project.getBasePath() + " rev-parse --abbrev-ref HEAD"); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + branch = reader.readLine(); + process.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + return branch; + } + + public static String getProjectNameFromGitUrl(String gitUrl) { + String urlWithoutProtocol = gitUrl.replaceFirst("^\\w+://|^\\w+@", ""); + String urlWithoutExtension = urlWithoutProtocol.replaceFirst("\\.git$", ""); + String[] parts = urlWithoutExtension.split("/"); + String projectName = parts[parts.length - 1]; + return projectName; + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/HintUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/HintUtils.java similarity index 86% rename from athena-all/src/main/java/run/mone/m78/ip/util/HintUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/HintUtils.java index 6c9a5aca7..9b759c38f 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/HintUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/HintUtils.java @@ -14,14 +14,18 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.google.gson.Gson; import com.intellij.codeInsight.hint.HintManager; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; -import run.mone.m78.ip.bo.Result; -import run.mone.m78.ip.common.ChromeUtils; +import com.intellij.openapi.project.Project; +import com.xiaomi.youpin.tesla.ip.bo.Result; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; /** * @Author goodjava@qq.com diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ImportUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ImportUtils.java new file mode 100644 index 000000000..3c8e90d5a --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ImportUtils.java @@ -0,0 +1,161 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.google.common.base.Splitter; +import com.intellij.codeInsight.actions.OptimizeImportsAction; +import com.intellij.codeInspection.unusedImport.UnusedImportInspection; +import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.PsiJavaFileImpl; +import com.intellij.psi.util.PsiTreeUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2023/6/22 21:41 + */ +@Slf4j +public abstract class ImportUtils { + + public static void removeInvalidImports(Project project, Editor editor) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiImportList importList = PsiTreeUtil.findChildOfType(psiFile, PsiImportList.class); + UnusedImportInspection unusedImportInspection = new UnusedImportInspection(); + if (importList != null) { + boolean modify = false; + if (importList != null) { + for (PsiImportStatementBase importStatement : importList.getAllImportStatements()) { + PsiJavaCodeReferenceElement importReference = importStatement.getImportReference(); + if (importReference != null && importReference.resolve() != null && importReference.multiResolve(true).length == 0) { + modify = true; + importStatement.delete(); + } + } + } + if (modify) { + PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(editor.getDocument()); + } + } + }); + } + + public static void optimizeImports(Project project, Editor editor) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + AnActionEvent event = AnActionEvent.createFromDataContext( + ActionPlaces.UNKNOWN, + null, + dataId -> { + if (CommonDataKeys.PSI_FILE.is(dataId)) { + return psiFile; + } else if (CommonDataKeys.PROJECT.is(dataId)) { + return project; + } else if (CommonDataKeys.EDITOR.is(dataId)) { + return editor; + } else { + return null; + } + } + ); + new OptimizeImportsAction().actionPerformed(event); + }); + } + + + public static void addImport(Project project, Editor editor, List importStrList) { + try { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + Document document = editor.getDocument(); + PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + PsiImportList importList = PsiTreeUtil.findChildOfType(psiFile, PsiImportList.class); + for (String importStr : importStrList) { + boolean isAlreadyImported = false; + boolean isStatic = false; + String memberName = ""; + if (importStr.contains("static ")) { + isStatic = true; + importStr = importStr.trim().split(" +")[1]; + String[] array = importStr.split("\\."); + importStr = Arrays.stream(array).limit(array.length - 1).collect(Collectors.joining(".")); + memberName = array[array.length - 1]; + } + for (PsiImportStatement importStatement : importList.getImportStatements()) { + String str = importStr; + List list = Splitter.on(" ").splitToList(importStr.replace(";", "")); + if (list.size() > 0) { + str = list.get(list.size() - 1); + } + if (importStatement.getQualifiedName().equals(str)) { + isAlreadyImported = true; + break; + } + } + if (!isAlreadyImported) { + PsiClass psiClass = createPsiClass(factory, importStr); + if (null == psiClass) { + continue; + } + PsiImportStatementBase importStatement = null; + + if (isStatic) { + importStatement = factory.createImportStaticStatement(psiClass, memberName); + } else { + importStatement = factory.createImportStatement(psiClass); + } + + if (importList != null) { + importList.add(importStatement); + PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(document); + } + } + } + }); + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + } + } + + public static PsiClass createPsiClass(PsiElementFactory factory, String className) { + try { + String[] array = className.split("\\."); + PsiClass psiClass = factory.createClass(array[array.length - 1]); + PsiJavaFile javaFile = (PsiJavaFile) psiClass.getContainingFile(); + javaFile.setPackageName(Arrays.stream(array).limit(array.length - 1).collect(Collectors.joining("."))); + return psiClass; + } catch (Throwable ex) { + return null; + } + } + + + public static String junitVersion(PsiClass psiClass) { + PsiElement c = psiClass.getParent(); + if (c instanceof PsiJavaFileImpl pfi) { + String text = pfi.getImportList().getText(); + if (StringUtils.isEmpty(text)) { + return "unknow"; + } + if (text.contains("org.junit.Test")) { + return "junit"; + } + if (text.contains("org.junit.jupiter.api.Test")) { + return "jupiter"; + } + } + return "unknow"; + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/LabelUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LabelUtils.java similarity index 88% rename from athena-all/src/main/java/run/mone/m78/ip/util/LabelUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LabelUtils.java index 9f0961916..0e10a22e4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/LabelUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LabelUtils.java @@ -1,11 +1,11 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.google.common.base.Joiner; import com.google.common.collect.Maps; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.ParamDialogReq; -import run.mone.m78.ip.dialog.ParamTableDialog; -import run.mone.m78.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.ParamDialogReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.dialog.ParamTableDialog; import java.util.Map; @@ -17,6 +17,7 @@ public class LabelUtils { public static String getLabelValue(Project project, PromptInfo promptInfo, String key, String defaultValue) { + //用户配置的优先级最高 Map map = ResourceUtils.getAthenaConfig(project); String rkey = Joiner.on("@").join(promptInfo.getPromptName(), key); if (map.containsKey(rkey)) { diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/LockUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LockUtils.java similarity index 85% rename from athena-all/src/main/java/run/mone/m78/ip/util/LockUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LockUtils.java index 4b76fe0a9..06ae2b58c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/LockUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/LockUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.openapi.editor.Editor; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkDownUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkDownUtils.java new file mode 100644 index 000000000..a2c92f123 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkDownUtils.java @@ -0,0 +1,48 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.vladsch.flexmark.ast.FencedCodeBlock; +import com.vladsch.flexmark.parser.Parser; +import com.vladsch.flexmark.util.ast.Document; +import com.vladsch.flexmark.util.ast.NodeVisitor; +import com.vladsch.flexmark.util.ast.VisitHandler; +import com.vladsch.flexmark.util.sequence.BasedSequence; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; + +/** + * @author goodjava@qq.com + * @date 2024/3/12 11:07 + */ +public class MarkDownUtils { + + + public static String extractCodeBlock(String markdown) { + try { + // 创建Markdown解析器 + Parser parser = Parser.builder().build(); + Document document = parser.parse(markdown); + Mutable res = new MutableObject<>(""); + // 创建自定义访问者,用于移除所有的代码块 + NodeVisitor visitor = new NodeVisitor(new VisitHandler(FencedCodeBlock.class, node -> { + FencedCodeBlock codeBlock = (FencedCodeBlock) node; + BasedSequence info = codeBlock.getInfo(); + // 检查代码块的语言标记是否为"json" + if (info.equals("json") || info.equals("java")) { + // 如果是,则从文档中移除该代码块 + res.setValue(codeBlock.getChildChars().toString()); + } + })); + + visitor.visit(document); + + if (StringUtils.isNotEmpty(res.getValue())) { + return res.getValue(); + } + return markdown; + } catch (Throwable ignore) { + return markdown; + } + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkdownFilter.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkdownFilter.java new file mode 100644 index 000000000..1f537516d --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/MarkdownFilter.java @@ -0,0 +1,62 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author goodjava@qq.com + * @date 2024/1/31 11:27 + */ +public class MarkdownFilter { + + + private static final Pattern START_PATTERN = Pattern.compile("```"); + private static final Pattern JAVA_PATTERN = Pattern.compile("\\bjava\\b|\\bgo\\b"); + private static final Pattern END_PATTERN = Pattern.compile("```$"); + private final Consumer codeConsumer; + private boolean inCodeBlock = false; + private boolean checkForJava = false; + + public MarkdownFilter(Consumer codeConsumer) { + this.codeConsumer = codeConsumer; + } + + public void accept(String str) { + if (inCodeBlock) { + Matcher endMatcher = END_PATTERN.matcher(str); + if (endMatcher.find()) { + inCodeBlock = false; + accept(str.substring(endMatcher.end())); + } else { + codeConsumer.accept(str); + } + } else if (checkForJava) { + Matcher javaMatcher = JAVA_PATTERN.matcher(str); + if (javaMatcher.lookingAt()) { + inCodeBlock = true; + // 处理java标记之后的内容 + accept(str.substring(javaMatcher.end())); + } else { + // 如果不是java,则发送之前缓存的```和当前字符串 + codeConsumer.accept("```" + str); + } + checkForJava = false; + } else { + Matcher startMatcher = START_PATTERN.matcher(str); + if (startMatcher.find()) { + checkForJava = true; + // 发送开始标记之前的内容 + codeConsumer.accept(str.substring(0, startMatcher.start())); + // 检查剩余的字符串是否以java开始 + String remaining = str.substring(startMatcher.end()); + if (!remaining.isEmpty()) { + accept(remaining); + } + } else { + codeConsumer.accept(str); + } + } + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/NetUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/NetUtils.java new file mode 100644 index 000000000..07eef84e8 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/NetUtils.java @@ -0,0 +1,154 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; + +import java.io.IOException; +import java.net.*; +import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + */ +@Slf4j +public class NetUtils { + + + private static volatile InetAddress LOCAL_ADDRESS = null; + + public static final String LOCALHOST = "127.0.0.1"; + public static final String ANYHOST = "0.0.0.0"; + public static final String DOCKERHOST = "172.17.0.1"; + + public static final String LOCALHOST2 = "192."; + + + + private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + + private static final int RND_PORT_START = 30000; + + private static final int MAX_PORT = 65535; + + private static final Random RANDOM = new Random(System.currentTimeMillis()); + + private static final int RND_PORT_RANGE = 10000; + + + public static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + log.error("get host name error:{}", e.getMessage()); + return ""; + } + } + + + public static String getLocalHost() { + InetAddress address = getLocalAddress(); + return address == null ? LOCALHOST : address.getHostAddress(); + } + + public static InetAddress getLocalAddress() { + if (LOCAL_ADDRESS != null) { + return LOCAL_ADDRESS; + } + InetAddress localAddress = getLocalAddress0(); + LOCAL_ADDRESS = localAddress; + return localAddress; + } + + private static InetAddress getLocalAddress0() { + InetAddress localAddress = null; + try { + localAddress = InetAddress.getLocalHost(); + if (localAddress instanceof Inet6Address) { + Inet6Address address = (Inet6Address) localAddress; + if (isValidV6Address(address)) { + return normalizeV6Address(address); + } + } else if (isValidAddress(localAddress)) { + return localAddress; + } + } catch (Throwable e) { + log.warn(e.getMessage()); + } + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (null == interfaces) { + return localAddress; + } + while (interfaces.hasMoreElements()) { + try { + NetworkInterface network = interfaces.nextElement(); + Enumeration addresses = network.getInetAddresses(); + while (addresses.hasMoreElements()) { + try { + InetAddress address = addresses.nextElement(); + if (address instanceof Inet6Address) { + Inet6Address v6Address = (Inet6Address) address; + if (isValidV6Address(v6Address)) { + return normalizeV6Address(v6Address); + } + } else if (isValidAddress(address)) { + return address; + } + } catch (Throwable e) { + log.warn(e.getMessage()); + } + } + } catch (Throwable e) { + log.warn(e.getMessage()); + } + } + } catch (Throwable e) { + log.warn(e.getMessage()); + } + return localAddress; + } + + static boolean isValidV6Address(Inet6Address address) { + boolean preferIpv6 = Boolean.getBoolean("java.net.preferIPv6Addresses"); + if (!preferIpv6) { + return false; + } + try { + return address.isReachable(100); + } catch (IOException e) { + // ignore + } + return false; + } + + static InetAddress normalizeV6Address(Inet6Address address) { + String addr = address.getHostAddress(); + int i = addr.lastIndexOf('%'); + if (i > 0) { + try { + return InetAddress.getByName(addr.substring(0, i) + '%' + address.getScopeId()); + } catch (UnknownHostException e) { + // ignore + log.debug("Unknown IPV6 address: ", e); + } + } + return address; + } + + + static boolean isValidAddress(InetAddress address) { + if (address == null || address.isLoopbackAddress()) { + return false; + } + String name = address.getHostAddress(); + return (name != null + && !ANYHOST.equals(name) + && !LOCALHOST.equals(name) + && !name.startsWith(LOCALHOST2) + && !DOCKERHOST.equals(name) + && IP_PATTERN.matcher(name).matches()); + } + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/Notify.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/Notify.java similarity index 90% rename from athena-all/src/main/java/run/mone/m78/ip/util/Notify.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/Notify.java index 5af8e5c61..3d6acd39b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/Notify.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/Notify.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.notification.*; @@ -38,6 +38,8 @@ public class Notify { public static void show(@NotNull Project project, @NotNull String title, @NotNull String content, @NotNull NotificationGroup group, @NotNull NotificationType type, @Nullable NotificationListener listener) { + Notification notification = group.createNotification(title, content, type, listener); + Notifications.Bus.notify(notification, project); } public static void show(@NotNull Project project, diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/PackageUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PackageUtils.java similarity index 83% rename from athena-all/src/main/java/run/mone/m78/ip/util/PackageUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PackageUtils.java index a03c0b06e..314fa29b7 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/PackageUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PackageUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.openapi.project.Project; import com.intellij.psi.JavaPsiFacade; @@ -15,6 +15,13 @@ public class PackageUtils { + /** + * 获取指定项目和包名下的所有类名列表 + * + * @param project 项目对象 + * @param packageName 包名 + * @return 类名列表 + */ public static List getClassList(Project project, String packageName) { PsiPackage psiPackage = JavaPsiFacade.getInstance(project).findPackage(packageName); List result = new ArrayList<>(); diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/ProjectUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ProjectUtils.java similarity index 74% rename from athena-all/src/main/java/run/mone/m78/ip/util/ProjectUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ProjectUtils.java index 2629d93c4..2b12b69af 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/ProjectUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ProjectUtils.java @@ -14,15 +14,21 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.google.common.collect.Lists; import com.intellij.ide.DataManager; import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.impl.OpenProjectTask; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.actionSystem.DataConstants; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; @@ -32,6 +38,7 @@ import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; @@ -42,13 +49,14 @@ import com.intellij.psi.PsiManager; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiUtilBase; +import com.xiaomi.youpin.codegen.M78DoceanMongoGen; +import com.xiaomi.youpin.infra.rpc.Result; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; import java.util.stream.Collectors; /** @@ -70,7 +78,7 @@ public static Project projectFromManager() { } public static Project projectFromManager(String name) { - return null; + return Arrays.stream(ProjectManager.getInstance().getOpenProjects()).filter(it -> it.getName().equals(name)).findFirst().get(); } /** @@ -212,5 +220,43 @@ public static String getModulePath(Project project, String moduleName) { return new File(module.getModuleFilePath()).getParent(); } + public static void openProject(Project project, String projectPathStr) { + ApplicationManager.getApplication().invokeLater(() -> { + // 获取本地文件系统 + ProjectManagerEx projectManager = ProjectManagerEx.getInstanceEx(); + Path projectPath = Paths.get(projectPathStr); + OpenProjectTask openProjectTask = new OpenProjectTask(false, project, true, false); + projectManager.openProject(projectPath, openProjectTask); + }); + } + public Optional generateProjectBase(Project project, String projectName, String packageName, String groupId, String author) { + VirtualFile contentRoot = ProjectRootManager.getInstance(project).getContentRoots()[0]; + String path = contentRoot.getPath(); + File projectRoot = new File(path); + String absolutePath = projectRoot.getParentFile().getAbsolutePath(); + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + try { + PluginId pluginId = PluginManagerCore.getPluginByClassName(this.getClass().getName()); + if (pluginId != null) { + IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId); + if (plugin != null) { + Thread.currentThread().setContextClassLoader(plugin.getPluginClassLoader()); + } + } + M78DoceanMongoGen m78DoceanMongoGen = new M78DoceanMongoGen(); + Result autoapp = m78DoceanMongoGen.generateAndZip(absolutePath, projectName, groupId, packageName, author, "1.0.0", null); + if (autoapp.getCode() == 0) { + return Optional.of(absolutePath + "/" + projectName); + } + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + + return Optional.empty(); + + } } + + + diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PromptUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PromptUtils.java new file mode 100644 index 000000000..688c5a90e --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PromptUtils.java @@ -0,0 +1,675 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.bo.prompt.PromptParam; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.consumer.CodeConsumer; +import com.xiaomi.youpin.tesla.ip.dialog.*; +import com.xiaomi.youpin.tesla.ip.service.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.ultraman.background.AthenaEditorTask; +import run.mone.ultraman.background.AthenaTask; +import run.mone.ultraman.common.Code; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.http.HttpClient; + +import java.lang.reflect.Type; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2023/5/29 10:09 + */ +@Slf4j +public class PromptUtils { + + + private static final Gson gson = new Gson(); + + + public static Map getParamsFromAiProxy(String promptName, String metaStr) { + return getParamsFromAiProxy(promptName, metaStr, false); + } + + public static Map getParamsFromAiProxy(String promptName, String metaStr, boolean useSelect) { + try { + String aiRes = HttpClient.callAiProxy("params", ImmutableMap.of("name", promptName)); + Type typeOfT = new TypeToken>() { + }.getType(); + Map m = gson.fromJson(aiRes, typeOfT); + Map v = m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> "")); + if (useSelect) { + return v; + } + //使用meta中的信息 + if (StringUtils.isNotEmpty(metaStr)) { + Type to = new TypeToken>() { + }.getType(); + List promptParamList = gson.fromJson(metaStr, to); + promptParamList.forEach(it -> v.put(it.getName(), it)); + } + return v; + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + return Maps.newHashMap(); + } + } + + + /** + * 创建类(class enum) + * + * @param project + * @param modelName + * @param promptName + */ + public static void createClass(Project project, final String modelName, String promptName) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + List classMetas = gson.fromJson(promptInfo.getMeta(), new TypeToken>() { + }.getType()); + CreateClassMeta createClassMeta = CollectionUtils.isEmpty(classMetas) ? null : classMetas.get(0); + Editor editor = CodeService.getEditor(project); + String[] params = getParams(createClassMeta, editor); + Map v = getParamsFromAiProxy(promptName, promptInfo.getMeta(), ObjectUtils.notEqual(null, createClassMeta) && createClassMeta.isUseSelect()); + Map> mList = new HashMap<>(); + mList.put("module", ProjectUtils.listAllModules(project)); + ParamTableDialog ppt = new ParamTableDialog(ParamDialogReq.builder().title("param").build(), project, v, mList, promptInfo); + ppt.setConsumer((values) -> { + String packageStr = values.get("package").toString(); + String className = values.get("class").toString(); + String modulePath = values.get("module").toString(); + String newModelName = StringUtils.isNotBlank(modulePath) ? modulePath : getModelName(modelName, values); + + CodeService.createEmptyClass(project, newModelName, packageStr, className); + PsiClass psiClass = CodeService.getPsiClass2(project); + TextRange textRange = psiClass.getTextRange(); + CodeService.deleteTextRange(project, psiClass.getTextRange()); + Editor codeEditor = CodeService.getEditor(project); + codeEditor.getCaretModel().moveToOffset(textRange.getStartOffset()); + Map pm = values.entrySet().stream().collect(Collectors.toMap(en -> en.getKey(), en -> en.getValue().toString())); + CodeService.generateCodeWithAi3(project, promptName, params, pm, (p, code) -> CodeService.writeCode2(p, codeEditor, code)); + }); + ppt.show(); + } + + private static String getModelName(String modelName, Map values) { + if (StringUtils.isEmpty(modelName)) { + modelName = values.getOrDefault("module", "").toString(); + } + return modelName; + } + + @Nullable + private static String[] getParams(CreateClassMeta createClassMeta, Editor editor) { + String[] params = null; + if (ObjectUtils.notEqual(null, createClassMeta) && createClassMeta.isUseSelect()) { + params = new String[]{EditorUtils.getSelectContent(editor)}; + } + return params; + } + + + public static void createClass2(Project project, String promptName, String showDialog, Map param) { + String isShowDialog = StringUtils.isEmpty(showDialog) ? "true" : showDialog; + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + Map v = getParamsFromAiProxy(promptName, promptInfo.getMeta()); + if ("true".equals(isShowDialog)) { + String url = buildDialogUrl(project, v, promptInfo); + ChromeDialog chromeDialog = new ChromeDialog(url, project); + chromeDialog.show(); + return; + } + + String packageStr = param.get("package").toString(); + String className = param.get("class").toString(); + String modelName = param.get("modelName").toString(); + + CodeService.createEmptyClass(project, modelName, packageStr, className); + + PsiClass psiClass = CodeService.getPsiClass2(project); + TextRange textRange = psiClass.getTextRange(); + CodeService.deleteTextRange(project, psiClass.getTextRange()); + Editor codeEditor = CodeService.getEditor(project); + codeEditor.getCaretModel().moveToOffset(textRange.getStartOffset()); + + Map pm = param.entrySet().stream().collect(Collectors.toMap(en -> en.getKey(), en -> en.getValue().toString())); + CodeService.generateCodeWithAi3(project, promptName, new String[]{}, pm, (p, code) -> CodeService.writeCode2(p, codeEditor, code)); + + } + + + public static void createClass3(Project project, String promptName, Map param) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + + String packageStr = param.get("package").toString(); + String className = param.get("class").toString(); + String modelName = param.get("modelName").toString(); + + CodeService.createEmptyClass(project, modelName, packageStr, className); + + PsiClass psiClass = CodeService.getPsiClass2(project); + TextRange textRange = psiClass.getTextRange(); + CodeService.deleteTextRange(project, psiClass.getTextRange()); + Editor codeEditor = CodeService.getEditor(project); + codeEditor.getCaretModel().moveToOffset(textRange.getStartOffset()); + + } + + + /** + * $$->隐藏 + * $@$->选择框 + * + * @param project + * @param param + * @param promptInfo + * @return + */ + private static String buildDialogUrl(Project project, Map param, PromptInfo promptInfo) { + if (!param.containsKey("model")) { + param.put("$@$model", ProjectUtils.listAllModules(project)); + } + if (!param.containsKey("package")) { + param.put("package", ""); + } + if (param.containsKey("class")) { + param.put("class", ""); + } + param.put("$$showDialog", "false"); + param.put("$$prompt", promptInfo.getPromptName()); + param.put("$$desc", promptInfo.getDesc()); + return ConfigUtils.getConfig().getChatServer() + "/code-form" + "?param=" + URLEncoder.encode(gson.toJson(param)); + } + + /** + * 给方法添加注释 + * + * @param req + */ + public static void addComment(GenerateCodeReq req) { + Project project = req.getProject(); + PsiMethod method = CodeService.getMethod(project); + Editor editor = CodeService.getEditor(project); + if (null == method) { + HintUtils.show(editor, Message.selectMethodMsg, true); + return; + } + String c = method.getText(); + Map map = Maps.newHashMap(); + map.put("code", c); + + AthenaTask task = new AthenaTask(req.getProject(), "Athena", req.getPromptName(), "", map); + task.setType("method_comment"); + PromptContext context = new PromptContext(); + context.setEditor(editor); + task.setPromptContext(context); + task.setReq(req); + AthenaTask.start(task); + } + + + /** + * 修改class + * + * @param project + * @param promptName + */ + public static void modifyClass(Project project, String promptName) { + PsiClass psiClass = CodeService.getPsiClass2(project); + String codeStr = psiClass.getText(); + CodeService.deletePsiClass(project, psiClass); + Editor codeEditor = CodeService.getEditor(project); + CodeService.generateCodeWithAi2(project, promptName, new String[]{codeStr}, (p, code) -> CodeService.writeCode2(p, codeEditor, code)); + } + + + /** + * 创建一个文件 + * + * @param req + */ + public static void createFile(String promptName, String fileName, GenerateCodeReq req) { + fileName = req.getPromptInfo().getLabels().getOrDefault("fileName", "athena_"); + String scope = req.getPromptInfo().getLabels().getOrDefault("scope", "method"); + String codeStr = ""; + if (scope.equals("method")) { + codeStr = CodeService.getMethod(req.getProject()).getText(); + } else if (scope.equals("class")) { + PsiClass psiClass = CodeService.getPsiClass(req.getProject()); + codeStr = psiClass.getText(); + fileName = fileName + psiClass.getName(); + } else if (scope.equals("select")) { + codeStr = CodeService.getSelectedText(CodeService.getEditor(req.getProject())); + } + final String c = codeStr; + TextService.writeContent(req.getProject(), fileName + ".md", req.getModule().getName(), () -> { + Editor editor = CodeService.getEditor(req.getProject()); + Map m = Maps.newHashMap(); + m.put("code", c); + CodeService.generateCodeWithAi3(req.getProject(), promptName, new String[]{req.getMeta()}, m, (p, code) -> CodeService.writeCode4(p, editor, code, false)); + }); + } + + /** + * 修改一个类,会清空编辑区的所有内容 + * + * @param req + */ + public static void updateClass(GenerateCodeReq req) { + PsiClass psiClass = CodeService.getPsiClass(req.getProject()); + String classCode = psiClass.getText(); + TextRange textRange = psiClass.getTextRange(); + CodeService.deleteTextRange(req.getProject(), textRange); + Editor editor = CodeService.getEditor(req.getProject()); + CodeService.generateCodeWithAi2(req.getProject(), req.getPromptName(), new String[]{classCode}, (p, code) -> CodeService.writeCode2(p, editor, code)); + } + + public static void modifyMethod(GenerateCodeReq req) { + Editor editor = CodeService.getEditor(req.getProject()); + if (null == editor) { + return; + } + //修改方法名 + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "modify_method_name") || LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "modify_method_param_name")) { + Map m = new HashMap<>(); + + PsiMethod method = CodeService.getMethod(req.getProject()); + if (null == method) { + HintUtils.show(editor, com.xiaomi.youpin.tesla.ip.bo.Message.selectMethodMsg, true); + return; + } + m.put("code", method.getText()); + m.put("paramName", req.getParam().getOrDefault("paramName", "")); + AthenaEditorTask task = new AthenaEditorTask(req, "Athena", m, new MessageConsumer() { + private StringBuilder sb = new StringBuilder(); + + @Override + public void onEvent(AiMessage message) { + sb.append(message.getText()); + } + + @Override + public void end(AiMessage message) { + if (LabelUtils.isOpen(req.getProject(), req.getPromptInfo(), "modify_method_name")) { + PsiMethodUtils.renameMethod(req.getProject(), method, sb.toString()); + } else { + PsiMethodUtils.renameParameter(req.getProject(), (PsiParameter) req.getObjMap().get("parameter"), sb.toString()); + } + } + }); + AthenaEditorTask.start(task); + } + } + + /** + * 给一个方法添加逐行注释,或者代码 + * + * @param promptName + * @param req + */ + public static void lineByLineCommentOrCode(String promptName, GenerateCodeReq req) { + Editor editor = null; + try { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + Map map = promptInfo.getLabels(); + editor = req.getEditor(); + addImportList(req.getProject(), map); + String codeStr = getCode(req, map); + codeStr = filterAnnoCode(codeStr, promptInfo); + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(req.getProject()); + @Nullable PsiFile psiFile = documentManager.getPsiFile(editor.getDocument()); + Code code = new Code(); + code.setEditor(editor); + code.setPromptInfo(promptInfo); + code.setDocument(editor.getDocument()); + code.setProject(req.getProject()); + code.setPsiFile(psiFile); + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena", codeStr, ImmutableMap.of("code", codeStr), new CodeConsumer(editor, req) { + @Override + public void onEvent(AiMessage message) { + code.append(message.getText()); + } + })); + } catch (Throwable ex) { + HintUtils.show(editor, ex.getMessage(), true); + } + } + + private static String filterAnnoCode(String codeStr, PromptInfo promptInfo) { + String str = promptInfo.getLabels().getOrDefault("delete", "").trim(); + if (StringUtils.isEmpty(str)) { + return codeStr; + } + String[] skipArray = str.split(","); + if (skipArray.length > 0) { + return codeStr.lines().map(it -> { + boolean has = Arrays.stream(skipArray).filter(it2 -> it.contains(it2)).findAny().isPresent(); + if (has) { + int begin = it.indexOf("@"); + return it.substring(0, begin); + } + return it; + }).collect(Collectors.joining("\n")); + } + return codeStr; + } + + private static void addImportList(Project project, Map map) { + if (map.containsKey("import")) { + String str = map.get("import"); + Type typeOfT = new TypeToken>() { + }.getType(); + List importList = gson.fromJson(str, typeOfT); + CodeService.addImport(project, importList); + } + } + + public static List getImportList(PromptInfo promptInfo) { + Map labels = promptInfo.getLabels(); + if (null != labels && labels.containsKey("import")) { + String str = labels.get("import"); + Type typeOfT = new TypeToken>() { + }.getType(); + List importList = gson.fromJson(str, typeOfT); + return importList; + } + return Lists.newArrayList(); + } + + /** + * 根据lable里的scope获取代码,有可能是method,也有可能是class + * + * @param req + * @param map + * @return + */ + @NotNull + private static String getCode(GenerateCodeReq req, Map map) { + String codeStr = ""; + String scope = getScope(req, map); + if (scope.equals("class")) { + codeStr = CodeService.getClassAndLineNumbers(CodeService.getPsiClass(req.getProject())); + } else { + PsiMethod method = CodeService.getMethod(req.getProject()); + if (null == method) { + throw new RuntimeException(Message.selectMethodMsg); + } + codeStr = CodeService.getMethodAndLineNumbers(method); + } + return codeStr; + } + + @NotNull + private static String getScope(GenerateCodeReq req, Map map) { + String scope = "method"; + if (null != map && map.containsKey("scope")) { + scope = map.getOrDefault("scope", "nearby"); + } + //就近选择(离method近,就是method,离class近就是class) + if (scope.equals("nearby")) { + PsiMethod method = CodeService.getMethod(req.getProject()); + if (null != method) { + scope = "method"; + } else { + scope = "class"; + } + } + return scope; + } + + + private static Pair getPackageAndClass(DialogResult result) { + String className = result.getData().get("class"); + String[] strs = className.split("\\."); + String packageStr = Arrays.stream(strs).limit(strs.length - 1).collect(Collectors.joining(".")); + return Pair.of(packageStr, strs[strs.length - 1]); + + } + + private static DialogResult showDialog(Project project, Module module, String data) { + DialogReq dialogReq = gson.fromJson(data, DialogReq.class); + dialogReq.setModule(module); + SelectClassAndMethodDialog dialog = new SelectClassAndMethodDialog(project, dialogReq); + dialog.show(); + int exitCode = dialog.getExitCode(); + if (exitCode != DialogWrapper.OK_EXIT_CODE) { + return null; + } + DialogResult result = dialog.getResult(); + return result; + } + + /** + * 生成接口 + * + * @param req + */ + public static void generateInterface(GenerateCodeReq req) { + Project project = req.getProject(); + String ps = req.getClassCode(); + Map map = new HashMap<>(); + map.put("code", ps); + String qualifiedName = req.getQualifiedName(); + String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')); + + ImportCode code = CodeService.createClassAndAddEmptyLine(project, req.getModule().getName(), packageName, req.getClassName(), "Interface", false, true); + + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena", ps, map, new MessageConsumer() { + @Override + public void onEvent(AiMessage message) { + code.append(message.getText()); + } + })); + + } + + + public static void generateTestMethod(GenerateCodeReq req) { + Project project = req.getProject(); + if (StringUtils.isEmpty(req.getMethodCode())) { + HintUtils.show(req.getEditor(), Message.selectMethodMsg, true); + return; + } + String methodCode = req.getMethodCode(); + String qualifiedName = req.getQualifiedName(); + String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')); + + ImportCode code = CodeService.createClassAndAddEmptyLine(project, req.getModule().getName(), packageName, req.getClassName(), "Test", true, false); + + Map map = new HashMap<>(); + map.put("code", "public class" + req.getClassName() + "{" + methodCode + " \n}"); + AthenaEditorTask.start(new AthenaEditorTask(req, "Athena", methodCode, map, new MessageConsumer() { + @Override + public void onEvent(AiMessage message) { + code.append(message.getText()); + } + })); + + + } + + /** + * 操作之前这里有选择(选择类名或者方法名) + * 更底层的机制是根据一段代码,生成一个方法或者替代一个方法 + *

+ * 用来生成测试方法 + */ + public static void select(GenerateCodeReq req, Project project, Module module, PromptInfo promptInfo) { + String codeClassName = CodeService.getPsiClass(project).getQualifiedName(); + PsiClass pc = CodeService.getPsiClass(project); + boolean springClass = LabelUtils.open("check_spring") && SpringUtils.isSpringClass(pc); + + PsiMethod pm = CodeService.getMethod(project); + if (null == pm) { + HintUtils.show(CodeService.getEditor(project), Message.selectMethodMsg, true); + return; + } + String methodCode = pm.getText(); + + //选择类和方法 + DialogResult result = showDialog(project, module, promptInfo.getMeta()); + + if (null == result) { + return; + } + String methodName = result.getData().get("method"); + String className = result.getData().get("class"); + + //创建新类 + if (result.getData().get("new_class").equals("true")) { + Pair pair = getPackageAndClass(result); + String addAnno = promptInfo.getLabels().getOrDefault("add_anno", ""); + List annoList = gson.fromJson(addAnno, new TypeToken>() { + }.getType()); + CodeService.createEmptyClass(project, module.getName(), pair.getKey(), pair.getValue(), true, annoList); + } + + PsiClass psiClass = CodeService.openJavaClass(project, className); + + String testClassCode = psiClass.getText(); + + Editor editor = CodeService.getEditor(project); + + Map map = new HashMap<>(); + + //spring 单元测试,需要把字段注入 + if (springClass) { + String serviceName = pc.getQualifiedName(); + String shortServiceName = pc.getNameIdentifier().getText(); + String junitVersion = ImportUtils.junitVersion(psiClass); + PromptService.addImports(req, project, serviceName, null, editor, true, true, junitVersion); + PromptService.addFields(project, serviceName, shortServiceName, psiClass, editor); + //spring 单元测试带上之前的测试代码 + map.put("context", editor.getDocument().getText()); + } else { + map.put("context", ""); + } + + //创建新方法,还是覆盖老的方法(并且光标移动到合理的位置) + if (methodName.equals("New")) { + PsiMethod @NotNull [] methods = psiClass.getMethods(); + int offset = 0; + if (0 == methods.length) { + offset = psiClass.getTextRange().getEndOffset() - 3; + } else { + PsiMethod psiMethod = methods[methods.length - 1]; + offset = psiMethod.getTextRange().getEndOffset(); + } + editor.getCaretModel().moveToOffset(offset); + CodeService.writeCode2(project, editor, "\n"); + } else { + PsiMethod psiMethod = CodeService.getMethod(psiClass, methodName); + CodeService.deleteMethod(project, psiMethod); + } + + generateUnitTest(project, methodCode, codeClassName, map, testClassCode, editor); + } + + /** + * 打开单元测试类 + * 设置偏移量,如果方法数组长度为 0 则进行特定计算,否则根据最后一个方法的结束偏移量计算 + */ + public static String openUnitTestClass(Project project, String className) { + PsiClass psiClass = CodeService.openJavaClass(project, className); + String testClassCode = psiClass.getText(); + Editor editor = CodeService.getEditor(project); + PsiMethod @NotNull [] methods = psiClass.getMethods(); + int offset = 0; + if (0 == methods.length) { + offset = psiClass.getTextRange().getEndOffset() - 3; + } else { + PsiMethod psiMethod = methods[methods.length - 1]; + offset = psiMethod.getTextRange().getEndOffset(); + } + editor.getCaretModel().moveToOffset(offset); + CodeService.writeCode2(project, editor, "\n"); + return testClassCode; + } + + //生成单元测试代码 + public static void generateUnitTest(Project project, String methodCode, String codeClassName, Map map, String testClassCode, Editor editor) { + generateUnitTest(project, methodCode, codeClassName, map, testClassCode, editor, null); + } + + public static void generateUnitTest(Project project, String methodCode, String codeClassName, Map map, String testClassCode, Editor editor, CountDownLatch latch) { + //生成测试方法的时候,让他能推理出来类名 + methodCode = "public class " + codeClassName + " {\n" + methodCode + "\n}"; + map.put("code", methodCode); + //单元测试那个类的内容 + map.put("testClassCode", testClassCode); + invokePrompt(project, Const.GENERATE_UNIT_TEST, map, editor, latch); + } + + + private static void invokePrompt(Project project, String promptName, Map param, Editor editor) { + invokePrompt(project, promptName, param, editor, null); + } + + private static void invokePrompt(Project project, String promptName, Map param, Editor editor, CountDownLatch latch) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + PromptType promptType = Prompt.getPromptType(promptInfo); + //直接使用bot + PromptService.dynamicInvoke(GenerateCodeReq.builder() + .project(project) + .promptType(promptType) + .promptName(promptName) + .promptInfo(promptInfo) + .countDownLatch(latch) + .param(param) + .editor(editor) + .build()); + } + + public static void checkPomVersion(GenerateCodeReq req) { + Editor editor = CodeService.getEditor(req.getProject()); + PromptInfo promptInfo = Prompt.getPromptInfo(req.getPromptName()); + Map lables = promptInfo.getLabels(); + Dependency dependency = gson.fromJson(lables.get("version"), Dependency.class); + Pair checkRes = XmlService.checkPomVersion(req.getProject(), dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion()); + HintUtils.show(editor, checkRes.getKey() == 0 ? Result.success(checkRes.getValue()) : Result.fail(-1, checkRes.getValue())); + } + + public static void generateAnnoForBootStrap(String promptName, Project project) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + PsiClass applicationBootStrapClass = PsiClassUtils.findApplicationRunClass(project); + if (applicationBootStrapClass == null) { + HintUtils.show(CodeService.getEditor(project), Result.fail(-1, "没有找到启动类!")); + return; + } + Map labels = promptInfo.getLabels(); + String annos = labels.get("anno"); + List annoList = gson.fromJson(annos, new TypeToken>() { + }.getType()); + Editor editor = EditorUtils.getEditorFromPsiClass(project, applicationBootStrapClass); + CodeService.addImport(project, editor, gson.fromJson(labels.get("import"), new TypeToken>() { + }.getType())); + CodeService.addClassAnno(project, applicationBootStrapClass, annoList); + } + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassFixer.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassFixer.java new file mode 100644 index 000000000..09e4db982 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassFixer.java @@ -0,0 +1,204 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInspection.InspectionManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +/** + * goodjava@qq.com + * minzai + */ +public class PsiClassFixer { + + /** + * 修复类中引用的不存在方法 + * + * @param psiClass 要修复的类 + * @param project 当前项目 + */ + public static void fixUndefinedMethods(PsiClass psiClass, Project project) { + // 在写操作中执行修复 + WriteCommandAction.runWriteCommandAction(project, () -> { + for (PsiMethod method : psiClass.getMethods()) { + PsiCodeBlock body = method.getBody(); + if (body != null) { + body.accept(new JavaRecursiveElementVisitor() { + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + + // 获取方法调用表达式 + PsiReferenceExpression methodExpression = expression.getMethodExpression(); + if (methodExpression != null) { + // 解析方法引用 + PsiElement referencedMethod = methodExpression.resolve(); + + if (referencedMethod == null) { + String methodName = methodExpression.getReferenceName(); + + if (methodName != null) { + Pair isReferencedClassPair = isReferencedClass(methodExpression); + if (isReferencedClassPair.getKey()){ + // 添加空方法到当前类 + addEmptyMethod(psiClass, methodName, expression); + } else { + // 添加空方法到外部类 + addEmptyMethod(isReferencedClassPair.getValue(), methodName, expression); + } + } + } + } + } + }); + } + } + }); + } + + /** + * 查找引用的外部类 + * + * @param methodExpression 方法引用表达式 + * @return 引用的外部类 + */ + private static Pair isReferencedClass(PsiReferenceExpression methodExpression) { + boolean isCurrentClassFlag = false; + PsiClass referencedClass = null; + + // 获取方法调用的限定表达式,例如 "this.method()" 或 "SomeClass.method()" + PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); + + if (qualifierExpression instanceof PsiThisExpression || qualifierExpression == null) { + // 如果限定表达式是 "this" 或者没有限定表达式,那么它是当前类的方法 + isCurrentClassFlag = true; + } else if (qualifierExpression instanceof PsiReferenceExpression) { + // 如果限定表达式是引用表达式,可能是外部类的方法 + PsiElement qualifier = ((PsiReferenceExpression) qualifierExpression).resolve(); + if (qualifier instanceof PsiClass) { + // 如果解析的限定符是一个类,那么它是外部类的方法 + referencedClass = (PsiClass) qualifier; + } + } + return Pair.of(isCurrentClassFlag, referencedClass); + } + + /** + * 添加空方法到指定类中 + * + * @param psiClass 指定类 + * @param methodName 方法名 + * @param expression 方法调用表达式(用于获取参数和返回类型) + */ + private static void addEmptyMethod(PsiClass psiClass, String methodName, PsiMethodCallExpression expression) { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + + // 获取方法参数和返回类型 + PsiExpressionList argumentList = expression.getArgumentList(); + PsiType returnType = getMethodCallReturnType(expression); + + // 构建方法签名 + StringBuilder methodSignature = new StringBuilder("public static "); + if (returnType != null) { + methodSignature.append(returnType.getCanonicalText()).append(" "); + } else { + methodSignature.append("void "); + } + methodSignature.append(methodName).append("("); + + if (argumentList != null) { + PsiExpression[] arguments = argumentList.getExpressions(); + for (int i = 0; i < arguments.length; i++) { + PsiExpression argument = arguments[i]; + methodSignature.append(argument.getType().getCanonicalText()).append(" arg").append(i); + if (i < arguments.length - 1) { + methodSignature.append(", "); + } + } + } + // 创建空方法并添加返回语句 + String returnStatement = getReturnStatement(returnType); + methodSignature.append(") { " + returnStatement + " }"); + + // 创建新的方法并添加到类中 + PsiMethod newMethod = elementFactory.createMethodFromText(methodSignature.toString(), psiClass); + psiClass.add(newMethod); + } + + + public static void a(Project project) { + InspectionManager inspectionManager = InspectionManager.getInstance(project); + DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project); + } + + public static void addFields0(PsiClass psiClass) { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + PsiField ageField = elementFactory.createField("age", PsiTypes.intType()); + PsiField nameField = elementFactory.createField("name", PsiType.getJavaLangString(psiClass.getManager(), psiClass.getResolveScope())); + + WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { + // 添加字段前检查是否已存在同名字段 + if (psiClass.findFieldByName("age", false) == null) { + psiClass.add(ageField); + } + if (psiClass.findFieldByName("name", false) == null) { + psiClass.add(nameField); + } + }); + } + + public static void addFields(PsiClass psiClass, List fieldList) { + WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { + fieldList.forEach(it -> psiClass.add(it)); + }); + + } + private static PsiType getMethodCallReturnType(PsiMethodCallExpression expression) { + PsiElement parent = expression.getParent(); + if (parent instanceof PsiAssignmentExpression) { + PsiAssignmentExpression assignment = (PsiAssignmentExpression) parent; + PsiExpression lExpression = assignment.getLExpression(); + if (lExpression instanceof PsiReferenceExpression) { + PsiElement resolved = ((PsiReferenceExpression) lExpression).resolve(); + if (resolved instanceof PsiVariable) { + return ((PsiVariable) resolved).getType(); + } + } + } else if (parent instanceof PsiVariable) { + return ((PsiVariable) parent).getType(); + } else if (parent instanceof PsiReturnStatement) { + PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class); + if (containingMethod != null) { + return containingMethod.getReturnType(); + } + } + // 其他情况,可能需要更复杂的逻辑来确定返回类型 + return null; + } + + /** + * 获取返回语句 + * + * @param returnType 返回类型 + * @return 返回语句 + */ + private static String getReturnStatement(PsiType returnType) { + if (PsiType.VOID.equals(returnType)) { + return ""; + } else if (PsiType.BOOLEAN.equals(returnType)) { + return "return false;"; + } else if (PsiType.INT.equals(returnType) || PsiType.LONG.equals(returnType) || PsiType.FLOAT.equals(returnType) || PsiType.DOUBLE.equals(returnType)) { + return "return 0;"; + } else if (PsiType.CHAR.equals(returnType)) { + return "return '\0';"; + } else { + return "return null;"; + } + } +} + diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/PsiClassUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassUtils.java similarity index 62% rename from athena-all/src/main/java/run/mone/m78/ip/util/PsiClassUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassUtils.java index 9085f1cec..57b091ee4 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/PsiClassUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiClassUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.google.common.collect.ImmutableList; import com.intellij.openapi.command.WriteCommandAction; @@ -9,21 +9,25 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; -import run.mone.m78.ip.bo.AddMethodConfig; -import run.mone.m78.ip.bo.ParamInfo; -import run.mone.m78.ip.common.JavaClassUtils; -import run.mone.m78.ip.service.CodeService; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.InheritanceUtil; +import com.xiaomi.youpin.tesla.ip.bo.AddMethodConfig; +import com.xiaomi.youpin.tesla.ip.bo.Message; +import com.xiaomi.youpin.tesla.ip.bo.ParamInfo; +import com.xiaomi.youpin.tesla.ip.common.JavaClassUtils; +import com.xiaomi.youpin.tesla.ip.service.CodeService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import run.mone.ultraman.bo.AthenaClassInfo; import run.mone.ultraman.service.AthenaCodeService; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; /** @@ -58,7 +62,6 @@ public static PsiClass findClassByName(Project project, String className) { return psiClass; } - /** * 添加字段 * 如果里边有同名字段则不添加 @@ -147,7 +150,6 @@ public static PsiClass findApplicationRunClass(Project project) { return null; } - public static PsiDirectory getSourceDirectory(Project project, String moduleName, boolean testPath) { return getSourceDirectory(project, moduleName, testPath, "java"); } @@ -165,27 +167,67 @@ public static void createEmptyClass(Project project, String moduleName, String p createEmptyClass(project, moduleName, packageName, className, testPath, false, null, isInterface); } - public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath, boolean openClass, List annoList, boolean isInterface) { - + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiDirectory psiDirectory = getSourceDirectory(project, moduleName, testPath); + if (null == psiDirectory) { + HintUtils.show(CodeService.getEditor(project), Message.cannotFindTestDirectory, true); + return; + } + String[] packageParts = packageName.split("\\."); + for (String packagePart : packageParts) { + PsiDirectory subDirectory = psiDirectory.findSubdirectory(packagePart); + if (subDirectory == null) { + subDirectory = psiDirectory.createSubdirectory(packagePart); + } + psiDirectory = subDirectory; + } + PsiDirectory tmp = psiDirectory; + String classText = isInterface ? buildEmptyInterfaceInfo(className) : buildEmptyClassInfo(project, className, testPath, annoList); + PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project); + PsiFile psiFile = psiFileFactory.createFileFromText(className + ".java", classText); + tmp.add(psiFile.getContainingFile()); + if (openClass) { + JavaClassUtils.openClass(project, className); + } + }); } //创建一个类,并打开 public static void createClass(Project project, String packageStr, String className, String code) { + createClass(project, packageStr, className, code, true); + } + + public static void createClass(Project project, String packageStr, String className, String code, boolean format) { WriteCommandAction.runWriteCommandAction(project, () -> { PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project); PsiFile psiFile = psiFileFactory.createFileFromText(className + ".java", code); PsiDirectory directory = getDirectoryFromPackage(project, packageStr); directory.add(psiFile); - //打开这个类 - JavaClassUtils.openClass(project, className); - //格式化代码 - CodeService.formatCode(project); + if (format) { + //打开这个类 + JavaClassUtils.openClass(project, className); + //格式化代码 + CodeService.formatCode(project); + } + }); + } + + public static void createClass(Project project, String className, String code, boolean format, PsiDirectory directory) { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project); + PsiFile psiFile = psiFileFactory.createFileFromText(className + ".java", code); + directory.add(psiFile); + if (format) { + //打开这个类 + JavaClassUtils.openClass(project, className); + //格式化代码 + CodeService.formatCode(project); + } }); } public static PsiDirectory getDirectoryFromPackage(Project project, String packagePath) { - PsiManager psiManager = PsiManager.getInstance(project); JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); PsiPackage psiPackage = javaPsiFacade.findPackage(packagePath); if (psiPackage != null) { @@ -197,7 +239,6 @@ public static PsiDirectory getDirectoryFromPackage(Project project, String packa return null; } - private static String buildEmptyClassInfo(Project project, String className, boolean testPath, List annoList) { String classText = testPath ? String.format("public class %s{\n\n}", className) @@ -242,22 +283,51 @@ public static PsiDirectory getSourceDirectory(Project project, String moduleName return null; } - public static PsiDirectory getSourceDirectory(Project project, String moduleName) { return getSourceDirectory(project, moduleName, "/src/main/java"); } + public static PsiDirectory getSourceDirectoryWithModule(Project project, String moduleName) { + return getSourceDirectory(project, moduleName, "/src/main/java", false, false); + } + + public static PsiDirectory getTestSourceDirectory(Project project, String moduleName) { + return getSourceDirectory(project, moduleName, "/src/test/java", true, false); + } + + public static PsiDirectory getSourceDirectory(Project project, String moduleName, String containsPath) { + return getSourceDirectory(project, moduleName, containsPath, false, true); + } + + public static PsiDirectory createPackageDirectories(PsiDirectory directory, String packageName) { + String[] names = packageName.split("\\."); + for (String name : names) { + PsiDirectory subdirectory = directory.findSubdirectory(name); + if (subdirectory == null) { + directory = directory.createSubdirectory(name); + } else { + directory = subdirectory; + } + } + return directory; + } + + public static PsiDirectory getSourceDirectory(Project project, String moduleName, String containsPath, boolean includingTests, boolean getParent) { Module[] modules = ModuleManager.getInstance(project).getModules(); for (Module module : modules) { ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); if (!module.getName().equals(moduleName)) { continue; } - for (VirtualFile sourceFolder : moduleRootManager.getSourceRoots(false)) { + for (VirtualFile sourceFolder : moduleRootManager.getSourceRoots(includingTests)) { //包含/test/目录才是测试代码路径 if (sourceFolder.getPath().contains(containsPath)) { - return PsiManager.getInstance(project).findDirectory(sourceFolder).getParent(); + PsiDirectory res = PsiManager.getInstance(project).findDirectory(sourceFolder); + if (getParent) { + return res.getParent(); + } + return res; } } } @@ -281,8 +351,26 @@ public static PsiDirectory getDirectory(Project project, String moduleName, Stri return null; } - public static PsiDirectory getSourceDirectory(Project project, boolean testPath, String packagePath) { + Module[] modules = ModuleManager.getInstance(project).getModules(); + for (Module module : modules) { + ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + for (VirtualFile sourceFolder : moduleRootManager.getSourceRoots(testPath)) { + //包含/test/目录才是测试代码路径 + if (testPath && !sourceFolder.getPath().contains("/src/test/java")) { + continue; + } + + if (!module.getName().contains("demo-server")) { + continue; + } + + if (sourceFolder.getName().equals("java")) { + sourceFolder = sourceFolder.findFileByRelativePath(packagePath.replace('.', '/')); + return PsiManager.getInstance(project).findDirectory(sourceFolder); + } + } + } return null; } @@ -292,17 +380,26 @@ public static Module getModule(Project project, PsiClass psiClass) { return module; } - private static List list = ImmutableList.of("javax.annotation.Resource", "jakarta.annotation.Resource" - , "org.springframework.beans.factory.annotation.Autowired", "org.apache.dubbo.config.annotation.Reference" - , "org.apache.dubbo.config.annotation.DubboReference" + //需要分析的引入类 + private static List list = ImmutableList.of("javax.annotation.Resource", + "jakarta.annotation.Resource", + "org.springframework.beans.factory.annotation.Autowired", + "org.apache.dubbo.config.annotation.Reference", + "org.apache.dubbo.config.annotation.DubboReference" ); - public static List findFieldsWithResourceAnnotation(@NotNull PsiClass psiClass) { - return Arrays.stream(psiClass.getFields()).filter(it -> hasAnno(it, list)).collect(Collectors.toList()); + @Nullable PsiClass superClass = psiClass.getSuperClass(); + List superClassFields = new ArrayList<>(); + //父类里有,也会被拉取出来 + if (null != superClass) { + superClassFields.addAll(Arrays.stream(superClass.getFields()).filter(it -> hasAnno(it, list)).collect(Collectors.toList())); + } + List fields = Arrays.stream(psiClass.getFields()).filter(it -> hasAnno(it, list)).collect(Collectors.toList()); + fields.addAll(superClassFields); + return fields; } - private static boolean hasAnno(PsiField field, List annoList) { if (null == field || null == annoList) { return false; @@ -340,7 +437,6 @@ public static String getClassText(Project project, String text) { return ""; } - public static String getInterfaceText(Project project, PsiClass originalClass) { //直接先分析下代码,如果加了@Data注解,则直接自己分析了 try { @@ -389,5 +485,88 @@ public static String getInterfaceText(Project project, PsiClass originalClass) { } + /** + * 查找指定类继承的非私有非静态方法集合. + * 遍历给定类的所有父类,忽略Object类,筛选出所有非私有非静态方法. + * 如果父类是接口,则只考虑默认方法. + * + * @param psiClass 需要查找方法的类 + * @return 继承的非私有非静态方法集合 + */ + public static Set findInheritedNonPrivateNonStaticMethods(PsiClass psiClass) { + Set inheritedMethods = new HashSet<>(); + LinkedHashSet superClasses = InheritanceUtil.getSuperClasses(psiClass); + for (PsiClass superClass : superClasses) { + if (superClass.getName().equals("Object")) { + continue; + } + // 获取当前父类的所有方法 + PsiMethod[] methods = superClass.getMethods(); + for (PsiMethod method : methods) { + if (superClass.isInterface() && !method.hasModifierProperty(PsiModifier.DEFAULT)) { + continue; + } + // 检查方法是否是继承来的 + if (!method.hasModifierProperty(PsiModifier.PRIVATE) && !method.hasModifierProperty(PsiModifier.STATIC)) { + // 如果方法不是 private 或 static,那么它可能是被继承的 + inheritedMethods.add(method); + } + } + } + return inheritedMethods; + } + + public static String generateMethodSignature(PsiMethod psiMethod) { + // 获取方法的访问修饰符(public, private, 等等) + if (psiMethod.isConstructor() || psiMethod.getReturnType() == null) { + return ""; + } + String modifier = psiMethod.getModifierList().getText(); + String returnType = psiMethod.getReturnType().getPresentableText(); + String methodName = psiMethod.getName(); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + StringBuilder paramsBuilder = new StringBuilder(); + // 获取方法的文档注释(如果存在) + PsiDocComment docComment = psiMethod.getDocComment(); + StringBuilder commentBuilder = new StringBuilder(); + // 如果存在文档注释,则获取注释的文本并添加到commentBuilder + if (docComment != null) { + commentBuilder.append(docComment.getText()); + } + + String comment = getSingleLineCommentAboveMethod(psiMethod); + if (StringUtils.isNotEmpty(comment)) { + commentBuilder.append(comment); + } + + for (PsiParameter param : parameters) { + if (paramsBuilder.length() > 0) { + paramsBuilder.append(", "); + } + paramsBuilder.append(param.getType().getPresentableText()).append(" ").append(param.getName()); + } + String methodDefinition = modifier + " " + returnType + " " + methodName + "(" + paramsBuilder.toString() + ")"; + return commentBuilder + "\n" + methodDefinition; + } + + /** + * 获取给定方法上方的单行注释文本. + * 遍历方法节点的前一个兄弟节点,直到找到单行注释或者不再有前一个兄弟节点为止. + * 如果找到单行注释,则返回该注释的文本内容;否则返回null. + */ + public static String getSingleLineCommentAboveMethod(PsiMethod psiMethod) { + for (PsiElement child : psiMethod.getChildren()) { + if (child instanceof PsiComment) { + PsiComment comment = (PsiComment) child; + IElementType type = comment.getTokenType(); + if (JavaTokenType.END_OF_LINE_COMMENT.equals(type)) { + return comment.getText(); + } + } else { + break; + } + } + return null; // No single line comment found + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/PsiFieldUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiFieldUtils.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/util/PsiFieldUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiFieldUtils.java index 8420fd73a..923b266f1 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/PsiFieldUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/PsiFieldUtils.java @@ -1,13 +1,13 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.openapi.project.Project; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiField; -import run.mone.m78.ip.bo.AnnoInfo; -import run.mone.m78.ip.bo.AnnoMember; -import run.mone.m78.ip.bo.FieldInfo; +import com.xiaomi.youpin.tesla.ip.bo.AnnoInfo; +import com.xiaomi.youpin.tesla.ip.bo.AnnoMember; +import com.xiaomi.youpin.tesla.ip.bo.FieldInfo; import java.util.Arrays; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/ResourceUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ResourceUtils.java similarity index 54% rename from athena-all/src/main/java/run/mone/m78/ip/util/ResourceUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ResourceUtils.java index 80afdaf5f..426457c8e 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/ResourceUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ResourceUtils.java @@ -1,14 +1,17 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; +import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; -import run.mone.m78.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Const; import lombok.SneakyThrows; +import org.HdrHistogram.AtomicHistogram; import java.io.File; import java.io.IOException; @@ -16,6 +19,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -29,6 +33,8 @@ public class ResourceUtils { public static final String USER_HOME_ATHENA_FILE_NAME = ".athena.json"; + private static final String ULTRAMAN_URL_PREFIX = "http://localhost/ultraman"; + public static String readResources(Project project, Module module) { try { StringBuilder stringBuilder = new StringBuilder(); @@ -74,15 +80,32 @@ public static Map getAthenaConfig(Project project, boolean refre str = System.getProperty("user.home") + File.separator + USER_HOME_ATHENA_FILE_NAME; config.putAll(defaultConfig); getConfig(str); + + //todo 未来版本删除 + String dashUrl = config.get(Const.CONF_DASH_URL); + if (dashUrl.startsWith(ULTRAMAN_URL_PREFIX)) { + config.put(Const.CONF_DASH_URL, defaultConfig.get(Const.CONF_DASH_URL)); + String content = new GsonBuilder().setPrettyPrinting().create().toJson(config); + FileUtils.writeConfig(content, ResourceUtils.USER_HOME_ATHENA_FILE_NAME); + } + + // 把OPEN_GUIDE强制置为true todo 未来版本删除? + String openGuide = config.get(Const.OPEN_GUIDE); + if ("false".equals(openGuide)) { + config.put(Const.OPEN_GUIDE, "true"); + String content = new GsonBuilder().setPrettyPrinting().create().toJson(config); + FileUtils.writeConfig(content, ResourceUtils.USER_HOME_ATHENA_FILE_NAME); + } + return config; } - private static Map defaultConfig = new HashMap<>() { + private static Map defaultConfig = new LinkedHashMap<>() { { put(Const.VISION, "false"); put(Const.DEBUG, "false"); - put(Const.OPEN_GUIDE, "false"); + put(Const.OPEN_GUIDE, "true"); put(Const.DISABLE_ACTION_GROUP, "false"); put(Const.BIZ_WRITE, "false"); put(Const.OPEN_AI_KEY, ""); @@ -93,7 +116,32 @@ public static Map getAthenaConfig(Project project, boolean refre put(Const.OPEN_AI_MODEL, "gpt-4-1106-preview");//gpt-3.5-turbo put(Const.DISABLE_SEARCH, "false"); put(Const.AI_PROXY_CHAT, "true"); - put(Const.ENABLE_ATHENA_STATUS_BAR, "false"); + put(Const.ENABLE_ATHENA_STATUS_BAR, "true"); + //调用bot + put(Const.USE_BOT, "true"); + put(Const.BOT_URL, "https://localhost/open-apis/ai-plugin-new/feature/router/probot/query"); + // inline 补全 + put(Const.INLAY, "true"); + put(Const.INLAY_DELAY, "200"); + put(Const.INLAY_BOT_ID, "160004"); + put(Const.INLAY_SCOPE, "method"); + //关闭整个代码补全功能(只留下chat) + put(Const.DISABLE_CODE_COMPLETION, Const.FALSE); + // 内置配置 + put(Const.CONF_NICK_NAME, "nick_mone"); + put(Const.CONF_DASH_URL, "http://127.0.0.1/ultraman/#/code"); + put(Const.CONF_AI_PROXY_URL, "http://127.0.0.1"); + //允许flow回调回来的端口号 + put(Const.CONF_PORT, "6666"); + put(Const.CONF_M78_URL, "https://localhost/open-apis/ai-plugin-new"); + put(Const.CONF_M78_SPEECH2TEXT, "/speechToText2"); + put(Const.CONF_M78_TEXT2SPEECH, "/textToSpeech"); + put(Const.CONF_M78_UPLOAD_CODE_INFO, "/uploadCodeInfo"); + // 右侧聊天是否调用BOT配置 + put(Const.CONF_CHAT_USE_BOT, "true"); + put(Const.CONF_M78_CODE_GEN_WITH_ENTER, "false"); + +// put(Const.CONF_COMPLETION_TYPE, "0"); } }; @@ -120,9 +168,26 @@ public static Map getAthenaConfig() { return getAthenaConfig(null, false); } + public static boolean isOpen(String key) { + return Boolean.valueOf(ResourceUtils.getAthenaConfig().getOrDefault(key, "false")); + } + + public static boolean has(String key) { + return ResourceUtils.getAthenaConfig().containsKey(key); + } + + public static String get(String key, String defaultValue) { + return ResourceUtils.getAthenaConfig().getOrDefault(key, defaultValue); + } + public static void putConfigIfAbsent(String key, String value) { config.putIfAbsent(key, value); } + public static boolean checkDisableCodeCompletionStatus() { + return isOpen(Const.DISABLE_CODE_COMPLETION); + } + + } diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/RunUntil.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUntil.java similarity index 95% rename from athena-all/src/main/java/run/mone/m78/ip/util/RunUntil.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUntil.java index 2e7fbf574..18cbf57fa 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/RunUntil.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUntil.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.execution.RunManager; import com.intellij.execution.RunnerAndConfigurationSettings; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUtils.java new file mode 100644 index 000000000..b0b23d74c --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/RunUtils.java @@ -0,0 +1,52 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.Executor; +import com.intellij.execution.RunManager; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.application.ApplicationConfiguration; +import com.intellij.execution.application.ApplicationConfigurationType; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; + +/** + * @author goodjava@qq.com + * @date 2024/4/27 22:17 + */ +public class RunUtils { + + public static void runMainMethod(Project project, PsiClass psiClass) { + // 检查是否存在 main 方法 + if (psiClass.findMethodsByName("main", false).length > 0) { + // 创建应用程序运行配置 + ApplicationConfiguration configuration = new ApplicationConfiguration("Run Main", project); + // 设置要运行的主类 + configuration.setMainClassName(psiClass.getQualifiedName()); + + // 创建执行环境 + Executor executor = DefaultRunExecutor.getRunExecutorInstance(); + RunnerAndConfigurationSettings runnerAndConfigurationSettings = RunManager.getInstance(project).createConfiguration(configuration, ApplicationConfigurationType.getInstance().getConfigurationFactories()[0]); + ExecutionEnvironment environment = new ExecutionEnvironment(executor, ProgramRunner.getRunner(executor.getId(), configuration), runnerAndConfigurationSettings, project); + + +// ExecutionUtil.runConfiguration(runnerAndConfigurationSettings, new DefaultDebugExecutor()); + + try { + ProgramRunner runner = ProgramRunner.getRunner(executor.getId(), configuration); + if (runner != null) { + runner.execute(environment); + } + } catch (ExecutionException e) { + e.printStackTrace(); + } + } else { + System.out.println("No main method found in class " + psiClass.getName()); + } + } + + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/ScreenSizeUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ScreenSizeUtils.java similarity index 96% rename from athena-all/src/main/java/run/mone/m78/ip/util/ScreenSizeUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ScreenSizeUtils.java index 0023e8cdc..ca7f7623c 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/ScreenSizeUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/ScreenSizeUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import java.awt.*; diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/SpringUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/SpringUtils.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/util/SpringUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/SpringUtils.java index 063c30532..38e692a53 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/SpringUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/SpringUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiClass; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TerminalUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TerminalUtils.java new file mode 100644 index 000000000..b9af42715 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TerminalUtils.java @@ -0,0 +1,167 @@ +/* + * Copyright 2020 Xiaomi + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.xiaomi.youpin.tesla.ip.util; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.OSProcessHandler; +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; +import com.intellij.terminal.JBTerminalPanel; +import com.intellij.terminal.JBTerminalWidget; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentManager; +import com.jediterm.terminal.TerminalOutputStream; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.plugins.terminal.TerminalView; + +import javax.swing.*; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * @Author goodjava@qq.com + * @Date 2021/11/7 11:21 + */ +@Slf4j +public class TerminalUtils { + + public static final String TERMINAL_ID = "Terminal"; + + @SneakyThrows + public static void show(Project project) { + ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); + ToolWindow terminal = toolWindowManager.getToolWindow(TERMINAL_ID); + if (terminal != null) { + terminal.show(null); + if (!terminal.isActive()) { + TimeUnit.SECONDS.sleep(1); + } + } + } + + + public static void send(Project project, String message) { + if (null == project) { + project = ProjectManager.getInstance().getOpenProjects()[0]; + } + ToolWindow terminal = ToolWindowManager.getInstance(project).getToolWindow("Terminal"); + JComponent root = terminal.getComponent(); + terminal.show(() -> { + JBTerminalPanel terminalPanel = (JBTerminalPanel) getPannel(root); + //执行history命令 + TerminalOutputStream is = terminalPanel.getTerminalOutputStream(); + if (null != is) { + is.sendString(message + "\n"); + } + }); + } + + public static ToolWindow getTerminalToolWindow(Project project) { + ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project); + ToolWindow toolWindow = toolWindowManager.getToolWindow("Terminal"); + if (toolWindow == null) { + toolWindow = toolWindowManager.registerToolWindow("Terminal", true, ToolWindowAnchor.BOTTOM); + } + toolWindow.show(null); + return toolWindow; + } + + + public static void runCommandOnTerminal(Project project, String command) { + GeneralCommandLine cmdLine = new GeneralCommandLine(); + cmdLine.setExePath("/bin/bash"); // 设置 shell 解释器 + cmdLine.addParameter("-c"); // 添加参数 + cmdLine.addParameter(command); // 添加要执行的命令 + + OSProcessHandler processHandler = null; // 创建进程处理器 + try { + processHandler = new OSProcessHandler(cmdLine); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + + + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + // 处理命令输出 + String output = event.getText(); + System.out.println(output); + } + }); + + processHandler.startNotify(); // 启动进程处理器 + + } + + + private static Object getPannel(Object root) { + if (root instanceof JBTerminalPanel) { + return root; + } + if (root instanceof JPanel) { + return getPannel(((JPanel) root).getComponent(0)); + } + if (root instanceof JLayeredPane) { + return getPannel(((JLayeredPane) root).getComponent(0)); + } + return null; + } + + + public static JBTerminalWidget getExistingTerminal(Project project) { + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Terminal"); + if (toolWindow != null) { + if (!toolWindow.isVisible()) { + // 获取终端工具窗口的内容管理器 + ContentManager contentManager = toolWindow.getContentManager(); + for (Content content : contentManager.getSelectedContents()) { + // 检查内容是否是终端视图 + if (content.getComponent() instanceof JBTerminalWidget) { + // 转换并返回JBTerminalWidget + return (JBTerminalWidget) content.getComponent(); + } + } + } + } + return null; + } + + public static void executeTerminalCommand(Project project, String command) { + ApplicationManager.getApplication().invokeLater(()->{ + TerminalView terminalView = TerminalView.getInstance(project); + try { + log.info("command:{}", command); + terminalView.createLocalShellWidget(project.getBasePath(), "Athena").executeCommand(command); + } catch (IOException err) { + err.printStackTrace(); + } + }); + } + + +} diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TestUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TestUtils.java new file mode 100644 index 000000000..681ed4cd1 --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/TestUtils.java @@ -0,0 +1,87 @@ +package com.xiaomi.youpin.tesla.ip.util; + +import com.google.common.collect.Lists; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.Executor; +import com.intellij.execution.RunManager; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.application.ApplicationConfiguration; +import com.intellij.execution.application.ApplicationConfigurationType; +import com.intellij.execution.configurations.ConfigurationFactory; +import com.intellij.execution.executors.DefaultDebugExecutor; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.junit.JUnitConfiguration; +import com.intellij.execution.junit.JUnitConfigurationType; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ExecutionUtil; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; + +import java.util.List; + +/** + * @author goodjava@qq.com + * @date 2023/8/11 09:46 + */ +public class TestUtils { + + + public static List junitImportList = Lists.newArrayList("import org.junit.Test", "import org.junit.Assert"); + + public static List jupiterImportList = Lists.newArrayList("import org.junit.jupiter.api.Test", "import static org.junit.jupiter.api.Assertions.assertEquals", "import static org.junit.jupiter.api.Assertions.assertNotNull"); + + + public static boolean isJupiter() { + if (isClassPresent("org.junit.Test")) { + return false; + } else if (isClassPresent("org.junit.jupiter.api.Test")) { + return true; + } else { + return false; + } + } + + public static List getImportList(String version) { + if (version.equals("unknow")) { + return Lists.newArrayList(); + } + if (version.equals("junit")) { + return junitImportList; + } + if (version.equals("jupiter")) { + return junitImportList; + } + return Lists.newArrayList(); + } + + + private static boolean isClassPresent(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + + public static void runAllTestsInClass(Project project, PsiClass psiClass) { + // 创建 JUnit 测试配置 + JUnitConfiguration configuration = new JUnitConfiguration("Run all tests in " + psiClass.getName(), project); + // 设置要运行的测试类 + configuration.setMainClass(psiClass); + // 创建 RunnerAndConfigurationSettings 对象 + RunnerAndConfigurationSettings runnerAndConfigurationSettings = RunManager.getInstance(project).createConfiguration(configuration, getJUnitConfigurationFactory()); + // 运行测试 + ExecutionUtil.runConfiguration(runnerAndConfigurationSettings, new DefaultDebugExecutor()); + } + + + + private static ConfigurationFactory getJUnitConfigurationFactory() { + return JUnitConfigurationType.getInstance().getConfigurationFactories()[0]; + } + + +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/UltramanConsole.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/UltramanConsole.java similarity index 51% rename from athena-all/src/main/java/run/mone/m78/ip/util/UltramanConsole.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/UltramanConsole.java index 9933160d0..b73b80c0b 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/UltramanConsole.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/UltramanConsole.java @@ -14,14 +14,20 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; -import run.mone.m78.ip.common.Safe; +import com.intellij.ui.content.Content; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import org.jetbrains.annotations.Nullable; import run.mone.ultraman.common.SafeRun; +import javax.swing.*; + /** * @Author goodjava@qq.com * @Date 2021/11/9 17:13 @@ -34,7 +40,7 @@ public static void append(String message) { } public static void append(String projectName, String messsage) { - SafeRun.run(()-> append(ProjectUtils.projectFromManager(projectName), messsage)); + SafeRun.run(() -> append(ProjectUtils.projectFromManager(projectName), messsage)); } @@ -43,12 +49,32 @@ public static void append(Project project, String message) { } public static void append(Project project, String message, boolean enableAutoWrap) { + ApplicationManager.getApplication().invokeLater(() -> { + Safe.run(() -> { + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(Const.MIONE_CONSOLE_NAME); + + @Nullable Content c = toolWindow.getContentManager().getContent(0); + if (null == c) { + return; + } + JScrollPane jpanel = (JScrollPane) toolWindow.getContentManager() + .getContent(0).getComponent().getComponent(0); + JViewport viewPort = jpanel.getViewport(); + JTextArea textArea = (JTextArea) viewPort.getComponent(0); + if (textArea != null) { + textArea.append(message); + if (enableAutoWrap) { + textArea.append("\n"); + } + } + }); + }); } public static void show() { Safe.run(() -> { - ToolWindow toolWindow = ToolWindowManager.getInstance(ProjectUtils.project()).getToolWindow("AthenaConsole"); + ToolWindow toolWindow = ToolWindowManager.getInstance(ProjectUtils.project()).getToolWindow(Const.MIONE_CONSOLE_NAME); toolWindow.show(); }); } diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/WindowUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/WindowUtils.java similarity index 91% rename from athena-all/src/main/java/run/mone/m78/ip/util/WindowUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/WindowUtils.java index 71721bd92..73d92ee9d 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/WindowUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/WindowUtils.java @@ -1,4 +1,4 @@ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/XmlUtils.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/XmlUtils.java similarity index 50% rename from athena-all/src/main/java/run/mone/m78/ip/util/XmlUtils.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/XmlUtils.java index 639998347..48c3600d2 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/util/XmlUtils.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/util/XmlUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package run.mone.m78.ip.util; +package com.xiaomi.youpin.tesla.ip.util; import com.google.common.collect.Maps; import com.intellij.openapi.application.ApplicationManager; @@ -25,12 +25,22 @@ import lombok.SneakyThrows; import org.jetbrains.annotations.Nullable; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; import run.mone.ultraman.AthenaContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -40,6 +50,10 @@ public class XmlUtils { + public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { + System.out.println(getKV("/tmp/databank/databank-service/pom.xml", "manifestEntries")); + } + public static Map getKV(String filePath, String tagName) { Map res = new HashMap<>(5); @@ -85,13 +99,56 @@ public static String getGeneratorConfigPath(String projectName, String moduleNam @SneakyThrows public static Map getMysqlConfigFromMybatisConfig(String path) { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(new File(path)); + NodeList nodeList = document.getElementsByTagName("jdbcConnection"); + if (nodeList.getLength() == 1) { + Element element = (Element) nodeList.item(0); + String dbUrl = element.getAttribute("connectionURL"); + String dbPassword = element.getAttribute("password"); + String dbName = element.getAttribute("userId"); + Map res = new HashMap<>(); + res.put("dbUrl", dbUrl); + res.put("dbPassword", dbPassword); + res.put("dbName", dbName); + return res; + } return Maps.newHashMap(); } public static void updateGeneratorConfig(String path, String newName) { + try { + // 初始化 DocumentBuilderFactory + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + // 解析现有的 XML 文件 + Document document = builder.parse(new File(path)); + // 查找所有名为 "tableName" 的元素 + NodeList nodeList = document.getElementsByTagName("table"); + if (nodeList.getLength() == 1) { + for (int i = 0; i < nodeList.getLength(); i++) { + Element element = (Element) nodeList.item(i); + element.setAttribute("domainObjectName", newName); + element.setAttribute("tableName", newName); + } + // 将修改后的 DOM 写回文件 + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + + transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"); + transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"); + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(new File(path)); + transformer.transform(source, result); + System.out.println("XML file updated successfully"); + } + } catch (Exception e) { + e.printStackTrace(); + } } diff --git a/athena-all/src/main/java/run/mone/m78/ip/window/UltramanConsoleWindowFactory.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanConsoleWindowFactory.java similarity index 93% rename from athena-all/src/main/java/run/mone/m78/ip/window/UltramanConsoleWindowFactory.java rename to athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanConsoleWindowFactory.java index 71d6acb7b..800764ee2 100644 --- a/athena-all/src/main/java/run/mone/m78/ip/window/UltramanConsoleWindowFactory.java +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanConsoleWindowFactory.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package run.mone.m78.ip.window; +package com.xiaomi.youpin.tesla.ip.window; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; -import run.mone.m78.ip.ui.UltramanConsoleUi; +import com.xiaomi.youpin.tesla.ip.ui.UltramanConsoleUi; import org.jetbrains.annotations.NotNull; import javax.swing.*; diff --git a/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanWindowFactory.java b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanWindowFactory.java new file mode 100644 index 000000000..b9b619e1d --- /dev/null +++ b/athena-all/src/main/java/com/xiaomi/youpin/tesla/ip/window/UltramanWindowFactory.java @@ -0,0 +1,85 @@ +/* + * Copyright 2020 Xiaomi + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.xiaomi.youpin.tesla.ip.window; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowFactory; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; +import com.intellij.ui.jcef.JBCefBrowser; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.listener.UltrmanTreeKeyAdapter; +import com.xiaomi.youpin.tesla.ip.ui.UltramanTreeUi; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * @Author goodjava@qq.com + * @Date 2021/11/8 20:55 + */ +public class UltramanWindowFactory implements ToolWindowFactory, DumbAware { + + private static final String nginxChatUrl = "http://127.0.0.1/ultraman/#/code"; + + @Override + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { + ContentFactory contentFactory = ContentFactory.getInstance(); + JPanel pannel = new UltramanTreeUi(project).jpanel(); + Content content = contentFactory.createContent(pannel, "", false); + toolWindow.getContentManager().addContent(content); + if (toolWindow instanceof ToolWindowEx toolWindowEx) { + toolWindowEx.setAdditionalGearActions(new AthenaWindowCustomActionGroup()); + } + } + + private static class AthenaWindowCustomActionGroup extends ActionGroup { + @Override + public AnAction @NotNull [] getChildren(@Nullable AnActionEvent e) { + List actions = new ArrayList<>(); + actions.add(new AthenaWindowCustomRefreshAction()); + return actions.toArray(new AnAction[0]); + } + } + + private static class AthenaWindowCustomRefreshAction extends AnAction { + + public AthenaWindowCustomRefreshAction() { + super("Force Refresh"); + } + + @Override + public void actionPerformed(AnActionEvent e) { + // 自定义选项的操作 + NotificationCenter.notice(null, "custom refresh action performed!", true); + Project project = e.getProject(); + if (project != null) { + JBCefBrowser jbCefBrowser = UltrmanTreeKeyAdapter.browserMap.get(project.getName()); + UltrmanTreeKeyAdapter.forceRefresh(jbCefBrowser, nginxChatUrl); + } + } + } +} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/ActionChain.java b/athena-all/src/main/java/run/mone/m78/ip/action/ActionChain.java deleted file mode 100644 index 045dfff3b..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/ActionChain.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Context; -import run.mone.m78.ip.service.*; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/7 21:00 - */ -public class ActionChain { - - - private AbstractService testService; - - public void init() { - testService = new TestService(); - - ChatGptService chatGptService = new ChatGptService(); - testService.setNext(chatGptService); - - CodeService codeService = new CodeService(); - chatGptService.setNext(codeService); - - MusicService musicService = MusicService.ins(); - codeService.setNext(musicService); - - ImageService imageService = new ImageService(); - musicService.setNext(imageService); - - UserService userService = new UserService(); - imageService.setNext(userService); - - } - - - public void execute(Context context, AnActionEvent e) { - testService.execute(context, e); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/ActionEnum.java b/athena-all/src/main/java/run/mone/m78/ip/action/ActionEnum.java deleted file mode 100644 index 0d41861da..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/ActionEnum.java +++ /dev/null @@ -1,16 +0,0 @@ -package run.mone.m78.ip.action; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/2 11:25 - */ -public enum ActionEnum { - - zero,//image - diga,//music - diga_stop, - background, - code_upload, - code_download, - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/AthenaAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/AthenaAction.java deleted file mode 100644 index c49b35b7c..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/AthenaAction.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.wm.impl.IdeBackgroundUtil; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.Context; -import run.mone.m78.ip.common.NotificationCenter; -import run.mone.m78.ip.util.EditorUtils; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - */ -public class AthenaAction extends AnAction { - - private static final Logger log = Logger.getInstance(AthenaAction.class); - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - String content = getText(e); - log.info("Ultraman req:" + content); - ActionChain chain = new ActionChain(); - chain.init(); - Context context = new Context(); - context.setContent(content); - chain.execute(context, e); - if (content.equals(ActionEnum.background.name())) { - NotificationCenter.notice("background"); - log.info("background"); - String image = new ApiCall().callOne(ApiCall.IMAGE_API); - PropertiesComponent prop = PropertiesComponent.getInstance(); - prop.setValue(IdeBackgroundUtil.FRAME_PROP, null); - prop.setValue(IdeBackgroundUtil.EDITOR_PROP, image); - IdeBackgroundUtil.repaintAllWindows(); - return; - } - } - - private String getText(AnActionEvent anActionEvent) { - Editor editor = anActionEvent.getData(PlatformDataKeys.EDITOR); - return EditorUtils.getSelectContent(editor); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/ChatAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/ChatAction.java deleted file mode 100644 index 779ab8181..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/ChatAction.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.ChatComponent; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - */ -public class ChatAction extends AnAction { - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Application application = ApplicationManager.getApplication(); - ChatComponent component= application.getComponent(ChatComponent.class); - component.show(anActionEvent.getProject(),anActionEvent); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/CommonAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/CommonAction.java deleted file mode 100644 index c930fdbab..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/CommonAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - */ -public class CommonAction extends AnAction { - - - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Project project = anActionEvent.getData(PlatformDataKeys.PROJECT); - String projectName = project.getName(); - String basePath = project.getBasePath(); -// Messages.showMessageDialog(project, projectName + ":" + basePath, "", Messages.getInformationIcon()); - String title = "title"; - String content = "content"; - - - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/CreateFilterAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/CreateFilterAction.java deleted file mode 100644 index b25d89ec5..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/CreateFilterAction.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.FilterComponent; -import org.jetbrains.annotations.NotNull; - -public class CreateFilterAction extends AnAction { - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Application application = ApplicationManager.getApplication(); - FilterComponent myComponent = application.getComponent(FilterComponent.class); - myComponent.show(anActionEvent.getProject()); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/CreateProjectAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/CreateProjectAction.java deleted file mode 100644 index 3dbf2518f..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/CreateProjectAction.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.CreateProjectComponent; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - */ -public class CreateProjectAction extends AnAction { - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Application application = ApplicationManager.getApplication(); - CreateProjectComponent myComponent = application.getComponent(CreateProjectComponent.class); - myComponent.show(anActionEvent.getProject()); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/CreateSprintBootProjectAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/CreateSprintBootProjectAction.java deleted file mode 100644 index bdaae8bac..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/CreateSprintBootProjectAction.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.component.CreateSpringBootProjectComponent; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - */ -public class CreateSprintBootProjectAction extends AnAction { - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Application application = ApplicationManager.getApplication(); - CreateSpringBootProjectComponent myComponent = application.getComponent(CreateSpringBootProjectComponent.class); - myComponent.show(anActionEvent.getProject()); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/DynamicActionGroup.java b/athena-all/src/main/java/run/mone/m78/ip/action/DynamicActionGroup.java deleted file mode 100644 index a3fdb2ca7..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/DynamicActionGroup.java +++ /dev/null @@ -1,27 +0,0 @@ -package run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.bo.PromptInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author goodjava@qq.com - * @date 2023/5/27 09:23 - */ -public class DynamicActionGroup extends ActionGroup { - - @Override - public AnAction @NotNull [] getChildren(@Nullable AnActionEvent event) { - List actions = new ArrayList<>(); - List list = Prompt.promptList("plugin"); - list.stream().forEach(it -> actions.add(new DynamicAction(it.getDesc(), Prompt.getPromptType(it), it))); - return actions.toArray(new AnAction[0]); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/MenuAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/MenuAction.java deleted file mode 100644 index f078b8f15..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/MenuAction.java +++ /dev/null @@ -1,32 +0,0 @@ -package run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.bo.PromptInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author caobaoyu - * @description: - * @date 2023-06-14 14:50 - */ -public class MenuAction extends ActionGroup { - - private List promptInfoList; - - public MenuAction(String text, List promptInfos) { - super(text, true); - this.promptInfoList = promptInfos; - } - - @Override - public AnAction @NotNull [] getChildren(@Nullable AnActionEvent e) { - return new AnAction[]{}; - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/MenuActionGroup.java b/athena-all/src/main/java/run/mone/m78/ip/action/MenuActionGroup.java deleted file mode 100644 index 0f1fa9db9..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/MenuActionGroup.java +++ /dev/null @@ -1,37 +0,0 @@ -package run.mone.m78.ip.action; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.LabelUtils; -import org.jetbrains.annotations.NotNull; - -import java.util.*; - -/** - * @author caobaoyu - * @author goodjava@qq.com - * @description: - * @date 2023-06-14 14:15 - */ -public class MenuActionGroup extends ActionGroup { - - public MenuActionGroup() { - super("Prompt", true); - } - - @Override - public AnAction @NotNull [] getChildren(AnActionEvent e) { - if (LabelUtils.getLabelValue(e.getProject(), Const.DISABLE_ACTION_GROUP, "false").equals("true")) { - return new AnAction[]{}; - } - List list = Prompt.getPromptInfoByTag(""); - list.addAll(Prompt.getCollected()); - return list.stream().map(it -> new DynamicAction(it.getDesc(), Prompt.getPromptType(it), it)).toArray(AnAction[]::new); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/action/TestAction.java b/athena-all/src/main/java/run/mone/m78/ip/action/TestAction.java deleted file mode 100644 index 5048bfa2d..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/action/TestAction.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.action; - -import com.google.common.collect.Maps; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import run.mone.m78.ip.service.ScriptService; - -/** - * @author goodjava@qq.com - */ -public class TestAction extends AnAction { - - @Override - public void actionPerformed(AnActionEvent e) { - //获取当前在操作的工程上下文 - Project project = e.getData(PlatformDataKeys.PROJECT); - - //获取当前操作的类文件 - PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE); - //获取当前类文件的路径 - String classPath = ""; - if (null != psiFile) { - classPath = psiFile.getVirtualFile().getPath(); - } - String title = "Hello World!"; - //显示对话框 - //Messages.showMessageDialog(project, classPath, title, Messages.getInformationIcon()); - - ScriptService.ins().invoke("def sum() {return 1+2}","sum", Maps.newHashMap(), Maps.newHashMap()); - - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/client/GrpcClient.java b/athena-all/src/main/java/run/mone/m78/ip/client/GrpcClient.java deleted file mode 100644 index 7b40a78d6..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/client/GrpcClient.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.client; - -import com.google.gson.Gson; -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.ui.Messages; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusConnection; -import run.mone.m78.ip.util.HintUtils; -import run.mone.m78.ip.util.ProjectUtils; -import run.mone.mone.ultraman.grpc.UltramanRequest; -import run.mone.mone.ultraman.grpc.UltramanResponse; -import run.mone.mone.ultraman.grpc.UltramanServiceGrpc; -import run.mone.m78.ip.action.ActionEnum; -import run.mone.m78.ip.bo.TeslaPluginConfig; -import run.mone.m78.ip.common.NotificationCenter; -import run.mone.m78.ip.common.PluginVersion; -import run.mone.m78.ip.common.UltramanNotifier; -import run.mone.m78.ip.service.DocumentService; -import run.mone.m78.ip.service.ImageService; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.stub.StreamObserver; -import org.apache.commons.lang.mutable.MutableObject; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/5 10:42 - */ -public class GrpcClient { - - private ManagedChannel channel; - - private TeslaPluginConfig config; - - private String ip; - - private boolean close = true; - - public void init() { - if (close) { - return; - } - - String v = PropertiesComponent.getInstance().getValue("tesla_plugin_token"); - if (null != v) { - try { - config = new Gson().fromJson(v, TeslaPluginConfig.class); - if (!StringUtils.equals(config.getChatServer(), ip)) { - try { - channel.shutdownNow(); - } catch (Throwable ex) { - } - } - - ip = config.getChatServer(); - System.out.println("Ultraman grpc channel build"); - channel = ManagedChannelBuilder.forAddress(ip, 5555).usePlaintext().build(); - - new Thread(() -> { - int i = 0; - MessageBusConnection connection = null; - for (; ; ) { - System.out.println("connect grpc num:" + (i++)); - CountDownLatch latch = new CountDownLatch(1); - try { - UltramanResponse res = call(UltramanRequest.newBuilder().setCmd("version").build()); - if (null != res && (Integer.valueOf(res.getData()) > Integer.valueOf(new PluginVersion().toString()))) { - //需要升级 - ApplicationManager.getApplication().invokeLater(() -> { - NotificationCenter.notice("Ultraman Plugin Update"); - }); - } - StreamObserver streamObserver = this.listener(latch); - MessageBus messageBus = ApplicationManager.getApplication().getMessageBus(); - connection = messageBus.connect(); - connection.subscribe(UltramanNotifier.ULTRAMAN_ACTION_TOPIC, event -> { - System.out.println(event.getCmd()); - switch (event.getCmd()) { - case "save_config": { - break; - } - case "req": { - streamObserver.onNext((UltramanRequest) event.getData()); - break; - } - } - }); - } catch (Throwable ex) { - ex.printStackTrace(); - latch.countDown(); - } - try { - latch.await(); - TimeUnit.SECONDS.sleep(3); - } catch (Throwable ex) { - - } finally { - if (null != connection) { - connection.disconnect(); - } - } - } - }).start(); - } catch (Throwable ex) { - System.out.println("Ultraman error:" + ex.getMessage()); - } - } else { - ApplicationManager.getApplication().invokeLater(() -> { - Messages.showMessageDialog("请初始化Ultraman配置(user)", "message", Messages.getInformationIcon()); - }); - } - } - - public UltramanResponse call(UltramanRequest req) { - UltramanServiceGrpc.UltramanServiceBlockingStub stub2 = UltramanServiceGrpc.newBlockingStub(channel); - UltramanResponse res = stub2.hello(req); - return res; - } - - public StreamObserver listener(CountDownLatch latch) { - UltramanServiceGrpc.UltramanServiceStub stub = UltramanServiceGrpc.newStub(channel); - MutableObject mo = new MutableObject(); - final StreamObserver reqStream = stub.stream(new StreamObserver() { - @Override - public void onNext(UltramanResponse res) { - System.out.println(res.getData()); - //通知 - if (res.getCmd().equals("notify")) { - String data = res.getData(); - if (!res.getResMapOrDefault("user", "").equals("")) { - data = res.getResMapOrDefault("user", "") + ":" + data; - } - String type = res.getResMapOrDefault("type", "0"); - if (type.equals("0")) { - NotificationCenter.notice(data); - HintUtils.show(null, data); - } else { - HintUtils.show(null, data); - } - } - //查看图片 - if (res.getCmd().equals("image")) { - new ImageService().open(ActionEnum.zero.name()); - } - //显示代码 - if (res.getCmd().equals("show_code")) { - MutableObject moc = new MutableObject(); - ApplicationManager.getApplication().invokeAndWait(() -> { - int v = Messages.showOkCancelDialog(ProjectUtils.project(), "有人给你推送了代码,是否选择查看", "选择", Messages.getInformationIcon()); - moc.setValue(v); - }); - if ((int) moc.getValue() == 0) { - new DocumentService().open(res.getResMapMap().get("fileName"), res.getData()); - } - } - //查看代码(别人主动要看代码,返回我的代码) - if (res.getCmd().equals("begin_review")) { - String user = res.getResMapMap().get("review"); - - MutableObject moc = new MutableObject(); - ApplicationManager.getApplication().invokeAndWait(() -> { - int v = Messages.showOkCancelDialog(ProjectUtils.project(), user + "想要查看你当前的code", "选择", Messages.getInformationIcon()); - moc.setValue(v); - }); - - if ((int) moc.getValue() != 0) { - return; - } - - Pair data = new DocumentService().getContent(null); - if (null == data) { - data = Pair.of("对方没有打开源码", "tmp.java"); - } - StreamObserver reqStream = (StreamObserver) mo.getValue(); - UltramanRequest req = UltramanRequest.newBuilder().setCmd("begin_review_res") - .setParams(data.getKey()) - .putParamMap("fileName", data.getValue()) - .putParamMap("review", user) - .putParamMap("user", res.getResMapMap().get("user")) - .build(); - reqStream.onNext(req); - } - } - - @Override - public void onError(Throwable throwable) { - throwable.printStackTrace(); - latch.countDown(); - } - - @Override - public void onCompleted() { - latch.countDown(); - } - }); - mo.setValue(reqStream); - UltramanRequest loginReq = UltramanRequest.newBuilder().setCmd("login").putParamMap("user", config.getNickName()).build(); - reqStream.onNext(loginReq); - return reqStream; - - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ChromeUtils.java b/athena-all/src/main/java/run/mone/m78/ip/common/ChromeUtils.java deleted file mode 100644 index 6c2ddf175..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ChromeUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package run.mone.m78.ip.common; - -import com.google.gson.Gson; -import run.mone.m78.ip.bo.robot.AiChatMessage; -import lombok.SneakyThrows; - -/** - * @author goodjava@qq.com - * @date 2023/6/2 16:44 - */ -public class ChromeUtils { - - private static final Gson gson = new Gson(); - - @SneakyThrows - public static void call(String projectName, String method, String param, boolean useReq) { - - } - - - public static void call(String projectName, String param, int code) { - call(projectName, param, "", code); - } - - public static void call(String projectName, String param, String sound, int code) { - - } - - public static void call(String projectName, AiChatMessage res) { - - } - - - public static void call(String projectName, String method, String param) { - call(projectName, method, param, false); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ColorEggUtils.java b/athena-all/src/main/java/run/mone/m78/ip/common/ColorEggUtils.java deleted file mode 100644 index 95ef501cc..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ColorEggUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.common; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.DESKeySpec; -import java.security.SecureRandom; - -public class ColorEggUtils { - - /** - * 加密 - * - * @param content - * 待加密内容 - * @param key - * 加密的密钥 - * @return - */ - public static byte[] encrypt(String content, String key) { - try { - SecureRandom random = new SecureRandom(); - DESKeySpec desKey = new DESKeySpec(key.getBytes()); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); - SecretKey securekey = keyFactory.generateSecret(desKey); - Cipher cipher = Cipher.getInstance("DES"); - cipher.init(Cipher.ENCRYPT_MODE, securekey, random); - byte[] result = cipher.doFinal(content.getBytes()); - return result; - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - /** - * 解密 - * - * @param content - * 待解密内容 - * @param key - * 解密的密钥 - * @return - */ - public static String decrypt(byte[] content, String key) { - try { - SecureRandom random = new SecureRandom(); - DESKeySpec desKey = new DESKeySpec(key.getBytes()); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); - SecretKey securekey = keyFactory.generateSecret(desKey); - Cipher cipher = Cipher.getInstance("DES"); - cipher.init(Cipher.DECRYPT_MODE, securekey, random); - byte[] result = cipher.doFinal(content); - return new String(result); - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - - /** - * 将二进制转换成16进制 - * - * @param buf - * @return - */ - public static String parseByte2HexStr(byte buf[]) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < buf.length; i++) { - String hex = Integer.toHexString(buf[i] & 0xFF); - if (hex.length() == 1) { - hex = '0' + hex; - } - sb.append(hex); - } - return sb.toString(); - } - - /** - * hex字符串转byte数组 - * @param inHex 待转换的Hex字符串 - * @return 转换后的byte数组结果 - */ - public static byte[] hexToByteArray(String inHex){ - int hexlen = inHex.length(); - byte[] result; - if (hexlen % 2 == 1){ - //奇数 - hexlen++; - result = new byte[(hexlen/2)]; - inHex="0"+inHex; - }else { - //偶数 - result = new byte[(hexlen/2)]; - } - int j=0; - for (int i = 0; i < hexlen; i+=2){ - result[j]=hexToByte(inHex.substring(i,i+2)); - j++; - } - return result; - } - - public static byte hexToByte(String inHex){ - return (byte)Integer.parseInt(inHex,16); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/ConfigCenter.java b/athena-all/src/main/java/run/mone/m78/ip/common/ConfigCenter.java deleted file mode 100644 index 330b88b98..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/ConfigCenter.java +++ /dev/null @@ -1,51 +0,0 @@ -package run.mone.m78.ip.common; - -import run.mone.m78.ip.bo.AiCodeRes; -import run.mone.m78.ip.bo.Tag; -import lombok.Data; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * @author caobaoyu - * @description: 从Z获取一些基础配置 对应 -> 68 Athena の cfg center - * @date 2023-05-30 11:02 - */ -@Data -public class ConfigCenter { - - - private static Map copyrightingMap = new HashMap<>(); - - @Getter - private static List guide = new ArrayList<>(); - - private static List menuTag = new ArrayList<>(); - - public static Map getMenuTag() { - return menuTag.stream().collect(Collectors.toMap(Tag::getName, Function.identity())); - } - - public static void init(String zAddr) { - guide.clear(); - menuTag.clear(); - buildCopyrighting(zAddr); - } - - private static void buildCopyrighting(String zAddr) { - - - } - - public static AiCodeRes build(String type) { - return copyrightingMap.get(type); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Const.java b/athena-all/src/main/java/run/mone/m78/ip/common/Const.java deleted file mode 100644 index eeb5d3925..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Const.java +++ /dev/null @@ -1,64 +0,0 @@ -package run.mone.m78.ip.common; - -import com.intellij.openapi.util.Key; -import com.intellij.util.messages.Topic; -import run.mone.ultraman.listener.AthenaMessageListener; - -/** - * @author goodjava@qq.com - * @date 2023/6/17 09:37 - */ -public interface Const { - - String MODULE_FILE_NAME = ""; - - String REQ_PACKAGE = "req_package"; - - String DEFAULT_REQ_PACKAGE = "run.mone.bo"; - - String DISABLE_SEARCH = "disable.search"; - - String AI_PROXY_CHAT = "ai.proxy.chat"; - - String ENABLE_ATHENA_STATUS_BAR = "enable.athena.status.bar"; - - String DISABLE_ACTION_GROUP = "disable.action.group"; - - String BIZ_WRITE = "biz_write"; - - String OPEN_AI_KEY = "open_ai_key"; - - String OPEN_AI_PROXY = "open_ai_proxy"; - - //直接本地调用chatgpt(local模式) - String OPEN_AI_LOCAL = "open_ai_local"; - - //本地测试 - String OPEN_AI_TEST = "open.ai.test"; - - //提问的时候是否开启选中的文本 - String OPEN_SELECT_TEXT = "open.select.text"; - - String OPEN_AI_MODEL = "open_ai_model"; - - String SEARCH = "search"; - - int UI_CANCEL_CODE = 555; - - String OPEN_GUIDE = "open.guide"; - - String DEBUG = "debug"; - - //多模态模式 - String VISION = "vision"; - - String CODE_SCRIPT = "code.script"; - - String TREE_SELECT = "tree.select"; - - Key T_KEY = new Key<>("t"); - - Topic ATHENA_TOPIC = new Topic(AthenaMessageListener.class); - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/JavaClassUtils.java b/athena-all/src/main/java/run/mone/m78/ip/common/JavaClassUtils.java deleted file mode 100644 index 8b0e0c2da..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/JavaClassUtils.java +++ /dev/null @@ -1,51 +0,0 @@ -package run.mone.m78.ip.common; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; - -/** - * @author goodjava@qq.com - * @date 2023/4/12 11:05 - */ -public abstract class JavaClassUtils { - - /** - * Create a class. - */ - public static void createClass(AnActionEvent e) { - createClass(e.getProject(), e.getData(PlatformDataKeys.EDITOR), "abc", ""); - } - - public static void createClass(Project project, Editor editor, String name, String code) { - - } - - - public static void createClass(Project project, Editor editor, String name, String code, boolean testClass) { - - } - - public static void createClass(Project project, Editor editor, String name, String code, boolean testClass, String packagePath) { - - } - - - public static void openClass(AnActionEvent e) { - - } - - public static void openClass(Project project, String className) { - - } - - - public static String getClassName(String className) { - String[] classNameParts = className.split("\\."); - String simpleClassName = classNameParts[classNameParts.length - 1]; - return simpleClassName; - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/Prompt.java b/athena-all/src/main/java/run/mone/m78/ip/common/Prompt.java deleted file mode 100644 index 0a570f5a2..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/Prompt.java +++ /dev/null @@ -1,142 +0,0 @@ -package run.mone.m78.ip.common; - -import com.google.gson.Gson; -import lombok.extern.slf4j.Slf4j; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.bo.Tag; -import run.mone.m78.ip.bo.ZAddrRes; -import run.mone.m78.ip.bo.ZPromptRes; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * @author goodjava@qq.com - * @author caobaoyu - * @date 2023/4/15 08:38 - */ -@Slf4j -public class Prompt { - - private static Map promptMap = new HashMap<>(); - - private static CopyOnWriteArrayList promptMeta = new CopyOnWriteArrayList<>(); - - private static String zAddr = ""; - - private static AtomicBoolean loadFinish = new AtomicBoolean(); - - public static String get(String key) { - return promptMap.get(key); - } - - public static List getPromptMeta() { - return promptMeta; - } - - public static boolean isLoadFinish() { - return loadFinish.get(); - } - - - private static Gson gson = new Gson(); - - public static void flush() { - init(); - } - - public static int size() { - return promptMap.size(); - } - - - public static void init() { - - } - - public static List getPrompt() { - return null; - } - - - public static PromptInfo getPrompt(int type, String name) { - return null; - } - - - /** - * 将Z的结果转换为实体 - * - * @param data - * @return - */ - private static List convertZResToInfo(List data) { - return null; - } - - public static List promptList(String tagName) { - return null; - } - - public static boolean containsTag(List tags, String tagName) { - return false; - } - - /** - * 查询是那种类型 - * - * @param info - * @return - */ - public static PromptType getPromptType(PromptInfo info) { - return null; - } - - - public static ZAddrRes zAddrRes() { - return null; - } - - private static void initConfig(ZAddrRes zAddrRes) { - - } - - - public static PromptInfo getPromptInfo(String promptName) { - return null; - } - - public static List getPromptInfoByTag(String tag) { - return null; - } - - public static List getCollected() { - return null; - } - - /** - * 获取使用次数最多的size个prompt - * - * @param size - * @return - */ - public static List getMostUsed(int size) { - return null; - } - - /** - * 获取某个标签下使用次数最多的size个prompt - * - * @param size - * @param tag - * @return - */ - public static List getMostUsed(int size, String tag) { - return null; - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/common/StringUtils.java b/athena-all/src/main/java/run/mone/m78/ip/common/StringUtils.java deleted file mode 100644 index f3694976f..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/common/StringUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -package run.mone.m78.ip.common; - -/** - * @author goodjava@qq.com - * @date 2023/5/18 22:26 - */ -public abstract class StringUtils { - - public static String convertToCamelCase(String input) { - StringBuilder result = new StringBuilder(); - String[] words = input.split("_"); - result.append(words[0]); - for (int i = 1; i < words.length; i++) { - String word = words[i]; - String capitalizedWord = Character.toUpperCase(word.charAt(0)) + word.substring(1); - result.append(capitalizedWord); - } - return result.toString(); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/component/UltramanComponent.java b/athena-all/src/main/java/run/mone/m78/ip/component/UltramanComponent.java deleted file mode 100644 index 30ffb9493..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/component/UltramanComponent.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.component; - -import com.intellij.openapi.components.ApplicationComponent; -import com.intellij.openapi.project.Project; -import run.mone.m78.ip.ui.UltramanUi; - -/** - * @Author goodjava@qq.com - * @Date 2021/10/31 19:17 - */ -public class UltramanComponent implements ApplicationComponent { - - - @Override - public String getComponentName() { - return "UltramanComponent"; - } - - - - public void show(Project project) { - UltramanUi dialog = new UltramanUi(); - dialog.setSize(600, 800); - dialog.setLocationRelativeTo(null); - dialog.setVisible(true); - dialog.setResizable(false); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/PromptHandler.java b/athena-all/src/main/java/run/mone/m78/ip/listener/PromptHandler.java deleted file mode 100644 index 0b50137c4..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/PromptHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package run.mone.m78.ip.listener; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.project.Project; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.bo.robot.AiChatMessage; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; -import run.mone.m78.ip.bo.robot.Role; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.service.LocalAiService; -import run.mone.m78.ip.util.ResourceUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.mutable.MutableObject; -import run.mone.ultraman.manager.ConsoleViewManager; -import run.mone.ultraman.service.AiCodeService; -import run.mone.ultraman.state.ProjectFsmManager; - -import java.util.UUID; - -/** - * @author goodjava@qq.com - * @date 2023/12/10 16:01 - */ -public class PromptHandler { - - - //修改用户的问题 - public static String handler(Project project, Req req) { - return ""; - } - - //根据给定的提示更改提示信息,并在需要的情况下生成代码 - private static void changePrompt(Project project, String prompt, MutableObject r, Req req) { - - } - - - //移除选择 - private static void removeSelection(Project project) { - ApplicationManager.getApplication().invokeAndWait(() -> { - Editor editor = CodeService.getEditor(project); - if (null != editor) { - editor.getSelectionModel().removeSelection(); - } - }); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/RequestHandler.java b/athena-all/src/main/java/run/mone/m78/ip/listener/RequestHandler.java deleted file mode 100644 index b9ebd0c75..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/RequestHandler.java +++ /dev/null @@ -1,12 +0,0 @@ -package run.mone.m78.ip.listener; - -import org.cef.handler.CefRequestHandlerAdapter; - -/** - * @author goodjava@qq.com - * @date 2023/11/22 18:40 - */ -public class RequestHandler extends CefRequestHandlerAdapter { - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/listener/TreeMouseClickedListener.java b/athena-all/src/main/java/run/mone/m78/ip/listener/TreeMouseClickedListener.java deleted file mode 100644 index d926fc028..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/listener/TreeMouseClickedListener.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.listener; - -import com.intellij.ide.BrowserUtil; -import run.mone.m78.ip.bo.SpiderUrl; -import run.mone.m78.ip.service.ImageService; -import run.mone.m78.ip.service.MusicService; - -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/10 10:59 - */ -public class TreeMouseClickedListener extends MouseAdapter { - - private JTree tree1; - - private JTextField textField1; - - private JPopupMenu popupMenu; - - public TreeMouseClickedListener(JTree tree1, JTextField textField1, JPopupMenu popupMenu) { - this.tree1 = tree1; - this.textField1 = textField1; - this.popupMenu = popupMenu; - } - - @Override - public void mouseClicked(MouseEvent mouseEvent) { - - if (mouseEvent.getClickCount() == 2) { - TreePath path = tree1.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); - String data = node.toString(); - System.out.println(data); - - - String text = textField1.getText(); - - if (text.equals("image")) { - new ImageService().openImage(data); - return; - } - - if (text.equals("music")) { - MusicService service = MusicService.ins(); - service.stop(); - - Object root = tree1.getModel().getRoot(); - int count = tree1.getModel().getChildCount(root); - List l = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Object v = tree1.getModel().getChild(root, i); - l.add(v.toString()); - } - - service.playWithUrl(data); - return; - } - - //打开爬虫 - if (text.startsWith("spider")) { - SpiderUrl url = (SpiderUrl) node.getUserObject(); - BrowserUtil.browse(url.getUrl()); - return; - } - - } - - //中键 - if (mouseEvent.getButton() == MouseEvent.BUTTON3) { - if (textField1.getText().equals("task")) { - int x = mouseEvent.getX(); - int y = mouseEvent.getY(); - popupMenu.show(tree1, x, y); - } - } - - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/AiService.java b/athena-all/src/main/java/run/mone/m78/ip/service/AiService.java deleted file mode 100644 index 9fb373b27..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/AiService.java +++ /dev/null @@ -1,24 +0,0 @@ -package run.mone.m78.ip.service; - -import com.google.gson.JsonObject; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.LabelUtils; - -/** - * @author goodjava@qq.com - * @date 2023/12/5 22:51 - */ -public class AiService { - - - //同时支持远程和本地的(本地的被限流的次数会更少) - public static JsonObject call(String req, long timeout, boolean vip) { - if (LabelUtils.open(Const.OPEN_AI_TEST)) { - return LocalAiService.call(req, timeout); - } - return ProxyAiService.call(req, timeout, vip); - - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ChatGptService.java b/athena-all/src/main/java/run/mone/m78/ip/service/ChatGptService.java deleted file mode 100644 index cb32a1ba1..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ChatGptService.java +++ /dev/null @@ -1,31 +0,0 @@ -package run.mone.m78.ip.service; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import run.mone.m78.ip.common.Context; -import lombok.extern.slf4j.Slf4j; - -/** - * @author goodjava@qq.com - * @date 2023/3/11 21:36 - *

- * 在editor中生成代码的都走这里了 - */ -@Slf4j -public class ChatGptService extends AbstractService { - - - @Override - public void execute(Context context, AnActionEvent e) { - String content = context.getContent(); - if (null != e) { - context.setProject(e.getProject()); - } - if (!(content.startsWith("//"))) { - next(context, e); - return; - } - PromptService.generateMethod(e.getProject(), content); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/CodeService.java b/athena-all/src/main/java/run/mone/m78/ip/service/CodeService.java deleted file mode 100644 index 484d72e19..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/CodeService.java +++ /dev/null @@ -1,861 +0,0 @@ -package run.mone.m78.ip.service; - -import com.google.common.collect.Maps; -import com.google.gson.Gson; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.*; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PsiTreeUtil; -import run.mone.m78.ip.bo.ClassInfo; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.bo.ProxyAsk; -import run.mone.m78.ip.common.Context; -import run.mone.m78.ip.util.EditorUtils; -import run.mone.m78.ip.util.ImportUtils; -import run.mone.m78.ip.util.PsiClassUtils; -import run.mone.m78.ip.util.UltramanConsole; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import okhttp3.Response; -import org.apache.commons.compress.utils.Lists; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import run.mone.ultraman.common.ImportCode; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * @author goodjava@qq.com - */ -@Slf4j -public class CodeService extends AbstractService { - - private static Gson gson = new Gson(); - - /** - * 打个某个指定的class - * - * @param project - * @param className - */ - public static PsiClass openJavaClass(Project project, String className) { - return null; - } - - - public static PsiClass[] getClassesInPackage(Project project, String packageName) { - return null; - } - - - /** - * 移动到方法的开头,且插入空行 - * Navigate to the beginning of the method and insert a blank line. - * - * @param project - */ - public static void moveToMethodAndInsertLine(Project project) { - - } - - public static String getMethodAndLineNumbers(PsiMethod method) { - return ""; - } - - public static String getClassName(PsiClass psiClass) { - return ""; - } - - - private static boolean readCodeContinue(String lineCode) { - return lineCode.trim().startsWith("//") || lineCode.trim().startsWith("/*") - || lineCode.trim().startsWith("*") || lineCode.trim().startsWith("*/"); - } - - public static String getClassAndLineNumbers(PsiClass psiClass) { - return ""; - } - - public static void addField(Project project, Document document, PsiClass psiClass, String code, String name) { - - } - - /** - * 添加方法 - * - * @param project - * @param code - */ - public static void addMethod(Project project, String code) { - - } - - - public static void insertCode(Project project, String code) { - } - - public static void insertCode(Project project, String code, boolean enter) { - } - - - /** - * 添加 import list - * - * @param project - * @param importStrList - */ - @SneakyThrows - public static void addImport(Project project, List importStrList) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - addImport(project, editor, importStrList); - } - - - public static void addImport(Project project, Editor editor, List importStrList) { - ImportUtils.addImport(project, editor, importStrList); - } - - - public static PsiClass createPsiClass(PsiElementFactory factory, String className) { - return ImportUtils.createPsiClass(factory, className); - } - - - /** - * 根据需求直接生成方法 - * - * @param project - * @param prompt - */ - public static void generateMethod(Project project, String prompt) { - } - - /** - * 向方法中添加语句 - * - * @param project - * @param code - */ - public static void addStatementToMethod(Project project, String code) { - - } - - /** - * 把代码写入Idea Editor - * - * @param project - * @param editor - * @param code - */ - public static void writeCode2(Project project, Editor editor, String code) { - writeCode4(project, editor, code, true); - } - - public static void writeCode4(Project project, Editor editor, String code, boolean appendT) { - - } - - public static void moveCaretToEndOfLine(Editor editor) { - Document document = editor.getDocument(); - CaretModel caretModel = editor.getCaretModel(); - int lineNumber = document.getLineNumber(caretModel.getOffset()); - int lineEndOffset = document.getLineEndOffset(lineNumber); - caretModel.moveToOffset(lineEndOffset); - } - - private static boolean isFirstColumn(int offset, Editor editor) { - int lineNumber = editor.getDocument().getLineNumber(offset); - int lineStartOffset = editor.getDocument().getLineStartOffset(lineNumber); - boolean isFirstColumn = (offset - lineStartOffset) == 0; - return isFirstColumn; - } - - - public static void writeCode3(Project project, String code) { - UltramanConsole.append(project, code, false); - } - - - public static Pair lineAndColumnNum(Document document, int offset) { - int lineNumber = document.getLineNumber(offset) + 1; - int columnNumber = offset - document.getLineStartOffset(lineNumber - 1); - return Pair.of(lineNumber, columnNumber); - } - - - /** - * 移动到指定行号 - * - * @param project - * @param lineNumber - */ - public static void moveLine(Project project, int lineNumber) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - LogicalPosition position = new LogicalPosition(lineNumber - 1, 0); // 创建逻辑位置对象 - editor.getCaretModel().moveToLogicalPosition(position); // 将光标移动到指定行 - } - - - /** - * 关闭当前Editor - * - * @param project - */ - public static void closeEditor(Project project) { - EditorUtils.closeEditor(project); - } - - /** - * 格式化当前代码 - */ - public static void formatCode(Project project) { - if (null == project) { - return; - } - } - - @Nullable - public static Project deleteCode(@NotNull Editor editor) { - return null; - } - - - /** - * 删除指定行 - * - * @param project - * @param lineToDelete - */ - public static void deleteLine(Project project, int lineToDelete) { - } - - - /** - * 返回所有method - * - * @param project - * @return - */ - public static List methods(Project project) { - Editor editor = getEditor(project); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); - PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); - return Arrays.stream(currentPsiClass.getAllMethods()).map(it -> it.getName()).collect(Collectors.toList()); - } - - - /** - * 通过module查询会快点 - * - * @param project - * @param module - * @param name - * @return - */ - public static PsiClass getPsiClass(Project project, Module module, String name) { - PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(name, GlobalSearchScope.moduleScope(module)); - return psiClass; - } - - - public static List methods(PsiClass psiClass) { - return Arrays.stream(psiClass.getMethods()).filter(it -> it.getModifierList().hasModifierProperty("public")).map(it -> it.getName()).collect(Collectors.toList()); - } - - - public static List fields(Project project) { - Editor editor = getEditor(project); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); - PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); - return Arrays.stream(currentPsiClass.getAllFields()).map(it -> it.getName()).collect(Collectors.toList()); - } - - public static PsiMethod getMethod(Project project) { - return null; - } - - public static String getMethodCode(Project project) { - return ApplicationManager.getApplication().runReadAction((Computable) () -> getMethod(project).getText()); - } - - public static PsiField getPsiField(Project project) { - return null; - } - - - public static boolean isTextSelected(Editor editor) { - return editor.getSelectionModel().hasSelection(); - } - - public static String getSelectedText(Editor editor) { - if (isTextSelected(editor)) { - SelectionModel selectionModel = editor.getSelectionModel(); - String selectedText = selectionModel.getSelectedText(); - return selectedText; - } - return ""; - } - - - public static PsiElement getSelectedPsiMethod(Editor editor, PsiFile psiFile) { - SelectionModel selectionModel = editor.getSelectionModel(); - int start = selectionModel.getSelectionStart(); - int end = selectionModel.getSelectionEnd(); - for (int i = start; i < end; i++) { - PsiElement element = psiFile.findElementAt(i); - @Nullable PsiMethod pm = PsiTreeUtil.getParentOfType(element, PsiMethod.class); - if (null != pm) { - return pm; - } - } - return null; - } - - public static PsiMethod getPsiMethodWithLineNum(Project project, Document document, int lineNum) { - return null; - } - - public static PsiField getPsiFieldWithLineNum(Project project, Document document, int lineNum) { - return ApplicationManager.getApplication().runReadAction((Computable) () -> { - @Nullable PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); - int start = document.getLineStartOffset(lineNum - 1); - int end = document.getLineEndOffset(lineNum - 1); - for (int i = start; i < end; i++) { - PsiElement element = psiFile.findElementAt(i); - @Nullable PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class); - if (null != field) { - return field; - } - } - return null; - }); - } - - - public static PsiClass getPsiClassWithLineNum(Project project, Document document, int lineNum) { - return ApplicationManager.getApplication().runReadAction((Computable) () -> { - @Nullable PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); - int start = document.getLineStartOffset(lineNum - 1); - int end = document.getLineEndOffset(lineNum - 1); - for (int i = start; i < end; i++) { - PsiElement element = psiFile.findElementAt(i); - @Nullable PsiClass pm = PsiTreeUtil.getParentOfType(element, PsiClass.class); - if (null != pm) { - return pm; - } - } - return null; - }); - - } - - - public static TextRange getTextRange(Project project, final Class clazz) { - Editor editor = getEditor(project); - CaretModel caretModel = editor.getCaretModel(); - int offset = caretModel.getOffset(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(offset); - - while (true) { - if (elementAtCaret.getClass().equals(clazz)) { - return elementAtCaret.getTextRange(); - } - elementAtCaret = elementAtCaret.getParent(); - if (null == elementAtCaret) { - return null; - } - } - } - - public static String getText(Project project, Class clazz) { - Editor editor = getEditor(project); - CaretModel caretModel = editor.getCaretModel(); - int offset = caretModel.getOffset(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(offset); - PsiElement element = PsiTreeUtil.getParentOfType(elementAtCaret, clazz); - return element.getText(); - } - - public static TextRange getParentTextRange(Project project) { - Editor editor = getEditor(project); - CaretModel caretModel = editor.getCaretModel(); - int offset = caretModel.getOffset(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - return psiFile.findElementAt(offset).getParent().getParent().getTextRange(); - } - - - public static PsiClass getPsiClass(Project project) { - Editor editor = getEditor(project); - if (null == editor) { - return null; - } - CaretModel caretModel = editor.getCaretModel(); - int offset = caretModel.getOffset(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(offset); - PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); - return psiClass; - } - - - public static PsiElement getParentOfType(Project project, Class clazz) { - Editor editor = getEditor(project); - if (null == editor) { - return null; - } - CaretModel caretModel = editor.getCaretModel(); - int offset = caretModel.getOffset(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(offset); - PsiElement res = PsiTreeUtil.getParentOfType(elementAtCaret, clazz); - return res; - } - - - public static PsiClass getPsiClass2(Project project) { - Editor editor = getEditor(project); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiClass psiClass = Arrays.stream(psiFile.getChildren()).filter(it -> it instanceof PsiClass).map(it -> (PsiClass) it).findFirst().get(); - return psiClass; - } - - - public static PsiMethod getMethod(PsiClass psiClass, String methodName) { - PsiMethod[] methods = psiClass.findMethodsByName(methodName, false); - return methods[0]; - } - - - public static Map getLineContentsAndNumbersForMethod(PsiMethod method) { - return Maps.newHashMap(); - } - - - public static String getClassText(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - return editor.getDocument().getText(); - } - - public static String getClassText2(Project project) { - return ""; - } - - - /** - * 根据prompt删除注解 - * - * @param project - */ - public static void removeComments(Project project) { - } - - - public static void createEmptyClass(Project project, String moduleName, String packageName, String className) { - createEmptyClass(project, moduleName, packageName, className, false); - } - - /** - * 创建空的类 - * - * @param project - * @param packageName - * @param className - */ - public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath) { - PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath); - } - - - public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath, boolean isInterface) { - PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath, false, null, isInterface); - } - - - public static void createEmptyClass(Project project, String moduleName, String packageName, String className, boolean testPath, List annoList) { - PsiClassUtils.createEmptyClass(project, moduleName, packageName, className, testPath, annoList); - } - - - public static PsiDirectory getSourceDirectory(Project project, String moduleName, boolean testPath) { - return PsiClassUtils.getSourceDirectory(project, moduleName, testPath); - } - - public static PsiDirectory getSourceDirectory(Project project, boolean testPath, String packagePath) { - return PsiClassUtils.getSourceDirectory(project, testPath, packagePath); - } - - public static PsiDirectory getSourceDirectory(Project project) { - return PsiClassUtils.getSourceDirectory(project, "", false); - } - - - public static List getClassByServiceAnno(Project project, String anno) { - return null; - } - - private static List getAllJavaFiles(PsiDirectory dir) { - return null; - } - - - /** - * 创建包路径 - * - * @param project - * @param packageName - */ - public static void createPackage(Project project, String packageName) { - - } - - public static List listMethodInfo(String clazz) { - return Lists.newArrayList(); - } - - /** - * 生成一个moon demo的handler - * - * @param project - */ - public static void generateMoonHandler(Project project) { - - } - - /** - * 获取当前类的package 路径 - * - * @param project - * @return 包路径 - */ - public static String getPackagePath(Project project) { - Editor editor = getEditor(project); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiElement elementAtCaret = psiFile.findElementAt(editor.getCaretModel().getOffset()); - // 获取最近的PsiClass - PsiClass currentPsiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class); - PsiJavaFile psiJavaFile = (PsiJavaFile) currentPsiClass.getContainingFile(); - PsiPackage psiPackage = JavaPsiFacade.getInstance(currentPsiClass.getProject()).findPackage(psiJavaFile.getPackageName()); - return psiPackage.getQualifiedName(); - } - - - @Override - public void execute(Context context, AnActionEvent e) { - this.next(context, e); - } - - public static void addClassAnno(Project project, PsiClass psiClass, List annoList) { - - } - - /** - * 删除这个编辑器中的所有内容 - * - * @param project - */ - public static void deleteCode(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - WriteCommandAction.runWriteCommandAction(project, () -> { - editor.getDocument().setText(""); - }); - Caret caret = editor.getCaretModel().getPrimaryCaret(); - caret.moveToOffset(0); - } - - public static void deleteTextRange(Project project, TextRange range) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - WriteCommandAction.runWriteCommandAction(project, () -> { - Document document = editor.getDocument(); - document.deleteString(range.getStartOffset(), range.getEndOffset()); - PsiDocumentManager.getInstance(project).commitDocument(document); - }); - } - - - public static boolean isClass(String text) { - if (text.contains(" class ")) { - return true; - } - return false; - } - - public static boolean isPrivateField(String text) { - if (text.contains("private") && text.contains(";")) { - return true; - } - return false; - } - - - private static Integer getNumFromStr(String str) { - Pattern pattern = Pattern.compile("\\d+"); - Matcher matcher = pattern.matcher(str); - String lineNumber = "0"; - if (matcher.find()) { - lineNumber = matcher.group(); - } - return Integer.valueOf(lineNumber); - } - - /** - * 通过chatgpt生成代码,然后插入编辑器中 - * - * @param project - * @param context - * @param prompt - */ - public static void generateCodeWithAi(Project project, String context, String[] prompt, BiConsumer consumer) { - - } - - public static void generateCodeWithAi2(Project project, String promptName, String[] pramas, BiConsumer consumer) { - generateCodeWithAi3(project, promptName, pramas, Maps.newHashMap(), consumer); - } - - - public static void generateCodeWithAi3(Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer) { - generateCodeWithAi4(project, promptName, pramas, paramMap, consumer, new MessageConsumer()); - } - - - public static void generateCodeWithAi4(Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer, MessageConsumer messageConsumer) { - generateCodeWithAi5(GenerateCodeReq.builder().promptName(promptName).project(project).build(), project, promptName, pramas, paramMap, consumer, messageConsumer); - } - - - @SneakyThrows - public static String call(String promptName, Map paramMap) { - return ""; - } - - - public static void generateCodeWithAi5(GenerateCodeReq req, Project project, String promptName, String[] pramas, Map paramMap, BiConsumer consumer, MessageConsumer messageConsumer) { - - } - - public static void setModelAndDebug(Project project, ProxyAsk pa, Map paramMap, GenerateCodeReq req) { - } - - private static int getCodeSize(Map paramMap) { - return 1; - } - - - @NotNull - private static String getErrorMessage(Throwable t, Response response) { - String message = ""; - if (null != response) { - message = response.message(); - if (StringUtils.isNotEmpty(message)) { - message = "错误原因:" + message; - } else { - message = ""; - } - } - if (null != t) { - message += t.getMessage(); - } - return message; - } - - - public static void generateCodeWithAi(Project project, String context, String[] prompt) { - generateCodeWithAi(project, context, prompt, (p, code) -> { - writeCode(p, code); - }); - } - - - /** - * 直接插入代码 - * - * @param project - * @param str - */ - public static void writeCode(Project project, String str) { - - } - - - /** - * 选中一个方法 - * - * @param project - */ - public static PsiMethod selectMethod(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - if (null == editor) { - return null; - } - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - if (psiFile == null) { - return null; - } - PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset()); - PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); - return method; - } - - public static void deleteMethod(Project project, PsiMethod method) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - if (null == editor) { - return; - } - - if (null == method) { - return; - } - Document document = editor.getDocument(); - int startOffset = method.getTextRange().getStartOffset(); - - editor.getCaretModel().getPrimaryCaret().moveToOffset(startOffset); - - int endOffset = method.getTextRange().getEndOffset(); - WriteCommandAction.runWriteCommandAction(project, () -> document.deleteString(startOffset, endOffset)); - } - - public static void deletePsiClass(Project project, PsiClass psiClass) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - Document document = editor.getDocument(); - int startOffset = psiClass.getTextRange().getStartOffset(); - editor.getCaretModel().getPrimaryCaret().moveToOffset(startOffset); - int endOffset = psiClass.getTextRange().getEndOffset(); - WriteCommandAction.runWriteCommandAction(project, () -> document.deleteString(startOffset, endOffset)); - } - - - public static Editor getEditor(Project project) { - return EditorUtils.getEditor(project); - } - - public static Document getDocument(Project project) { - return getEditor(project).getDocument(); - } - - - /** - * 添加空行 - * - * @param project - * @param document - * @param num - */ - public static void addLineBreak(Project project, Document document, int lineNum, int num) { - - } - - public static List getClassList(Project project, String end, String mn) { - return null; - } - - - private static String findPomDependencies(String basePath, String groupId, String artifactId, String version) throws IOException { - File baseDir = new File(basePath); - String[] extensions = {"xml"}; - boolean recursive = true; - - Collection pomFiles = FileUtils.listFiles(baseDir, extensions, recursive); - for (File pomFile : pomFiles) { - try { - MavenXpp3Reader reader = new MavenXpp3Reader(); - Model model = reader.read(new FileReader(pomFile)); - List dependencies = model.getDependencies(); - for (Dependency dependency : dependencies) { - if (dependency.getGroupId().equals(groupId) && - dependency.getArtifactId().equals(artifactId) && - dependency.getVersion().equals(version)) { - // 找到了指定的依赖项 - return "找到了"; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - return "没找到"; - } - - - /** - * 获取方法的注释 - * - * @param psiMethod - * @return - */ - public static String getMethodComment(PsiMethod psiMethod) { - PsiDocComment comment = psiMethod.getDocComment(); - if (comment != null) { - return comment.getText(); - } - return null; - } - - /** - * 获取属性的注释 - * - * @param psiField - * @return - */ - public static String getFieldComment(PsiField psiField) { - PsiDocComment comment = psiField.getDocComment(); - if (comment != null) { - return comment.getText(); - } - return ""; - } - - public static ImportCode createClassAndAddEmptyLine(Project project, String module, String packageName, String className, String classNameSuffix, boolean isTestClass, boolean isInterface) { - return null; - } - - private static void addEmptyLine(Project project, PsiClass openJavaClass, Editor editor) { - PsiMethod @NotNull [] methods = openJavaClass.getMethods(); - int offset = 0; - if (0 == methods.length) { - offset = openJavaClass.getTextRange().getEndOffset() - 3; - } else { - PsiMethod psiMethod = methods[methods.length - 1]; - offset = psiMethod.getTextRange().getEndOffset(); - } - editor.getCaretModel().moveToOffset(offset); - CodeService.writeCode2(project, editor, "\n"); - - } - - - @Override - public void next(Context context, AnActionEvent e) { - super.next(context, e); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/DocumentService.java b/athena-all/src/main/java/run/mone/m78/ip/service/DocumentService.java deleted file mode 100644 index d2e1246e1..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/DocumentService.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.service; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.diagnostic.Logger; -import org.apache.commons.lang3.tuple.Pair; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/6 12:08 - */ -public class DocumentService { - - private static final Logger log = Logger.getInstance(DocumentService.class); - - /** - * 用ide打开文件 - * - * @param name - * @param text - */ - public void open(String name, String text) { - log.info("open file"); - } - - /** - * 获取文件内容和文件名(content,fileName) - * - * @param anActionEvent - * @return - */ - public Pair getContent(AnActionEvent anActionEvent) { - log.info("get content"); - return null; - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/LocalAiService.java b/athena-all/src/main/java/run/mone/m78/ip/service/LocalAiService.java deleted file mode 100644 index 4a9b83b76..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/LocalAiService.java +++ /dev/null @@ -1,139 +0,0 @@ -package run.mone.m78.ip.service; - -import com.google.common.collect.Lists; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.intellij.openapi.project.Project; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.tuple.Pair; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.chatgpt.*; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.util.ResourceUtils; -import run.mone.openai.StreamListener; -import run.mone.ultraman.common.GsonUtils; - -import java.io.File; -import java.util.List; - -/** - * @author goodjava@qq.com - * @date 2023/11/23 13:56 - *

- * 这个类允许你本地直连chatgpt(如果是国内的网络需要设置open_ai_proxy) - */ -@Slf4j -public class LocalAiService { - - - private static String getOpenAiUrl() { - String url = ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_PROXY, ""); - return url; - } - - - /** - * 调用chatgpt的语音翻译(你需要有chatgpt的账号) - * - * @param file - * @return - */ - @SneakyThrows - public static Pair callChatgptTranscriptions(File file) { - return Pair.of(200, ""); - } - - - /** - * 把文字转成语音 - * - * @param req - * @return - */ - @SneakyThrows - public static Pair speech(SpeechReq req) { - return null; - } - - - //多模态调用(支持图片) - public static String vision(VisionReq req) { - return ""; - } - - - public static JsonObject call(List messageList) { - Completions completions = Completions.builder() - .stream(false) - .response_format(Format.builder().build()).messages(messageList).build(); - String req = GsonUtils.gson.toJson(completions); - return call(req); - } - - - public static JsonObject call(String req) { - return call(req, 5000); - } - - //这个会直接调用chatgpt - @SneakyThrows - public static JsonObject call(String req, long timeout) { - return null; - } - - - //直接问问题(直接调用chatgpt) - public static void completions(String req, StreamListener sl) { - } - - - private static String parse(String data) { - log.info(data); - if (data.equals("[DONE]")) { - return ""; - } - return ""; - } - - private static JsonObject parseJson(String data) { - log.info("data:{}", data); - JsonObject obj = GsonUtils.gson.fromJson(data, JsonObject.class); - JsonArray choices = obj.getAsJsonArray("choices"); - return GsonUtils.gson.fromJson(choices.get(0).getAsJsonObject().getAsJsonObject("").get("").getAsString(), JsonObject.class); - } - - //本地直接调用chatgpt,单条提问 - public static void localCall(Project project, String prompt) { - localCall(project, Lists.newArrayList(Message.builder().content(prompt).role("user").build()), false, 0); - } - - - public static void localCall(String projectName, boolean code) { - } - - - public static void localCall(Project project, List messageList, boolean code, int num) { - } - - - public static List getLastElements(List list, int num) { - return null; - } - - private static void chat(Project project, boolean code, List newMessageList, String projectName, String id) { - } - - - //调用ai proxy(进行聊天) - private static void aiProxyChat(Project project, List newMessageList) { - - } - - //每次都只发一部分(发送到右侧 athena) - private static void sendMsg(AiMessage message, String projectName) { - - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/MusicService.java b/athena-all/src/main/java/run/mone/m78/ip/service/MusicService.java deleted file mode 100644 index a36a9ab2f..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/MusicService.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.service; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ApplicationManager; -import run.mone.m78.ip.action.ActionEnum; -import run.mone.m78.ip.common.ApiCall; -import run.mone.m78.ip.common.Context; -import run.mone.m78.ip.common.Mp3PlayerV2; -import run.mone.m78.ip.common.NotificationCenter; -import run.mone.m78.ip.common.Safe; -import org.apache.commons.lang.StringUtils; - -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/6 11:46 - */ -public class MusicService extends AbstractService { - - private List list = new ArrayList<>(); - - private int index; - - private String musicUrl; - - public void setList(List list) { - this.list = list; - } - - private static final class LazyHolder { - private static MusicService ins = new MusicService(); - } - - public static MusicService ins() { - return LazyHolder.ins; - } - - private MusicService() { - Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { - if (StringUtils.isNotEmpty(musicUrl)) { - if (Mp3PlayerV2.ins().isComplete()) { - play(musicUrl); - } - } - }, 0, 1, TimeUnit.SECONDS); - } - - public synchronized void play(String t) { - musicUrl = t; - ApplicationManager.getApplication().invokeLater(() -> { - Safe.run(() -> { - if (StringUtils.startsWith(t, ActionEnum.diga.name() + ":")) { - String url = new ApiCall().callIt(ApiCall.MUSIC_API, t.replaceFirst(ActionEnum.diga.name() + ":", "") + ".mp3"); - InputStream input = new URL(url).openStream(); - Mp3PlayerV2.ins().play(input); - return; - } - String url = new ApiCall().callOne(ApiCall.MUSIC_API); - NotificationCenter.notice("music:" + url); - InputStream input = new URL(url).openStream(); - //这里会启用一个新的线程 - Mp3PlayerV2.ins().play(input); - }); - }); - } - - public void playWithUrl(String url) { - Safe.run(() -> { - InputStream input = new URL(url).openStream(); - Mp3PlayerV2.ins().play(input); - }); - } - - public synchronized void stop() { - this.musicUrl = ""; - Safe.run(() -> Mp3PlayerV2.ins().close()); - } - - @Override - public void execute(Context context, AnActionEvent e) { - String content = context.getContent(); - if (content.equals(ActionEnum.diga.name()) || StringUtils.startsWith(content, ActionEnum.diga.name() + ":")) { - play(content); - return; - } - - if (content.equals(ActionEnum.diga_stop.name())) { - stop(); - return; - } - - this.next(context, e); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/PromptService.java b/athena-all/src/main/java/run/mone/m78/ip/service/PromptService.java deleted file mode 100644 index 01befe325..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/PromptService.java +++ /dev/null @@ -1,356 +0,0 @@ -package run.mone.m78.ip.service; - -import com.google.gson.Gson; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiMethod; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.Message; -import run.mone.m78.ip.bo.PromptContext; -import run.mone.m78.ip.bo.RobotContext; -import run.mone.m78.ip.util.HintUtils; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; -import java.util.Map; - -import static run.mone.m78.ip.util.PromptUtils.*; - -/** - * @author goodjava@qq.com - * @author baoyu - * @date 2023/5/11 21:53 - *

- * 这个类主要处理Prompt在Idea中的落地(写入编辑器) - */ -@Slf4j -public class PromptService { - - private static Gson gson = new Gson(); - - /** - * 动态执行 - * - * @param req - * @return - */ - public static String dynamicInvoke(GenerateCodeReq req) { - setReq(req); - switch (req.getPromptType()) { - case createClass -> createClass(req.getProject(), req.getModule().getName(), req.getPromptName()); - case createClass4 -> createClass4(req); - case createMethod -> createMethod(req); - case createMethod2 -> createMethod2(req); - case comment -> addComment(req); - case lineByLineComment -> lineByLineCommentOrCode(req.getPromptName(), req); - case createFile -> createFile(req.getPromptName(), req.getFileName(), req); - case modifyClass -> updateClass(req); - case modifyMethod -> updateMethod(req); - case select -> select(req, req.getProject(), req.getModule(), req.getPromptInfo()); - case removeComment -> removeComment(req.getProject()); - case showInfo -> showInfo(req); - case repleaceSelectContent -> repleaceSelectContent(req); - case testPrompt -> testPrompt(req); - case checkPomVersion -> checkPomVersion(req); - case generateBootStrapAnno -> generateAnnoForBootStrap(req.getPromptName(), req.getProject()); - case inlayHint -> inlayHint(req); - case genBizMethodCode -> genBizMethodCode(req); - case generateMethod -> generateMethod(req, req.getProject(), ""); - case bot -> RobotService.bot(req); - case generateMiapiMethod -> generateMiapiMethod(req); - case generateInterface -> generateInterface(req); - case question -> question(req); - case createClass2 -> - createClass2(req.getProject(), req.getPromptName(), req.getShowDialog(), req.getParam()); - default -> { - return "UnSupport"; - } - } - return "ok"; - } - - private static void createClass4(GenerateCodeReq req) { - - } - - //ai会向你提问(绝大部分分多步的操作,ai问你更合适) - private static void question(GenerateCodeReq req) { - - } - - //后边代码尽量用这里获取的内容,editor中的内容放入到req中,避免后边的再次获取 - public static void setReq(GenerateCodeReq req) { - - } - - private static String getClassPackage(String qualifiedName) { - int lastDotIndex = qualifiedName.lastIndexOf('.'); - if (lastDotIndex >= 0) { - return qualifiedName.substring(0, lastDotIndex); - } - return ""; - } - - - //获取编辑器的注释信息 - private static String getComment(Editor editor) { - return getComment(editor, "//biz:"); - } - - private static String getComment(Editor editor, String str) { - return ""; - } - - - /** - * 生成业务方法 - * - * @param req - */ - public static void genBizMethodCode(GenerateCodeReq req) { - - } - - private static String addCode(GenerateCodeReq req, Map m, PromptContext context) { - return ""; - } - - - //添加上下文信息到映射中 - private static void addContext(GenerateCodeReq req, Map m, PromptContext promptContext) { - - } - - public static String getResourceFromAi(Project project, Map m, PromptContext promptContext, List resourceCode) { - return ""; - } - - - public static void inlayHint(GenerateCodeReq req) { - - } - - /** - * 测试prompt的接口 - * - * @param req - */ - private static void testPrompt(GenerateCodeReq req) { - - } - - private static void repleaceSelectContent(GenerateCodeReq req) { - - } - - /** - * 在聊天窗口显示信息 - * - * @param req - */ - public static void showInfo(GenerateCodeReq req) { - - } - - - public static void generateMethod(Project project, String content) { - - } - - - //创建方法都收口在这里了 - public static void generateMethod(GenerateCodeReq req) { - - } - - private static void initAiReqMap(GenerateCodeReq req, Map aiReqMap) { - - } - - private static void analysisScope(GenerateCodeReq req, PromptContext context) { - - } - - private static void addField(GenerateCodeReq req, Map map) { - - } - - private static void addClass(GenerateCodeReq req, Map map, PromptContext context) { - - } - - - public static String getCode(GenerateCodeReq req, PromptContext context) { - return ""; - } - - /** - * 删除逐行注释 - * - * @param project - */ - private static void removeComment(Project project) { - PsiMethod psiMethod = CodeService.getMethod(project); - Editor editor = CodeService.getEditor(project); - if (null == psiMethod) { - HintUtils.show(editor, Message.selectMethodMsg, true); - return; - } - PsiMethodUtils.deleteCommentsFromMethod(project, psiMethod, comment -> comment.getText().startsWith("//Athena:")); - } - - - - /** - * 生成方法(在edit中) - * - * @param project - * @param text - */ - public static void generateMethod(GenerateCodeReq req, Project project, String text) { - - } - - - private static void createMethod(GenerateCodeReq req) { - - } - - /** - * stream样式添加注释 - */ - public static void comment2(RobotContext context, GenerateCodeReq req) { - } - - /** - * 给出一些修改代码的意见 - */ - public static void modifyCodeSuggest(RobotContext context, GenerateCodeReq req) { - } - - /** - * 需要导入那些依赖 - * - * @param context - * @param req - */ - public static void getImport(RobotContext context, GenerateCodeReq req) { - req.setPromptName("get_import"); - addComment(req); - } - - - /** - * 根据类生成sql建表文件 - * - * @param context - * @param req - */ - public static void createTabStatement(RobotContext context, GenerateCodeReq req) { - createFile("create_tab_statement", "tmp.sql", req); - } - - /** - * 把class转换为json文件 - * - * @param context - * @param req - */ - public static void classJson(RobotContext context, GenerateCodeReq req) { - createFile("class_json", "tmp.json", req); - } - - - /** - * 根据业务需求直接生成代码 - * - * @param context - * @param req - */ - public static void bizCodeGen(RobotContext context, GenerateCodeReq req) { - } - - - - - /** - * 创建方法2 - *

- * 会打开两个表单 - * 1.填参数 - * 2.选中类和方法 - * - *

- * 选择类和方法,然后插入代码 - *

- * 可以用来生成Controller中的方法 - * - * @param req - */ - public static void createMethod2(GenerateCodeReq req) { - - - } - - public static void addFields(Project project, String serviceName, String shortServiceName, PsiClass psiClass, Editor editor) { - } - - public static void addImports(GenerateCodeReq req, Project project, String serviceName, String reqClass, Editor editor) { - } - - public static void addImports(GenerateCodeReq req, Project project, String serviceName, String reqClass, Editor editor, boolean unitTest, boolean resource, String unitVersion) { - - } - - /** - * 给interface中添加方法(返回值可能被包装要注意) - * - * @param psiClass - */ - private static void addMethodToInterface(GenerateCodeReq req, PsiClass psiClass, PsiMethod pm, PsiClass reqClass) { - - } - - private static void modifyReq(GenerateCodeReq req, PsiMethod pm, String reqClass) { - - } - - private static void setLabels(GenerateCodeReq req, Map map) { - - } - - - /** - * 生成使用中间件的代码 - * - * @param context - * @param req - */ - public static void midCodeGen(RobotContext context, GenerateCodeReq req) { - } - - /** - * 逐行注释 - * - * @param context - * @param req - */ - public static void cc(RobotContext context, GenerateCodeReq req) { - } - - /** - * fix(问题修复,给出来的是建议) - * - * @param context - * @param req - */ - public static void fix(RobotContext context, GenerateCodeReq req) { - } - - //暂时只生成接口引入 - public static void generateMiapiMethod(GenerateCodeReq req) { - - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/ProxyAiService.java b/athena-all/src/main/java/run/mone/m78/ip/service/ProxyAiService.java deleted file mode 100644 index 016ebfd93..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/ProxyAiService.java +++ /dev/null @@ -1,41 +0,0 @@ -package run.mone.m78.ip.service; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import run.mone.m78.ip.bo.chatgpt.Message; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; - -/** - * @author goodjava@qq.com - * @date 2023/12/5 22:13 - */ -@Slf4j -public class ProxyAiService { - - - private static Gson gson = new Gson(); - - public static JsonObject call(List messageList) { - return call(messageList, 50000); - } - - public static JsonObject call(String r, long time, boolean vip) { - String pa = "jsonStr"; - String req = gson.toJson(pa); - return call0(req, time, vip); - } - - //调用ai proxy (调用的是json接口,返回的数据一定是json格式) - public static JsonObject call0(String req, long time, boolean vip) { - return null; - } - - public static JsonObject call(List messageList, long time) { - String pa = "jsonStr"; - String req = gson.toJson(pa); - return call0(req, time, true); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/PsiMethodUtils.java b/athena-all/src/main/java/run/mone/m78/ip/service/PsiMethodUtils.java deleted file mode 100644 index a82638d23..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/PsiMethodUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -package run.mone.m78.ip.service; - -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.function.Predicate; - -/** - * @author goodjava@qq.com - * @date 2023/6/3 22:31 - */ -public class PsiMethodUtils { - - - /** - * 删除指定方法中的注释 - * - * @param psiMethod - */ - public static void deleteCommentsFromMethod(Project project, PsiMethod psiMethod, Predicate predicate) { - @NotNull Collection comments = PsiTreeUtil.collectElementsOfType(psiMethod, PsiComment.class); - WriteCommandAction.runWriteCommandAction(project, () -> { - for (PsiComment comment : comments) { - if (predicate.test(comment)) { - comment.delete(); - } - } - }); - } - - /** - * 修改方法名 - * - * @param project 项目对象 - * @param document 文档对象 - * @param method 方法对象 - * @param newName 新方法名 - */ - public static void modifyMethodName(Project project, Document document, PsiMethod method, String newName) { - - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/TestService.java b/athena-all/src/main/java/run/mone/m78/ip/service/TestService.java deleted file mode 100644 index 396b2e879..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/TestService.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.service; - -import com.intellij.openapi.actionSystem.AnActionEvent; -import lombok.extern.slf4j.Slf4j; -import run.mone.m78.ip.common.Context; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/7 21:43 - */ -@Slf4j -public class TestService extends AbstractService { - @Override - public void execute(Context context, AnActionEvent e) { - String content = context.getContent(); - if (content.equals("test")) { - } - this.next(context, e); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/TextService.java b/athena-all/src/main/java/run/mone/m78/ip/service/TextService.java deleted file mode 100644 index b3be6808a..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/TextService.java +++ /dev/null @@ -1,56 +0,0 @@ -package run.mone.m78.ip.service; - -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiFile; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; - - -/** - * @author goodjava@qq.com - * @date 2023/5/17 15:46 - */ -@Slf4j -public class TextService { - - - public static void writeContent(Project project, String fileName, String moduleName, Runnable runnable) { - writeContent(project, fileName, moduleName, runnable, null); - } - - - public static String readContent(Project project, String module, String fileName) { - PsiDirectory directory = getPsiDirectory(project, module); - if (null == directory) { - return ""; - } - PsiFile file = directory.findFile(fileName); - if (null == file) { - return ""; - } - return file.getText(); - } - - - public static void writeContent(Project project, String fileName, String moduleName, Runnable runnable, String content) { - - } - - @NotNull - private static String getFileContent(String content) { - String fileContent = " "; - if (StringUtils.isNotEmpty(content)) { - fileContent = content; - } - return fileContent; - } - - - private static PsiDirectory getPsiDirectory(Project project, String moduleName) { - return null; - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/service/XmlService.java b/athena-all/src/main/java/run/mone/m78/ip/service/XmlService.java deleted file mode 100644 index c558a6fec..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/service/XmlService.java +++ /dev/null @@ -1,56 +0,0 @@ -package run.mone.m78.ip.service; - -import com.intellij.openapi.project.Project; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Writer; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Map; - -/** - * @author goodjava@qq.com - * @date 2023/5/21 22:07 - */ -public class XmlService { - - /** - * 方便操纵xml,这里的作用是修改maven 中的 pom 加入依赖 - * - * @param project - * @param moduleName - * @param dependency - */ - public static void openMavenPomAndModify(Project project, String moduleName, String dependency) { - - } - - public static Pair checkPomVersion(Project project, String groupId, String artifactId, String version) { - return null; - } - - @NotNull - private static Pair insertDependency(Project project, String groupId, String artifactId, String version, Map modulePathMap) throws IOException, XmlPullParserException { - return null; - } - - private static Pair writeDependency(Model model, File pomFile) { - return null; - } - - private static String buildDependencyString(String groupId, String artifactId, String version) { - return String.format("```\n" + - "\n" + - " \t%s\n" + - " \t%s\n" + - " \t%s\n" + - "", groupId, artifactId, version); - - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.form b/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.form deleted file mode 100644 index 19237e4c8..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.form +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.java b/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.java deleted file mode 100644 index 29998009a..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/TestUi.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.ui; - - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Style; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; -import java.awt.*; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; -import java.awt.event.*; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -public class TestUi extends JDialog { - private JPanel contentPane; - private JButton buttonOK; - private JButton buttonCancel; - private JTextPane textPane1; - private JButton button1; - - public TestUi() { - setContentPane(contentPane); - setModal(true); - getRootPane().setDefaultButton(buttonOK); - - buttonOK.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onOK(); - } - }); - - buttonCancel.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onCancel(); - } - }); - - // call onCancel() when cross is clicked - setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - onCancel(); - } - }); - - // call onCancel() on ESCAPE - contentPane.registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onCancel(); - } - }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - - init(); - button1.addActionListener(e -> { - JFileChooser jfc = new JFileChooser(); - jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); - jfc.showDialog(new JLabel(), "选择"); - File file = jfc.getSelectedFile(); - if (file.isDirectory()) { - System.out.println("文件夹:" + file.getAbsolutePath()); - } else if (file.isFile()) { - System.out.println("文件:" + file.getAbsolutePath()); - } - System.out.println(jfc.getSelectedFile().getName()); - URL url = uploadFile(bucketName, jfc.getSelectedFile()); - setClipboardString(url.toString()); - }); - } - - - public static void setClipboardString(String text) { - // 获取系统剪贴板 - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - // 封装文本内容 - Transferable trans = new StringSelection(text); - // 把文本内容设置到系统剪贴板 - clipboard.setContents(trans, null); - } - - - /** - * 从剪贴板中获取文本(粘贴) - */ - public static String getClipboardString() { - // 获取系统剪贴板 - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - - // 获取剪贴板中的内容 - Transferable trans = clipboard.getContents(null); - - if (trans != null) { - // 判断剪贴板中的内容是否支持文本 - if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) { - try { - // 获取剪贴板中的文本内容 - String text = (String) trans.getTransferData(DataFlavor.stringFlavor); - return text; - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - return null; - } - - - private void init() { - JTextPane textPane = textPane1; - textPane.setMaximumSize(new Dimension(100, 100)); - StyledDocument doc = (StyledDocument) textPane.getDocument(); - - Style style = doc.addStyle("StyleName", null); - try { - StyleConstants.setIcon(style, scaledImage("https://static.runoob.com/images/demo/demo1.jpg")); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - - try { - doc.insertString(doc.getLength(), "", style); - } catch (BadLocationException e) { - e.printStackTrace(); - } - - System.out.println(textPane1.getText()); - } - - - private ImageIcon scaledImage(String location) throws MalformedURLException { - Image image = Toolkit.getDefaultToolkit().getImage(new URL(location)); - image = image.getScaledInstance(120, 120, Image.SCALE_SMOOTH); - return new ImageIcon(image); - } - - private void onOK() { - - System.out.println(textPane1.getText()); -// fileMeta(); - -// getUrl(key); -// uploadFile(bucketName,new File("/Users/zhangzhiyong/Desktop/girl2.jpeg")); - listFile(); - } - - - String endpoint = "oss-cn-beijing.aliyuncs.com"; - String accessKeyId = ""; - String accessKeySecret = ""; - String bucketName = "datazzy"; - String key = "girl.jpeg"; - - public URL getUrl(String key) { - return null; - } - - - public void listFile() { - } - - - public URL uploadFile(String bucketName, File file) { - return null; - } - - - private void fileMeta() { - } - - - private void onCancel() { - // add your code here if necessary - dispose(); - } - - public static void main(String[] args) { - TestUi dialog = new TestUi(); - dialog.pack(); - dialog.setVisible(true); - System.exit(0); - } -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.form b/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.form deleted file mode 100644 index 42d80ecbf..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.form +++ /dev/null @@ -1,99 +0,0 @@ - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.java b/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.java deleted file mode 100644 index cf20e17b7..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/ui/UltramanUi.java +++ /dev/null @@ -1,68 +0,0 @@ -package run.mone.m78.ip.ui; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -public class UltramanUi extends JDialog { - - private JPanel contentPane; - private JButton buttonOK; - - private JPanel panel1; - private JLabel imageLabel; - private JLabel descLabel; - - - public UltramanUi() { - setContentPane(contentPane); - setModal(true); - getRootPane().setDefaultButton(buttonOK); - - buttonOK.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onOK(); - } - }); - - // call onCancel() when cross is clicked - setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - onOK(); - } - }); - - // call onCancel() on ESCAPE - contentPane.registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onOK(); - } - }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - - ImageIcon img = new ImageIcon("/tmp/a.jpeg"); - imageLabel.setIcon(img); - imageLabel.setText(""); - this.descLabel.setText("就算化成灰,我的bug也不会放过你;所以,请相信你自己,然后,也请给我发红包"); - - } - - private void onOK() { - // add your code here - dispose(); - } - - public static void main(String[] args) { - UltramanUi dialog = new UltramanUi(); - dialog.pack(); - dialog.setVisible(true); - System.exit(0); - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/EditorUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/EditorUtils.java deleted file mode 100644 index 99a4c6896..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/EditorUtils.java +++ /dev/null @@ -1,149 +0,0 @@ -package run.mone.m78.ip.util; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ScrollType; -import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.OpenFileDescriptor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.search.FilenameIndex; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.testFramework.LightVirtualFile; -import run.mone.m78.ip.common.Const; -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; - -/** - * @author goodjava@qq.com - * @date 2023/4/18 00:13 - */ -public class EditorUtils { - - public static void scroll(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - editor.getScrollingModel().scrollToCaret(ScrollType.CENTER_DOWN); // 翻到下一页 - } - - public static String getSelectContent(Editor editor) { - return getSelectContent(editor, true); - } - - public static String getSelectContent(Editor editor, boolean selectLine) { - try { - Document document = editor.getDocument(); - final SelectionModel selectionModel = editor.getSelectionModel(); - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - TextRange range = new TextRange(start, end); - String selectTxt = document.getText(range); - - //没有选中任何东西,则选中那一行 - if (StringUtils.isEmpty(selectTxt) && selectLine) { - selectionModel.selectLineAtCaret(); - final int start1 = selectionModel.getSelectionStart(); - final int end1 = selectionModel.getSelectionEnd(); - TextRange range1 = new TextRange(start1, end1); - selectTxt = document.getText(range1); - if (null != selectTxt) { - selectTxt = selectTxt.trim(); - } - } - return selectTxt; - } catch (Throwable ignore) { - return ""; - } - } - - public static Editor getEditorFromPsiClass(Project project, PsiClass psiClass) { - PsiFile psiFile = psiClass.getContainingFile(); - if (psiFile != null) { - String fileName = psiFile.getName(); - PsiFile[] files = FilenameIndex.getFilesByName(project, fileName, GlobalSearchScope.allScope(project)); - for (PsiFile file : files) { - VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - return fileEditorManager.openTextEditor(new OpenFileDescriptor(project, virtualFile), true); - } - } - } - return null; - } - - /** - * 移动到最后一个方法的最后部 - * - * @param psiClass - * @param editor - */ - public static void moveToLastMethodEnd(PsiClass psiClass, Editor editor) { - PsiMethod @NotNull [] methods = psiClass.getMethods(); - int offset = 0; - if (methods.length == 0) { - offset = psiClass.getTextRange().getEndOffset() - 1; - } else { - PsiMethod psiMethod = methods[methods.length - 1]; - offset = psiMethod.getTextRange().getEndOffset(); - } - editor.getCaretModel().moveToOffset(offset); - } - - public static void closeEditor(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - if (null != editor) { - FileEditorManager manager = FileEditorManager.getInstance(project); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - manager.closeFile(psiFile.getVirtualFile()); - } - } - - public static void openEditor(Project project, String content, String name) { - VirtualFile virtualFile = new LightVirtualFile(name, content); - virtualFile.putUserData(Const.T_KEY, name); - ApplicationManager.getApplication().runWriteAction((Computable) () -> { - Document document = FileDocumentManager.getInstance().getDocument(virtualFile); - if (document != null) { - document.setText(content); - } - return FileEditorManager.getInstance(project).openFile(virtualFile, true); - }); - } - - public static Editor getEditor(Project project) { - Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - return editor; - } - - - /** - * 获取或打开指定名称和内容的编辑器。 - * 如果已经存在打开的编辑器,则返回该编辑器,否则打开一个新的编辑器。 - * 如果打开的文件扩展名为"md",则返回该编辑器。 - * - * @param project 项目对象 - * @param name 文件名称 - * @param content 文件内容 - * @return 编辑器对象 - */ - public static Editor getOrOpenEditor(Project project, String name, String content) { - Editor editor = getEditor(project); - if (null == editor || !FileDocumentManager.getInstance().getFile(editor.getDocument()).equals("md")) { - openEditor(project, content, name); - } else { - return editor; - } - return getEditor(project); - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/GitUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/GitUtils.java deleted file mode 100644 index a3e304c15..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/GitUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package run.mone.m78.ip.util; - -import com.google.common.base.Joiner; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import lombok.SneakyThrows; - -import java.io.BufferedReader; -import java.io.File; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author goodjava@qq.com - * @date 2023/7/8 23:19 - */ -public class GitUtils { - - - /** - * 获取项目中受影响的文件名列表。 - * - * @param project 项目对象 - * @return 受影响的文件名列表 - */ - public static List getAffectedFileNames(Project project) { - ChangeListManager changeListManager = ChangeListManager.getInstance(project); - return changeListManager.getAffectedFiles().stream().map(it -> it.toString()).collect(Collectors.toList()); - } - - public static String getAffectedFileNamesStr(Project project) { - ChangeListManager changeListManager = ChangeListManager.getInstance(project); - List list = changeListManager.getAffectedFiles().stream().map(it -> it.toString()).collect(Collectors.toList()); - return list.stream().collect(Collectors.joining("\n")); - } - - - //获取git地址 - @SneakyThrows - public static String getGitAddress(Project project) { - return null; - } - - //获取最后一条commit记录 - @SneakyThrows - public static List getLastCommit(Project project) { - return null; - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/ImportUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/ImportUtils.java deleted file mode 100644 index a2cb51720..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/ImportUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -package run.mone.m78.ip.util; - -import com.google.common.base.Splitter; -import com.intellij.codeInsight.actions.OptimizeImportsAction; -import com.intellij.codeInspection.unusedImport.UnusedImportInspection; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.impl.source.PsiJavaFileImpl; -import com.intellij.psi.util.PsiTreeUtil; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author goodjava@qq.com - * @date 2023/6/22 21:41 - */ -@Slf4j -public abstract class ImportUtils { - - public static void removeInvalidImports(Project project, Editor editor) { - } - - public static void optimizeImports(Project project, Editor editor) { - - } - - - public static void addImport(Project project, Editor editor, List importStrList) { - - } - - public static PsiClass createPsiClass(PsiElementFactory factory, String className) { - return null; - } - - - public static String junitVersion(PsiClass psiClass) { - return ""; - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/PromptUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/PromptUtils.java deleted file mode 100644 index e25a9fa58..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/PromptUtils.java +++ /dev/null @@ -1,257 +0,0 @@ -package run.mone.m78.ip.util; - -import com.google.common.collect.Maps; -import com.google.gson.Gson; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiClass; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.dialog.DialogResult; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.bo.CreateClassMeta; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.dialog.ChromeDialog; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.net.URLEncoder; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author goodjava@qq.com - * @date 2023/5/29 10:09 - */ -@Slf4j -public class PromptUtils { - - - private static final Gson gson = new Gson(); - - - public static Map getParamsFromAiProxy(String promptName, String metaStr) { - return getParamsFromAiProxy(promptName, metaStr, false); - } - - public static Map getParamsFromAiProxy(String promptName, String metaStr, boolean useSelect) { - return Maps.newHashMap(); - } - - - /** - * 创建类(class enum) - * - * @param project - * @param modelName - * @param promptName - */ - public static void createClass(Project project, final String modelName, String promptName) { - - } - - private static String getModelName(String modelName, Map values) { - if (StringUtils.isEmpty(modelName)) { - modelName = values.getOrDefault("module", "").toString(); - } - return modelName; - } - - @Nullable - private static String[] getParams(CreateClassMeta createClassMeta, Editor editor) { - String[] params = null; - if (ObjectUtils.notEqual(null, createClassMeta) && createClassMeta.isUseSelect()) { - params = new String[]{EditorUtils.getSelectContent(editor)}; - } - return params; - } - - - public static void createClass2(Project project, String promptName, String showDialog, Map param) { - String isShowDialog = StringUtils.isEmpty(showDialog) ? "true" : showDialog; - PromptInfo promptInfo = Prompt.getPromptInfo(promptName); - Map v = getParamsFromAiProxy(promptName, promptInfo.getMeta()); - if ("true".equals(isShowDialog)) { - String url = buildDialogUrl(project, v, promptInfo); - ChromeDialog chromeDialog = new ChromeDialog(url, project); - chromeDialog.show(); - return; - } - - String packageStr = param.get("package").toString(); - String className = param.get("class").toString(); - String modelName = param.get("modelName").toString(); - - CodeService.createEmptyClass(project, modelName, packageStr, className); - - PsiClass psiClass = CodeService.getPsiClass2(project); - TextRange textRange = psiClass.getTextRange(); - CodeService.deleteTextRange(project, psiClass.getTextRange()); - Editor codeEditor = CodeService.getEditor(project); - codeEditor.getCaretModel().moveToOffset(textRange.getStartOffset()); - - Map pm = param.entrySet().stream().collect(Collectors.toMap(en -> en.getKey(), en -> en.getValue().toString())); - CodeService.generateCodeWithAi3(project, promptName, new String[]{}, pm, (p, code) -> CodeService.writeCode2(p, codeEditor, code)); - - } - - - /** - * $$->隐藏 - * $@$->选择框 - * - * @param project - * @param param - * @param promptInfo - * @return - */ - private static String buildDialogUrl(Project project, Map param, PromptInfo promptInfo) { - if (!param.containsKey("model")) { - param.put("$@$model", ProjectUtils.listAllModules(project)); - } - if (!param.containsKey("package")) { - param.put("package", ""); - } - if (param.containsKey("class")) { - param.put("class", ""); - } - param.put("$$showDialog", "false"); - param.put("$$prompt", promptInfo.getPromptName()); - param.put("$$desc", promptInfo.getDesc()); - return ConfigUtils.getConfig().getChatServer() + "/code-form" + "?param=" + URLEncoder.encode(gson.toJson(param)); - } - - /** - * 给方法添加注释 - * - * @param req - */ - public static void addComment(GenerateCodeReq req) { - - } - - - /** - * 修改class - * - * @param project - * @param promptName - */ - public static void modifyClass(Project project, String promptName) { - PsiClass psiClass = CodeService.getPsiClass2(project); - String codeStr = psiClass.getText(); - CodeService.deletePsiClass(project, psiClass); - Editor codeEditor = CodeService.getEditor(project); - CodeService.generateCodeWithAi2(project, promptName, new String[]{codeStr}, (p, code) -> CodeService.writeCode2(p, codeEditor, code)); - } - - - /** - * 创建一个文件 - * - * @param req - */ - public static void createFile(String promptName, String fileName, GenerateCodeReq req) { - - } - - /** - * @param req - */ - public static void updateClass(GenerateCodeReq req) { - PsiClass psiClass = CodeService.getPsiClass(req.getProject()); - String classCode = psiClass.getText(); - TextRange textRange = psiClass.getTextRange(); - CodeService.deleteTextRange(req.getProject(), textRange); - Editor editor = CodeService.getEditor(req.getProject()); - CodeService.generateCodeWithAi2(req.getProject(), req.getPromptName(), new String[]{classCode}, (p, code) -> CodeService.writeCode2(p, editor, code)); - } - - /** - * 更新方法 - * - * @param req - */ - public static void updateMethod(GenerateCodeReq req) { - - } - - /** - * 给一个方法添加逐行注释,或者代码 - * - * @param promptName - * @param req - */ - public static void lineByLineCommentOrCode(String promptName, GenerateCodeReq req) { - - } - - private static String filterAnnoCode(String codeStr, PromptInfo promptInfo) { - return codeStr; - } - - private static void addImportList(Project project, Map map) { - - } - - public static List getImportList(PromptInfo promptInfo) { - return null; - } - - /** - * @param req - * @param map - * @return - */ - @NotNull - private static String getCode(GenerateCodeReq req, Map map) { - return ""; - } - - @NotNull - private static String getScope(GenerateCodeReq req, Map map) { - return ""; - } - - - private static Pair getPackageAndClass(DialogResult result) { - return null; - } - - private static DialogResult showDialog(Project project, Module module, String data) { - return null; - } - - /** - * 生成接口 - * - * @param req - */ - public static void generateInterface(GenerateCodeReq req) { - - - } - - /** - * 用来生成测试方法 - */ - public static void select(GenerateCodeReq req, Project project, Module module, PromptInfo promptInfo) { - - } - - public static void checkPomVersion(GenerateCodeReq req) { - } - - public static void generateAnnoForBootStrap(String promptName, Project project) { - - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/TerminalUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/TerminalUtils.java deleted file mode 100644 index 88701e92f..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/TerminalUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.util; - -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessAdapter; -import com.intellij.execution.process.ProcessEvent; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowAnchor; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.openapi.wm.ex.ToolWindowManagerEx; -import com.intellij.terminal.JBTerminalPanel; -import com.jediterm.terminal.TerminalOutputStream; -import lombok.SneakyThrows; - -import javax.swing.*; -import java.util.concurrent.TimeUnit; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/7 11:21 - */ -public class TerminalUtils { - - @SneakyThrows - public static void show(Project project) { - ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); - ToolWindow terminal = toolWindowManager.getToolWindow("Terminal"); - if (terminal != null) { - terminal.show(null); - if (!terminal.isActive()) { - TimeUnit.SECONDS.sleep(1); - } - } - } - - - public static void send(Project project, String message) { - - } - - public static ToolWindow getTerminalToolWindow(Project project) { - return null; - } - - - public static void runCommandOnTerminal(Project project, String command) { - - - } - - - private static Object getPannel(Object root) { - if (root instanceof JBTerminalPanel) { - return root; - } - if (root instanceof JPanel) { - return getPannel(((JPanel) root).getComponent(0)); - } - if (root instanceof JLayeredPane) { - return getPannel(((JLayeredPane) root).getComponent(0)); - } - return null; - } - - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/util/TestUtils.java b/athena-all/src/main/java/run/mone/m78/ip/util/TestUtils.java deleted file mode 100644 index 17010eea2..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/util/TestUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -package run.mone.m78.ip.util; - -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * @author goodjava@qq.com - * @date 2023/8/11 09:46 - */ -public class TestUtils { - - - public static List junitImportList = Lists.newArrayList("import org.junit.Test", "import org.junit.Assert"); - - public static List jupiterImportList = Lists.newArrayList("import org.junit.jupiter.api.Test", "import static org.junit.jupiter.api.Assertions.assertEquals", "import static org.junit.jupiter.api.Assertions.assertNotNull"); - - - public static boolean isJupiter() { - if (isClassPresent("org.junit.Test")) { - return false; - } else if (isClassPresent("org.junit.jupiter.api.Test")) { - return true; - } else { - return false; - } - } - - public static List getImportList(String version) { - if (version.equals("unknow")) { - return Lists.newArrayList(); - } - if (version.equals("junit")) { - return junitImportList; - } - if (version.equals("jupiter")) { - return junitImportList; - } - return Lists.newArrayList(); - } - - - private static boolean isClassPresent(String className) { - try { - Class.forName(className); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - -} diff --git a/athena-all/src/main/java/run/mone/m78/ip/window/UltramanWindowFactory.java b/athena-all/src/main/java/run/mone/m78/ip/window/UltramanWindowFactory.java deleted file mode 100644 index cc72bfb50..000000000 --- a/athena-all/src/main/java/run/mone/m78/ip/window/UltramanWindowFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2020 Xiaomi - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 run.mone.m78.ip.window; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; -import run.mone.m78.ip.ui.UltramanTreeUi; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -/** - * @Author goodjava@qq.com - * @Date 2021/11/8 20:55 - */ -public class UltramanWindowFactory implements ToolWindowFactory { - - @Override - public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { - ContentFactory contentFactory = ContentFactory.getInstance(); - JPanel pannel = new UltramanTreeUi(project).jpanel(); - Content content = contentFactory.createContent(pannel, "", false); - toolWindow.getContentManager().addContent(content); - - } -} diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/CommonUtils.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/CommonUtils.java deleted file mode 100644 index 08671b6db..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/CommonUtils.java +++ /dev/null @@ -1,19 +0,0 @@ -package run.mone.mone.ultraman.grpc; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author goodjava@qq.com - * @date 2023/8/1 15:10 - */ -public class CommonUtils { - - - //ai:给你两个List,帮我计算交集 - public List getIntersection(List list1, List list2) { - return list1.stream().filter(list2::contains).collect(Collectors.toList()); - } - - -} diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/Service.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/Service.java deleted file mode 100644 index c9e9c2279..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/Service.java +++ /dev/null @@ -1,87 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: service.proto - -package run.mone.mone.ultraman.grpc; - -public final class Service { - private Service() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); - } - static final com.google.protobuf.Descriptors.Descriptor - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor; - static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_descriptor; - static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor; - static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_descriptor; - static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - String[] descriptorData = { - - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor, - new String[] { "Id", "Cmd", "Params", "ParamMap", }); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_descriptor = - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor.getNestedTypes().get(0); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_descriptor, - new String[] { "Key", "Value", }); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor, - new String[] { "Id", "Data", "Code", "Cmd", "ResMap", }); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_descriptor = - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor.getNestedTypes().get(0); - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_descriptor, - new String[] { "Key", "Value", }); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequest.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequest.java deleted file mode 100644 index 83bff749e..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequest.java +++ /dev/null @@ -1,1073 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: service.proto - -package run.mone.mone.ultraman.grpc; - -/** - * Protobuf type {@code com.xiaomi.mone.ultraman.grpc.UltramanRequest} - */ -public final class UltramanRequest extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:com.xiaomi.mone.ultraman.grpc.UltramanRequest) - UltramanRequestOrBuilder { -private static final long serialVersionUID = 0L; - // Use UltramanRequest.newBuilder() to construct. - private UltramanRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - private UltramanRequest() { - id_ = ""; - cmd_ = ""; - params_ = ""; - } - - @Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private UltramanRequest( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - if (extensionRegistry == null) { - throw new NullPointerException(); - } - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - String s = input.readStringRequireUtf8(); - - id_ = s; - break; - } - case 18: { - String s = input.readStringRequireUtf8(); - - cmd_ = s; - break; - } - case 26: { - String s = input.readStringRequireUtf8(); - - params_ = s; - break; - } - case 34: { - if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { - paramMap_ = com.google.protobuf.MapField.newMapField( - ParamMapDefaultEntryHolder.defaultEntry); - mutable_bitField0_ |= 0x00000008; - } - com.google.protobuf.MapEntry - paramMap__ = input.readMessage( - ParamMapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - paramMap_.getMutableMap().put( - paramMap__.getKey(), paramMap__.getValue()); - break; - } - default: { - if (!parseUnknownFieldProto3( - input, unknownFields, extensionRegistry, tag)) { - done = true; - } - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @Override - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 4: - return internalGetParamMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - UltramanRequest.class, Builder.class); - } - - private int bitField0_; - public static final int ID_FIELD_NUMBER = 1; - private volatile Object id_; - /** - * string id = 1; - */ - public String getId() { - Object ref = id_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - * string id = 1; - */ - public com.google.protobuf.ByteString - getIdBytes() { - Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CMD_FIELD_NUMBER = 2; - private volatile Object cmd_; - /** - * string cmd = 2; - */ - public String getCmd() { - Object ref = cmd_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - cmd_ = s; - return s; - } - } - /** - * string cmd = 2; - */ - public com.google.protobuf.ByteString - getCmdBytes() { - Object ref = cmd_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - cmd_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PARAMS_FIELD_NUMBER = 3; - private volatile Object params_; - /** - * string params = 3; - */ - public String getParams() { - Object ref = params_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - params_ = s; - return s; - } - } - /** - * string params = 3; - */ - public com.google.protobuf.ByteString - getParamsBytes() { - Object ref = params_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - params_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PARAMMAP_FIELD_NUMBER = 4; - private static final class ParamMapDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - String, String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_ParamMapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - private com.google.protobuf.MapField< - String, String> paramMap_; - private com.google.protobuf.MapField - internalGetParamMap() { - if (paramMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ParamMapDefaultEntryHolder.defaultEntry); - } - return paramMap_; - } - - public int getParamMapCount() { - return internalGetParamMap().getMap().size(); - } - /** - * map<string, string> paramMap = 4; - */ - - public boolean containsParamMap( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetParamMap().getMap().containsKey(key); - } - /** - * Use {@link #getParamMapMap()} instead. - */ - @Deprecated - public java.util.Map getParamMap() { - return getParamMapMap(); - } - /** - * map<string, string> paramMap = 4; - */ - - public java.util.Map getParamMapMap() { - return internalGetParamMap().getMap(); - } - /** - * map<string, string> paramMap = 4; - */ - - public String getParamMapOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetParamMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> paramMap = 4; - */ - - public String getParamMapOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetParamMap().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!getIdBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_); - } - if (!getCmdBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 2, cmd_); - } - if (!getParamsBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 3, params_); - } - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetParamMap(), - ParamMapDefaultEntryHolder.defaultEntry, - 4); - unknownFields.writeTo(output); - } - - @Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!getIdBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_); - } - if (!getCmdBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, cmd_); - } - if (!getParamsBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, params_); - } - for (java.util.Map.Entry entry - : internalGetParamMap().getMap().entrySet()) { - com.google.protobuf.MapEntry - paramMap__ = ParamMapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, paramMap__); - } - size += unknownFields.getSerializedSize(); - memoizedSize = size; - return size; - } - - @Override - public boolean equals(final Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof UltramanRequest)) { - return super.equals(obj); - } - UltramanRequest other = (UltramanRequest) obj; - - boolean result = true; - result = result && getId() - .equals(other.getId()); - result = result && getCmd() - .equals(other.getCmd()); - result = result && getParams() - .equals(other.getParams()); - result = result && internalGetParamMap().equals( - other.internalGetParamMap()); - result = result && unknownFields.equals(other.unknownFields); - return result; - } - - @Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + CMD_FIELD_NUMBER; - hash = (53 * hash) + getCmd().hashCode(); - hash = (37 * hash) + PARAMS_FIELD_NUMBER; - hash = (53 * hash) + getParams().hashCode(); - if (!internalGetParamMap().getMap().isEmpty()) { - hash = (37 * hash) + PARAMMAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetParamMap().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static UltramanRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static UltramanRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - public static UltramanRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - public static UltramanRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static UltramanRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static UltramanRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(UltramanRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @Override - protected Builder newBuilderForType( - BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code com.xiaomi.mone.ultraman.grpc.UltramanRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:com.xiaomi.mone.ultraman.grpc.UltramanRequest) - UltramanRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 4: - return internalGetParamMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMutableMapField( - int number) { - switch (number) { - case 4: - return internalGetMutableParamMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - UltramanRequest.class, Builder.class); - } - - // Construct using com.xiaomi.mone.ultraman.grpc.UltramanRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } - } - @Override - public Builder clear() { - super.clear(); - id_ = ""; - - cmd_ = ""; - - params_ = ""; - - internalGetMutableParamMap().clear(); - return this; - } - - @Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanRequest_descriptor; - } - - @Override - public UltramanRequest getDefaultInstanceForType() { - return UltramanRequest.getDefaultInstance(); - } - - @Override - public UltramanRequest build() { - UltramanRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @Override - public UltramanRequest buildPartial() { - UltramanRequest result = new UltramanRequest(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - result.id_ = id_; - result.cmd_ = cmd_; - result.params_ = params_; - result.paramMap_ = internalGetParamMap(); - result.paramMap_.makeImmutable(); - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - @Override - public Builder clone() { - return (Builder) super.clone(); - } - @Override - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); - } - @Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - @Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - @Override - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - @Override - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); - } - @Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof UltramanRequest) { - return mergeFrom((UltramanRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(UltramanRequest other) { - if (other == UltramanRequest.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - onChanged(); - } - if (!other.getCmd().isEmpty()) { - cmd_ = other.cmd_; - onChanged(); - } - if (!other.getParams().isEmpty()) { - params_ = other.params_; - onChanged(); - } - internalGetMutableParamMap().mergeFrom( - other.internalGetParamMap()); - this.mergeUnknownFields(other.unknownFields); - onChanged(); - return this; - } - - @Override - public final boolean isInitialized() { - return true; - } - - @Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - UltramanRequest parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (UltramanRequest) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - private Object id_ = ""; - /** - * string id = 1; - */ - public String getId() { - Object ref = id_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string id = 1; - */ - public com.google.protobuf.ByteString - getIdBytes() { - Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string id = 1; - */ - public Builder setId( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - id_ = value; - onChanged(); - return this; - } - /** - * string id = 1; - */ - public Builder clearId() { - - id_ = getDefaultInstance().getId(); - onChanged(); - return this; - } - /** - * string id = 1; - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - id_ = value; - onChanged(); - return this; - } - - private Object cmd_ = ""; - /** - * string cmd = 2; - */ - public String getCmd() { - Object ref = cmd_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - cmd_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string cmd = 2; - */ - public com.google.protobuf.ByteString - getCmdBytes() { - Object ref = cmd_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - cmd_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string cmd = 2; - */ - public Builder setCmd( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - cmd_ = value; - onChanged(); - return this; - } - /** - * string cmd = 2; - */ - public Builder clearCmd() { - - cmd_ = getDefaultInstance().getCmd(); - onChanged(); - return this; - } - /** - * string cmd = 2; - */ - public Builder setCmdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - cmd_ = value; - onChanged(); - return this; - } - - private Object params_ = ""; - /** - * string params = 3; - */ - public String getParams() { - Object ref = params_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - params_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string params = 3; - */ - public com.google.protobuf.ByteString - getParamsBytes() { - Object ref = params_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - params_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string params = 3; - */ - public Builder setParams( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - params_ = value; - onChanged(); - return this; - } - /** - * string params = 3; - */ - public Builder clearParams() { - - params_ = getDefaultInstance().getParams(); - onChanged(); - return this; - } - /** - * string params = 3; - */ - public Builder setParamsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - params_ = value; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - String, String> paramMap_; - private com.google.protobuf.MapField - internalGetParamMap() { - if (paramMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ParamMapDefaultEntryHolder.defaultEntry); - } - return paramMap_; - } - private com.google.protobuf.MapField - internalGetMutableParamMap() { - onChanged();; - if (paramMap_ == null) { - paramMap_ = com.google.protobuf.MapField.newMapField( - ParamMapDefaultEntryHolder.defaultEntry); - } - if (!paramMap_.isMutable()) { - paramMap_ = paramMap_.copy(); - } - return paramMap_; - } - - public int getParamMapCount() { - return internalGetParamMap().getMap().size(); - } - /** - * map<string, string> paramMap = 4; - */ - - public boolean containsParamMap( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetParamMap().getMap().containsKey(key); - } - /** - * Use {@link #getParamMapMap()} instead. - */ - @Deprecated - public java.util.Map getParamMap() { - return getParamMapMap(); - } - /** - * map<string, string> paramMap = 4; - */ - - public java.util.Map getParamMapMap() { - return internalGetParamMap().getMap(); - } - /** - * map<string, string> paramMap = 4; - */ - - public String getParamMapOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetParamMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> paramMap = 4; - */ - - public String getParamMapOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetParamMap().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearParamMap() { - internalGetMutableParamMap().getMutableMap() - .clear(); - return this; - } - /** - * map<string, string> paramMap = 4; - */ - - public Builder removeParamMap( - String key) { - if (key == null) { throw new NullPointerException(); } - internalGetMutableParamMap().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @Deprecated - public java.util.Map - getMutableParamMap() { - return internalGetMutableParamMap().getMutableMap(); - } - /** - * map<string, string> paramMap = 4; - */ - public Builder putParamMap( - String key, - String value) { - if (key == null) { throw new NullPointerException(); } - if (value == null) { throw new NullPointerException(); } - internalGetMutableParamMap().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, string> paramMap = 4; - */ - - public Builder putAllParamMap( - java.util.Map values) { - internalGetMutableParamMap().getMutableMap() - .putAll(values); - return this; - } - @Override - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.setUnknownFieldsProto3(unknownFields); - } - - @Override - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.mergeUnknownFields(unknownFields); - } - - - // @@protoc_insertion_point(builder_scope:com.xiaomi.mone.ultraman.grpc.UltramanRequest) - } - - // @@protoc_insertion_point(class_scope:com.xiaomi.mone.ultraman.grpc.UltramanRequest) - private static final UltramanRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new UltramanRequest(); - } - - public static UltramanRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @Override - public UltramanRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new UltramanRequest(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @Override - public UltramanRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequestOrBuilder.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequestOrBuilder.java deleted file mode 100644 index 521ac7441..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanRequestOrBuilder.java +++ /dev/null @@ -1,73 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: service.proto - -package run.mone.mone.ultraman.grpc; - -public interface UltramanRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:com.xiaomi.mone.ultraman.grpc.UltramanRequest) - com.google.protobuf.MessageOrBuilder { - - /** - * string id = 1; - */ - String getId(); - /** - * string id = 1; - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - * string cmd = 2; - */ - String getCmd(); - /** - * string cmd = 2; - */ - com.google.protobuf.ByteString - getCmdBytes(); - - /** - * string params = 3; - */ - String getParams(); - /** - * string params = 3; - */ - com.google.protobuf.ByteString - getParamsBytes(); - - /** - * map<string, string> paramMap = 4; - */ - int getParamMapCount(); - /** - * map<string, string> paramMap = 4; - */ - boolean containsParamMap( - String key); - /** - * Use {@link #getParamMapMap()} instead. - */ - @Deprecated - java.util.Map - getParamMap(); - /** - * map<string, string> paramMap = 4; - */ - java.util.Map - getParamMapMap(); - /** - * map<string, string> paramMap = 4; - */ - - String getParamMapOrDefault( - String key, - String defaultValue); - /** - * map<string, string> paramMap = 4; - */ - - String getParamMapOrThrow( - String key); -} diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponse.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponse.java deleted file mode 100644 index 003facbf1..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponse.java +++ /dev/null @@ -1,1131 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: service.proto - -package run.mone.mone.ultraman.grpc; - -/** - * Protobuf type {@code com.xiaomi.mone.ultraman.grpc.UltramanResponse} - */ -public final class UltramanResponse extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:com.xiaomi.mone.ultraman.grpc.UltramanResponse) - UltramanResponseOrBuilder { -private static final long serialVersionUID = 0L; - // Use UltramanResponse.newBuilder() to construct. - private UltramanResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - private UltramanResponse() { - id_ = ""; - data_ = ""; - code_ = 0; - cmd_ = ""; - } - - @Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private UltramanResponse( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - if (extensionRegistry == null) { - throw new NullPointerException(); - } - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - String s = input.readStringRequireUtf8(); - - id_ = s; - break; - } - case 18: { - String s = input.readStringRequireUtf8(); - - data_ = s; - break; - } - case 24: { - - code_ = input.readInt32(); - break; - } - case 34: { - String s = input.readStringRequireUtf8(); - - cmd_ = s; - break; - } - case 42: { - if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { - resMap_ = com.google.protobuf.MapField.newMapField( - ResMapDefaultEntryHolder.defaultEntry); - mutable_bitField0_ |= 0x00000010; - } - com.google.protobuf.MapEntry - resMap__ = input.readMessage( - ResMapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - resMap_.getMutableMap().put( - resMap__.getKey(), resMap__.getValue()); - break; - } - default: { - if (!parseUnknownFieldProto3( - input, unknownFields, extensionRegistry, tag)) { - done = true; - } - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @Override - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 5: - return internalGetResMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - UltramanResponse.class, Builder.class); - } - - private int bitField0_; - public static final int ID_FIELD_NUMBER = 1; - private volatile Object id_; - /** - * string id = 1; - */ - public String getId() { - Object ref = id_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - * string id = 1; - */ - public com.google.protobuf.ByteString - getIdBytes() { - Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DATA_FIELD_NUMBER = 2; - private volatile Object data_; - /** - * string data = 2; - */ - public String getData() { - Object ref = data_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - data_ = s; - return s; - } - } - /** - * string data = 2; - */ - public com.google.protobuf.ByteString - getDataBytes() { - Object ref = data_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - data_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CODE_FIELD_NUMBER = 3; - private int code_; - /** - * int32 code = 3; - */ - public int getCode() { - return code_; - } - - public static final int CMD_FIELD_NUMBER = 4; - private volatile Object cmd_; - /** - * string cmd = 4; - */ - public String getCmd() { - Object ref = cmd_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - cmd_ = s; - return s; - } - } - /** - * string cmd = 4; - */ - public com.google.protobuf.ByteString - getCmdBytes() { - Object ref = cmd_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - cmd_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int RESMAP_FIELD_NUMBER = 5; - private static final class ResMapDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - String, String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_ResMapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - private com.google.protobuf.MapField< - String, String> resMap_; - private com.google.protobuf.MapField - internalGetResMap() { - if (resMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ResMapDefaultEntryHolder.defaultEntry); - } - return resMap_; - } - - public int getResMapCount() { - return internalGetResMap().getMap().size(); - } - /** - * map<string, string> resMap = 5; - */ - - public boolean containsResMap( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetResMap().getMap().containsKey(key); - } - /** - * Use {@link #getResMapMap()} instead. - */ - @Deprecated - public java.util.Map getResMap() { - return getResMapMap(); - } - /** - * map<string, string> resMap = 5; - */ - - public java.util.Map getResMapMap() { - return internalGetResMap().getMap(); - } - /** - * map<string, string> resMap = 5; - */ - - public String getResMapOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetResMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> resMap = 5; - */ - - public String getResMapOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetResMap().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!getIdBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_); - } - if (!getDataBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 2, data_); - } - if (code_ != 0) { - output.writeInt32(3, code_); - } - if (!getCmdBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 4, cmd_); - } - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetResMap(), - ResMapDefaultEntryHolder.defaultEntry, - 5); - unknownFields.writeTo(output); - } - - @Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!getIdBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_); - } - if (!getDataBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, data_); - } - if (code_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, code_); - } - if (!getCmdBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, cmd_); - } - for (java.util.Map.Entry entry - : internalGetResMap().getMap().entrySet()) { - com.google.protobuf.MapEntry - resMap__ = ResMapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, resMap__); - } - size += unknownFields.getSerializedSize(); - memoizedSize = size; - return size; - } - - @Override - public boolean equals(final Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof UltramanResponse)) { - return super.equals(obj); - } - UltramanResponse other = (UltramanResponse) obj; - - boolean result = true; - result = result && getId() - .equals(other.getId()); - result = result && getData() - .equals(other.getData()); - result = result && (getCode() - == other.getCode()); - result = result && getCmd() - .equals(other.getCmd()); - result = result && internalGetResMap().equals( - other.internalGetResMap()); - result = result && unknownFields.equals(other.unknownFields); - return result; - } - - @Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + DATA_FIELD_NUMBER; - hash = (53 * hash) + getData().hashCode(); - hash = (37 * hash) + CODE_FIELD_NUMBER; - hash = (53 * hash) + getCode(); - hash = (37 * hash) + CMD_FIELD_NUMBER; - hash = (53 * hash) + getCmd().hashCode(); - if (!internalGetResMap().getMap().isEmpty()) { - hash = (37 * hash) + RESMAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetResMap().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static UltramanResponse parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanResponse parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanResponse parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanResponse parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanResponse parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static UltramanResponse parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static UltramanResponse parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static UltramanResponse parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - public static UltramanResponse parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - public static UltramanResponse parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static UltramanResponse parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static UltramanResponse parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(UltramanResponse prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @Override - protected Builder newBuilderForType( - BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code com.xiaomi.mone.ultraman.grpc.UltramanResponse} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:com.xiaomi.mone.ultraman.grpc.UltramanResponse) - UltramanResponseOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 5: - return internalGetResMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMutableMapField( - int number) { - switch (number) { - case 5: - return internalGetMutableResMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - UltramanResponse.class, Builder.class); - } - - // Construct using com.xiaomi.mone.ultraman.grpc.UltramanResponse.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } - } - @Override - public Builder clear() { - super.clear(); - id_ = ""; - - data_ = ""; - - code_ = 0; - - cmd_ = ""; - - internalGetMutableResMap().clear(); - return this; - } - - @Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return Service.internal_static_com_xiaomi_mone_ultraman_grpc_UltramanResponse_descriptor; - } - - @Override - public UltramanResponse getDefaultInstanceForType() { - return UltramanResponse.getDefaultInstance(); - } - - @Override - public UltramanResponse build() { - UltramanResponse result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @Override - public UltramanResponse buildPartial() { - UltramanResponse result = new UltramanResponse(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - result.id_ = id_; - result.data_ = data_; - result.code_ = code_; - result.cmd_ = cmd_; - result.resMap_ = internalGetResMap(); - result.resMap_.makeImmutable(); - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - @Override - public Builder clone() { - return (Builder) super.clone(); - } - @Override - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); - } - @Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - @Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - @Override - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - @Override - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); - } - @Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof UltramanResponse) { - return mergeFrom((UltramanResponse)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(UltramanResponse other) { - if (other == UltramanResponse.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - onChanged(); - } - if (!other.getData().isEmpty()) { - data_ = other.data_; - onChanged(); - } - if (other.getCode() != 0) { - setCode(other.getCode()); - } - if (!other.getCmd().isEmpty()) { - cmd_ = other.cmd_; - onChanged(); - } - internalGetMutableResMap().mergeFrom( - other.internalGetResMap()); - this.mergeUnknownFields(other.unknownFields); - onChanged(); - return this; - } - - @Override - public final boolean isInitialized() { - return true; - } - - @Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - UltramanResponse parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (UltramanResponse) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - private Object id_ = ""; - /** - * string id = 1; - */ - public String getId() { - Object ref = id_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string id = 1; - */ - public com.google.protobuf.ByteString - getIdBytes() { - Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string id = 1; - */ - public Builder setId( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - id_ = value; - onChanged(); - return this; - } - /** - * string id = 1; - */ - public Builder clearId() { - - id_ = getDefaultInstance().getId(); - onChanged(); - return this; - } - /** - * string id = 1; - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - id_ = value; - onChanged(); - return this; - } - - private Object data_ = ""; - /** - * string data = 2; - */ - public String getData() { - Object ref = data_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - data_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string data = 2; - */ - public com.google.protobuf.ByteString - getDataBytes() { - Object ref = data_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - data_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string data = 2; - */ - public Builder setData( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - data_ = value; - onChanged(); - return this; - } - /** - * string data = 2; - */ - public Builder clearData() { - - data_ = getDefaultInstance().getData(); - onChanged(); - return this; - } - /** - * string data = 2; - */ - public Builder setDataBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - data_ = value; - onChanged(); - return this; - } - - private int code_ ; - /** - * int32 code = 3; - */ - public int getCode() { - return code_; - } - /** - * int32 code = 3; - */ - public Builder setCode(int value) { - - code_ = value; - onChanged(); - return this; - } - /** - * int32 code = 3; - */ - public Builder clearCode() { - - code_ = 0; - onChanged(); - return this; - } - - private Object cmd_ = ""; - /** - * string cmd = 4; - */ - public String getCmd() { - Object ref = cmd_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - cmd_ = s; - return s; - } else { - return (String) ref; - } - } - /** - * string cmd = 4; - */ - public com.google.protobuf.ByteString - getCmdBytes() { - Object ref = cmd_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - cmd_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string cmd = 4; - */ - public Builder setCmd( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - cmd_ = value; - onChanged(); - return this; - } - /** - * string cmd = 4; - */ - public Builder clearCmd() { - - cmd_ = getDefaultInstance().getCmd(); - onChanged(); - return this; - } - /** - * string cmd = 4; - */ - public Builder setCmdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - cmd_ = value; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - String, String> resMap_; - private com.google.protobuf.MapField - internalGetResMap() { - if (resMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ResMapDefaultEntryHolder.defaultEntry); - } - return resMap_; - } - private com.google.protobuf.MapField - internalGetMutableResMap() { - onChanged();; - if (resMap_ == null) { - resMap_ = com.google.protobuf.MapField.newMapField( - ResMapDefaultEntryHolder.defaultEntry); - } - if (!resMap_.isMutable()) { - resMap_ = resMap_.copy(); - } - return resMap_; - } - - public int getResMapCount() { - return internalGetResMap().getMap().size(); - } - /** - * map<string, string> resMap = 5; - */ - - public boolean containsResMap( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetResMap().getMap().containsKey(key); - } - /** - * Use {@link #getResMapMap()} instead. - */ - @Deprecated - public java.util.Map getResMap() { - return getResMapMap(); - } - /** - * map<string, string> resMap = 5; - */ - - public java.util.Map getResMapMap() { - return internalGetResMap().getMap(); - } - /** - * map<string, string> resMap = 5; - */ - - public String getResMapOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetResMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> resMap = 5; - */ - - public String getResMapOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetResMap().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearResMap() { - internalGetMutableResMap().getMutableMap() - .clear(); - return this; - } - /** - * map<string, string> resMap = 5; - */ - - public Builder removeResMap( - String key) { - if (key == null) { throw new NullPointerException(); } - internalGetMutableResMap().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @Deprecated - public java.util.Map - getMutableResMap() { - return internalGetMutableResMap().getMutableMap(); - } - /** - * map<string, string> resMap = 5; - */ - public Builder putResMap( - String key, - String value) { - if (key == null) { throw new NullPointerException(); } - if (value == null) { throw new NullPointerException(); } - internalGetMutableResMap().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, string> resMap = 5; - */ - - public Builder putAllResMap( - java.util.Map values) { - internalGetMutableResMap().getMutableMap() - .putAll(values); - return this; - } - @Override - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.setUnknownFieldsProto3(unknownFields); - } - - @Override - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.mergeUnknownFields(unknownFields); - } - - - // @@protoc_insertion_point(builder_scope:com.xiaomi.mone.ultraman.grpc.UltramanResponse) - } - - // @@protoc_insertion_point(class_scope:com.xiaomi.mone.ultraman.grpc.UltramanResponse) - private static final UltramanResponse DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new UltramanResponse(); - } - - public static UltramanResponse getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @Override - public UltramanResponse parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new UltramanResponse(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @Override - public UltramanResponse getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponseOrBuilder.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponseOrBuilder.java deleted file mode 100644 index 0c098e04c..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanResponseOrBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: service.proto - -package run.mone.mone.ultraman.grpc; - -public interface UltramanResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:com.xiaomi.mone.ultraman.grpc.UltramanResponse) - com.google.protobuf.MessageOrBuilder { - - /** - * string id = 1; - */ - String getId(); - /** - * string id = 1; - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - * string data = 2; - */ - String getData(); - /** - * string data = 2; - */ - com.google.protobuf.ByteString - getDataBytes(); - - /** - * int32 code = 3; - */ - int getCode(); - - /** - * string cmd = 4; - */ - String getCmd(); - /** - * string cmd = 4; - */ - com.google.protobuf.ByteString - getCmdBytes(); - - /** - * map<string, string> resMap = 5; - */ - int getResMapCount(); - /** - * map<string, string> resMap = 5; - */ - boolean containsResMap( - String key); - /** - * Use {@link #getResMapMap()} instead. - */ - @Deprecated - java.util.Map - getResMap(); - /** - * map<string, string> resMap = 5; - */ - java.util.Map - getResMapMap(); - /** - * map<string, string> resMap = 5; - */ - - String getResMapOrDefault( - String key, - String defaultValue); - /** - * map<string, string> resMap = 5; - */ - - String getResMapOrThrow( - String key); -} diff --git a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanServiceGrpc.java b/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanServiceGrpc.java deleted file mode 100644 index c46af6dc9..000000000 --- a/athena-all/src/main/java/run/mone/mone/ultraman/grpc/UltramanServiceGrpc.java +++ /dev/null @@ -1,401 +0,0 @@ -package run.mone.mone.ultraman.grpc; - -import static io.grpc.MethodDescriptor.generateFullMethodName; -import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; -import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; -import static io.grpc.stub.ClientCalls.asyncUnaryCall; -import static io.grpc.stub.ClientCalls.blockingUnaryCall; -import static io.grpc.stub.ClientCalls.futureUnaryCall; -import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; -import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; -import static io.grpc.stub.ServerCalls.asyncUnaryCall; -import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; -import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; - -/** - */ -@javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.34.1)", - comments = "Source: service.proto") -public final class UltramanServiceGrpc { - - private UltramanServiceGrpc() {} - - public static final String SERVICE_NAME = "com.xiaomi.mone.ultraman.grpc.UltramanService"; - - // Static method descriptors that strictly reflect the proto. - private static volatile io.grpc.MethodDescriptor getHelloMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "hello", - requestType = UltramanRequest.class, - responseType = UltramanResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getHelloMethod() { - io.grpc.MethodDescriptor getHelloMethod; - if ((getHelloMethod = UltramanServiceGrpc.getHelloMethod) == null) { - synchronized (UltramanServiceGrpc.class) { - if ((getHelloMethod = UltramanServiceGrpc.getHelloMethod) == null) { - UltramanServiceGrpc.getHelloMethod = getHelloMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "hello")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanResponse.getDefaultInstance())) - .setSchemaDescriptor(new UltramanServiceMethodDescriptorSupplier("hello")) - .build(); - } - } - } - return getHelloMethod; - } - - private static volatile io.grpc.MethodDescriptor getStreamMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "stream", - requestType = UltramanRequest.class, - responseType = UltramanResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING) - public static io.grpc.MethodDescriptor getStreamMethod() { - io.grpc.MethodDescriptor getStreamMethod; - if ((getStreamMethod = UltramanServiceGrpc.getStreamMethod) == null) { - synchronized (UltramanServiceGrpc.class) { - if ((getStreamMethod = UltramanServiceGrpc.getStreamMethod) == null) { - UltramanServiceGrpc.getStreamMethod = getStreamMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "stream")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanResponse.getDefaultInstance())) - .setSchemaDescriptor(new UltramanServiceMethodDescriptorSupplier("stream")) - .build(); - } - } - } - return getStreamMethod; - } - - private static volatile io.grpc.MethodDescriptor getCallMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "call", - requestType = UltramanRequest.class, - responseType = UltramanResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.CLIENT_STREAMING) - public static io.grpc.MethodDescriptor getCallMethod() { - io.grpc.MethodDescriptor getCallMethod; - if ((getCallMethod = UltramanServiceGrpc.getCallMethod) == null) { - synchronized (UltramanServiceGrpc.class) { - if ((getCallMethod = UltramanServiceGrpc.getCallMethod) == null) { - UltramanServiceGrpc.getCallMethod = getCallMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.CLIENT_STREAMING) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "call")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - UltramanResponse.getDefaultInstance())) - .setSchemaDescriptor(new UltramanServiceMethodDescriptorSupplier("call")) - .build(); - } - } - } - return getCallMethod; - } - - /** - * Creates a new async stub that supports all call types for the service - */ - public static UltramanServiceStub newStub(io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @Override - public UltramanServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceStub(channel, callOptions); - } - }; - return UltramanServiceStub.newStub(factory, channel); - } - - /** - * Creates a new blocking-style stub that supports unary and streaming output calls on the service - */ - public static UltramanServiceBlockingStub newBlockingStub( - io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @Override - public UltramanServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceBlockingStub(channel, callOptions); - } - }; - return UltramanServiceBlockingStub.newStub(factory, channel); - } - - /** - * Creates a new ListenableFuture-style stub that supports unary calls on the service - */ - public static UltramanServiceFutureStub newFutureStub( - io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @Override - public UltramanServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceFutureStub(channel, callOptions); - } - }; - return UltramanServiceFutureStub.newStub(factory, channel); - } - - /** - */ - public static abstract class UltramanServiceImplBase implements io.grpc.BindableService { - - /** - */ - public void hello(UltramanRequest request, - io.grpc.stub.StreamObserver responseObserver) { - asyncUnimplementedUnaryCall(getHelloMethod(), responseObserver); - } - - /** - */ - public io.grpc.stub.StreamObserver stream( - io.grpc.stub.StreamObserver responseObserver) { - return asyncUnimplementedStreamingCall(getStreamMethod(), responseObserver); - } - - /** - */ - public io.grpc.stub.StreamObserver call( - io.grpc.stub.StreamObserver responseObserver) { - return asyncUnimplementedStreamingCall(getCallMethod(), responseObserver); - } - - @Override public final io.grpc.ServerServiceDefinition bindService() { - return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - getHelloMethod(), - asyncUnaryCall( - new MethodHandlers< - UltramanRequest, - UltramanResponse>( - this, METHODID_HELLO))) - .addMethod( - getStreamMethod(), - asyncBidiStreamingCall( - new MethodHandlers< - UltramanRequest, - UltramanResponse>( - this, METHODID_STREAM))) - .addMethod( - getCallMethod(), - asyncClientStreamingCall( - new MethodHandlers< - UltramanRequest, - UltramanResponse>( - this, METHODID_CALL))) - .build(); - } - } - - /** - */ - public static final class UltramanServiceStub extends io.grpc.stub.AbstractAsyncStub { - private UltramanServiceStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @Override - protected UltramanServiceStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceStub(channel, callOptions); - } - - /** - */ - public void hello(UltramanRequest request, - io.grpc.stub.StreamObserver responseObserver) { - asyncUnaryCall( - getChannel().newCall(getHelloMethod(), getCallOptions()), request, responseObserver); - } - - /** - */ - public io.grpc.stub.StreamObserver stream( - io.grpc.stub.StreamObserver responseObserver) { - return asyncBidiStreamingCall( - getChannel().newCall(getStreamMethod(), getCallOptions()), responseObserver); - } - - /** - */ - public io.grpc.stub.StreamObserver call( - io.grpc.stub.StreamObserver responseObserver) { - return asyncClientStreamingCall( - getChannel().newCall(getCallMethod(), getCallOptions()), responseObserver); - } - } - - /** - */ - public static final class UltramanServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { - private UltramanServiceBlockingStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @Override - protected UltramanServiceBlockingStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceBlockingStub(channel, callOptions); - } - - /** - */ - public UltramanResponse hello(UltramanRequest request) { - return blockingUnaryCall( - getChannel(), getHelloMethod(), getCallOptions(), request); - } - } - - /** - */ - public static final class UltramanServiceFutureStub extends io.grpc.stub.AbstractFutureStub { - private UltramanServiceFutureStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @Override - protected UltramanServiceFutureStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new UltramanServiceFutureStub(channel, callOptions); - } - - /** - */ - public com.google.common.util.concurrent.ListenableFuture hello( - UltramanRequest request) { - return futureUnaryCall( - getChannel().newCall(getHelloMethod(), getCallOptions()), request); - } - } - - private static final int METHODID_HELLO = 0; - private static final int METHODID_STREAM = 1; - private static final int METHODID_CALL = 2; - - private static final class MethodHandlers implements - io.grpc.stub.ServerCalls.UnaryMethod, - io.grpc.stub.ServerCalls.ServerStreamingMethod, - io.grpc.stub.ServerCalls.ClientStreamingMethod, - io.grpc.stub.ServerCalls.BidiStreamingMethod { - private final UltramanServiceImplBase serviceImpl; - private final int methodId; - - MethodHandlers(UltramanServiceImplBase serviceImpl, int methodId) { - this.serviceImpl = serviceImpl; - this.methodId = methodId; - } - - @Override - @SuppressWarnings("unchecked") - public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { - switch (methodId) { - case METHODID_HELLO: - serviceImpl.hello((UltramanRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - default: - throw new AssertionError(); - } - } - - @Override - @SuppressWarnings("unchecked") - public io.grpc.stub.StreamObserver invoke( - io.grpc.stub.StreamObserver responseObserver) { - switch (methodId) { - case METHODID_STREAM: - return (io.grpc.stub.StreamObserver) serviceImpl.stream( - (io.grpc.stub.StreamObserver) responseObserver); - case METHODID_CALL: - return (io.grpc.stub.StreamObserver) serviceImpl.call( - (io.grpc.stub.StreamObserver) responseObserver); - default: - throw new AssertionError(); - } - } - } - - private static abstract class UltramanServiceBaseDescriptorSupplier - implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { - UltramanServiceBaseDescriptorSupplier() {} - - @Override - public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { - return Service.getDescriptor(); - } - - @Override - public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { - return getFileDescriptor().findServiceByName("UltramanService"); - } - } - - private static final class UltramanServiceFileDescriptorSupplier - extends UltramanServiceBaseDescriptorSupplier { - UltramanServiceFileDescriptorSupplier() {} - } - - private static final class UltramanServiceMethodDescriptorSupplier - extends UltramanServiceBaseDescriptorSupplier - implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { - private final String methodName; - - UltramanServiceMethodDescriptorSupplier(String methodName) { - this.methodName = methodName; - } - - @Override - public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { - return getServiceDescriptor().findMethodByName(methodName); - } - } - - private static volatile io.grpc.ServiceDescriptor serviceDescriptor; - - public static io.grpc.ServiceDescriptor getServiceDescriptor() { - io.grpc.ServiceDescriptor result = serviceDescriptor; - if (result == null) { - synchronized (UltramanServiceGrpc.class) { - result = serviceDescriptor; - if (result == null) { - serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) - .setSchemaDescriptor(new UltramanServiceFileDescriptorSupplier()) - .addMethod(getHelloMethod()) - .addMethod(getStreamMethod()) - .addMethod(getCallMethod()) - .build(); - } - } - } - return result; - } -} diff --git a/athena-all/src/main/java/run/mone/ultraman/AthenaContext.java b/athena-all/src/main/java/run/mone/ultraman/AthenaContext.java index 57250c706..f2debfa19 100644 --- a/athena-all/src/main/java/run/mone/ultraman/AthenaContext.java +++ b/athena-all/src/main/java/run/mone/ultraman/AthenaContext.java @@ -1,8 +1,8 @@ package run.mone.ultraman; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.ModelRes; -import run.mone.m78.ip.listener.UltrmanTreeKeyAdapter; +import com.xiaomi.youpin.tesla.ip.bo.ModelRes; +import com.xiaomi.youpin.tesla.ip.listener.UltrmanTreeKeyAdapter; import lombok.Data; import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.bo.ClientData; @@ -29,10 +29,16 @@ public class AthenaContext { private String zAddr; + private String userName; + private List models; private Map modelMap; + private String localAddress; + + private String localPort; + //models 直接 转换为 modelMap,key是 ModelRes中的 value(class) public void convertModelsToModelMap() { @@ -60,14 +66,23 @@ public ClientData getClientData(String projectName) { } /** - * chatgpt的模型 + * 聊天模型 */ private String gptModel = ""; + /** + * 非聊天模型 + */ + private String noChatModel = ""; + public int getMaxTokenNum() { return getModel(gptModel).getMaxToken(); } + public int getNoChatMaxTokenNum() { + return getModel(noChatModel).getMaxToken(); + } + public ModelRes gptModel() { if (StringUtils.isEmpty(this.gptModel)) { return null; @@ -75,6 +90,13 @@ public ModelRes gptModel() { return getModel(this.gptModel); } + public ModelRes noChatModel() { + if (StringUtils.isEmpty(this.noChatModel)) { + return null; + } + return getModel(this.noChatModel); + } + private List modelList = new ArrayList<>(); private String token; diff --git a/athena-all/src/main/java/run/mone/ultraman/AthenaInspection.java b/athena-all/src/main/java/run/mone/ultraman/AthenaInspection.java index 81c3551fb..a2056be94 100644 --- a/athena-all/src/main/java/run/mone/ultraman/AthenaInspection.java +++ b/athena-all/src/main/java/run/mone/ultraman/AthenaInspection.java @@ -1,24 +1,30 @@ package run.mone.ultraman; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.intellij.codeInspection.*; import com.intellij.codeInspection.util.IntentionFamilyName; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.EditorUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** * @author goodjava@qq.com - * 对方法进行重命名 - * @date 2022/5/2 09:19 */ public class AthenaInspection extends AbstractBaseJavaLocalInspectionTool { @@ -27,33 +33,73 @@ public class AthenaInspection extends AbstractBaseJavaLocalInspectionTool { public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { return new JavaElementVisitor() { + @Override + public void visitParameter(@NotNull PsiParameter parameter) { + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + + // 获取参数名 + String paramName = parameter.getName(); + // 获取参数类型 + PsiElement parent = parameter.getParent(); + if (parent instanceof PsiParameterList) { + PsiElement grandparent = parent.getParent(); + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + + if (grandparent instanceof PsiMethod) { + holder.registerProblem(parameter, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { + @Override + public @IntentionFamilyName @NotNull String getFamilyName() { + return Const.PLUGIN_NAME + "(参数命名)"; + } + + + //参数重命名 + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + HashMap param = Maps.newHashMap(); + param.put("paramName", paramName); + invokePrompt(project, "rename_param_name", param, ImmutableMap.of("parameter", parameter)); + } + }); + + } + } + + + } + //analyse_class @Override public void visitClass(PsiClass aClass) { + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; - holder.registerProblem(aClass, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { + List> list = Prompt.getPromptInfoByTag("class_inspection").stream() + .filter(it -> it.isCollected() || Prompt.containsTag(it.getTags(), "system")) + .map(it -> Pair.of(it.getDesc(), it.getPromptName())) + .collect(Collectors.toList()); + + list.forEach(it -> holder.registerProblem(aClass, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { @Override public @IntentionFamilyName @NotNull String getFamilyName() { - return "Athena(类分析)"; + return it.getKey(); } - //类分析 @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - String promptName = "analyse_class"; - invokePrompt(project,promptName); + String promptName = it.getValue(); + invokePrompt(project, promptName, Maps.newHashMap()); } - }); + })); + } - // rename_method(方法重命名) comment_2(方法添加注释) suggest_sidecar(方法review+建议) + // rename_method(方法重命名) comment_2(方法添加注释) suggest_sidecar(方法review+建议) test_code(单元测试) @Override public void visitMethod(PsiMethod method) { - List> list = Prompt.getPromptInfoByTag("method_inspection").stream() - .filter(it -> it.isCollected() || Prompt.containsTag(it.getTags(), "system")) - .map(it -> Pair.of(it.getDesc(), it.getPromptName())) - .collect(Collectors.toList()); + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + + List> list = getPromptMethodMenu(); list.forEach(it -> holder.registerProblem(method, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { @Override public @IntentionFamilyName @NotNull String getFamilyName() { @@ -63,7 +109,12 @@ public void visitMethod(PsiMethod method) { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { String promptName = it.getValue(); - invokePrompt(project,promptName); + invokePrompt(project, promptName, Maps.newHashMap()); + } + + @Override + public boolean startInWriteAction() { + return false; } })); @@ -73,23 +124,69 @@ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descri @Override //访问注释 public void visitComment(@NotNull PsiComment comment) { - //直接生成代码 + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + //单行注释 直接生成代码 if (comment.getText().startsWith("//")) { - final String content = comment.getText().substring(2); - holder.registerProblem(comment, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { - @Override - //获取修复的家族名称 - public @IntentionFamilyName @NotNull String getFamilyName() { - return "Athena(生成方法)"; - } - - @Override - //应用修复 - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - //根据注释生成代码 - PromptService.generateMethod(project, content); - } - }); + //注释范围在 (method, class] + if (EditorUtils.isCommentInsideClass(comment) + && EditorUtils.isNotClassHeaderComment(comment) + && isNotMethodComment(comment)) { + final String content = comment.getText().substring(2); + holder.registerProblem(comment, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { + @Override + //获取修复的家族名称 + public @IntentionFamilyName @NotNull String getFamilyName() { + return Const.PLUGIN_NAME + "(生成代码)"; + } + + @Override + //应用修复 + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PromptInfo promptInfo = Prompt.getPromptInfo(Const.GENERATE_CODE); + if (isBotUsageConfigured(promptInfo)) { + //调用bot生成代码 + invokePrompt(project, promptInfo.getPromptName(), Maps.newHashMap()); + } else { + //根据注释生成代码 + PromptService.generateMethod(project, content); + } + } + }); + } + } + + // 处理多行注释 + if (comment.getText().startsWith("/*")) { + if (EditorUtils.isCommentInsideClass(comment) + && EditorUtils.isNotClassHeaderComment(comment) + && isNotMethodComment(comment)) { + final String content = comment.getText().trim(); + holder.registerProblem(comment, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { + @Override + public @IntentionFamilyName @NotNull String getFamilyName() { + return Const.PLUGIN_NAME + "(生成代码)"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + // 移动光标到注释末尾 + PsiElement element = descriptor.getPsiElement(); + if (element instanceof PsiComment) { + PsiComment comment = (PsiComment) element; + EditorUtils.moveCaretToCommentEnd(project, comment); + } + + PromptInfo promptInfo = Prompt.getPromptInfo(Const.GENERATE_CODE); + if (isBotUsageConfigured(promptInfo)) { + Map parms = Maps.newHashMap(); + parms.put(Const.GENERATE_CODE_COMMENT, content); + invokePrompt(project, promptInfo.getPromptName(), parms); + } else { + PromptService.generateMethod(project, content); + } + } + }); + } } } @@ -99,33 +196,62 @@ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descri */ @Override public void visitField(PsiField field) { + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; holder.registerProblem(field, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { @Override public @IntentionFamilyName @NotNull String getFamilyName() { - return "Athena(字段重命名)"; + return Const.PLUGIN_NAME + "(字段重命名)"; } @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { String promptName = "rename_field"; - invokePrompt(project, promptName); + invokePrompt(project, promptName, Maps.newHashMap()); } }); } }; } + //查询方法级菜单列表 + private List> getPromptMethodMenu() { + List> list = Prompt.getPromptInfoByTag("method_inspection").stream() + .filter(it -> it.isCollected() || Prompt.containsTag(it.getTags(), "popup")) + .sorted(Comparator.comparingInt(it -> Integer.parseInt(it.getLabels().getOrDefault("order", "1")))) + .map(it -> Pair.of(it.getDesc(), it.getPromptName())) + .collect(Collectors.toList()); + return list; + } + + private static boolean isNotMethodComment(@NotNull PsiComment comment) { + return !(comment.getParent() instanceof PsiMethod); + } + - public static void invokePrompt(Project project, String promptName) { + public static void invokePrompt(Project project, String promptName, Map param) { + invokePrompt(project, promptName, param, Maps.newHashMap()); + } + + public static void invokePrompt(Project project, String promptName, Map param, Map objMap) { PromptInfo promptInfo = Prompt.getPromptInfo(promptName); PromptType promptType = Prompt.getPromptType(promptInfo); + //直接使用bot + if (isBotUsageConfigured(promptInfo)) { + promptType = PromptType.executeBot; + } PromptService.dynamicInvoke(GenerateCodeReq.builder() .project(project) .promptType(promptType) .promptName(promptName) .promptInfo(promptInfo) + .param(param) + .objMap(objMap) .build()); } + //是否是调用bot来执行 + public static boolean isBotUsageConfigured(PromptInfo promptInfo) { + return ResourceUtils.has(Const.USE_BOT) && promptInfo.has(Const.BOT_ID) && !(promptInfo.getLabels().get(Const.BOT_ID).equals("0")); + } } diff --git a/athena-all/src/main/java/run/mone/ultraman/AthenaSuggestionInspection.java b/athena-all/src/main/java/run/mone/ultraman/AthenaSuggestionInspection.java index eba5aa615..4f4a3cb47 100644 --- a/athena-all/src/main/java/run/mone/ultraman/AthenaSuggestionInspection.java +++ b/athena-all/src/main/java/run/mone/ultraman/AthenaSuggestionInspection.java @@ -6,12 +6,13 @@ import com.intellij.psi.JavaElementVisitor; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiMethod; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.Message; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.Message; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; import org.jetbrains.annotations.NotNull; /** @@ -20,6 +21,7 @@ */ public class AthenaSuggestionInspection extends AbstractBaseJavaLocalInspectionTool { + //代码修改建议 private static final String promptName = "hi2"; @NotNull @@ -29,10 +31,10 @@ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean is @Override public void visitMethod(PsiMethod method) { - if (true) { - return; - } super.visitMethod(method); + + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + holder.registerProblem(method, "", ProblemHighlightType.INFORMATION, new LocalQuickFix() { @Override @@ -44,12 +46,12 @@ public void visitMethod(PsiMethod method) { public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { PromptInfo promptInfo = Prompt.getPromptInfo(promptName); PromptType promptType = Prompt.getPromptType(promptInfo); - PromptService.inlayHint(GenerateCodeReq.builder() - .promptName(promptName) - .promptInfo(promptInfo) - .promptType(promptType) - .project(project) - .projectName(project.getName()).build()); + PromptService.dynamicInvoke(GenerateCodeReq.builder() + .promptName(promptName) + .promptInfo(promptInfo) + .promptType(promptType) + .project(project) + .projectName(project.getName()).build()); } }); } diff --git a/athena-all/src/main/java/run/mone/ultraman/DemoService.java b/athena-all/src/main/java/run/mone/ultraman/DemoService.java index f1dd49a07..de7cd99ed 100644 --- a/athena-all/src/main/java/run/mone/ultraman/DemoService.java +++ b/athena-all/src/main/java/run/mone/ultraman/DemoService.java @@ -1,6 +1,15 @@ package run.mone.ultraman; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + /** * @author goodjava@qq.com * @date 2023/6/7 18:20 @@ -8,5 +17,27 @@ public class DemoService { + //ai:截取当前桌面,保存到指定文件(filePath参数),如果截取成功,则返回"ok" + public String captureDesktop(String filePath) { + try { + Robot robot = new Robot(); + Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); + BufferedImage image = robot.createScreenCapture(screenRect); + File file = new File(filePath); + ImageIO.write(image, "png", file); + return "ok"; + } catch (Exception e) { + e.printStackTrace(); + return "error"; + } + } + + //ai:根据提供的的文件地址,读取文件内容,用String返回 + public String readFile(String filePath) throws IOException { + Path path = Paths.get(filePath); + return Files.readString(path); + } + + } diff --git a/athena-all/src/main/java/run/mone/ultraman/HttpServerHandler.java b/athena-all/src/main/java/run/mone/ultraman/HttpServerHandler.java index 6db1c2640..9987088bf 100644 --- a/athena-all/src/main/java/run/mone/ultraman/HttpServerHandler.java +++ b/athena-all/src/main/java/run/mone/ultraman/HttpServerHandler.java @@ -1,7 +1,26 @@ package run.mone.ultraman; -import com.google.gson.Gson; -import com.google.gson.JsonObject; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.gson.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.RobotContext; +import com.xiaomi.youpin.tesla.ip.bo.RobotReq; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.JavaClassUtils; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.RobotService; +import com.xiaomi.youpin.tesla.ip.util.*; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; @@ -9,17 +28,400 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.util.CharsetUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.mutable.MutableObject; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import run.mone.openai.OpenaiCall; +import run.mone.ultraman.bo.AiReq; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.common.ActionEventUtils; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.common.PythonExecutor; +import run.mone.ultraman.common.SafeRun; +import run.mone.ultraman.http.HttpClient; import run.mone.ultraman.http.HttpResponseUtils; +import run.mone.ultraman.http.Param; +import run.mone.ultraman.http.handler.ReadCodeHandler; +import run.mone.ultraman.http.handler.WriteCodeHandler; +import run.mone.ultraman.service.AgentService; +import run.mone.ultraman.service.AthenaCodeService; +import run.mone.ultraman.state.PromptAndFunctionProcessor; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.util.Base64; +import java.util.List; +import java.util.Optional; + +@Slf4j public class HttpServerHandler extends SimpleChannelInboundHandler { private Gson gson = new Gson(); @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { + String uri = req.uri(); + + // 使用java.net.URI解析URI字符串 + URI parsedUri = new URI(uri); + + // 获取路径部分 + String path = parsedUri.getPath(); + + if (uri.startsWith("/favicon.ico")) { + ctx.writeAndFlush(HttpResponseUtils.createResponse(HttpResponseStatus.NOT_FOUND, "404")).addListener(ChannelFutureListener.CLOSE); + return; + } + + RobotContext context = new RobotContext(); + + Param p = new Param(); + p.decode(req); + String data = "ok"; + String message = "success"; + + JsonObject resObj = new JsonObject(); + resObj.addProperty("code", 0); + if (path.equals("/tianye")) { + ByteBuf jsonBuf = req.content(); + String reqString = jsonBuf.toString(CharsetUtil.UTF_8); + log.info("call tianye req:{}", reqString); + JsonElement element = JsonParser.parseString(reqString); + JsonObject obj = (JsonObject) element; + if (element.isJsonObject()) { + String cmd = obj.get("cmd").getAsString(); + switch (cmd) { + case "close_all_tab": { + log.info("close_all_tab"); + CodeService.invokeLater(() -> AthenaContext.ins().getProjectMap().keySet().forEach(projectName -> AgentService.closeAllOpenFilesInProject(AthenaContext.ins().getProjectMap().get(projectName)))); + break; + } + //创建代码或者修改代码 + case "write_code": { + resObj = new WriteCodeHandler().execute(obj, resObj); + break; + } + //创建测试类 + case "generate_test_class": { + String projectName = obj.get("projectName").getAsString(); + String moduleName = obj.get("moduleName").getAsString(); + String promptName = getPromptNameFromJsonObject(obj); + Project project = AthenaContext.ins().getProjectMap().get(projectName); + //如果指定package,则这个package下的所有类都会创建测试类 + String packageName = getPackageNameFromJsonObject(obj); + List list = getClassListFromPackage(packageName, project, obj); + list.stream().forEach(className -> { + log.info("generate_test_class class name:{}", className); + String code = ApplicationManager.getApplication().runReadAction((Computable) () -> { + PsiClass psiClass = PsiClassUtils.findClassByName(project, className); + PsiElement javaFile = psiClass.getParent(); + return javaFile.getText(); + }); + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + JsonObject jsonRes = PromptAndFunctionProcessor.callPrompt(project, promptInfo, ImmutableMap.of("code", code)); + String testClassCode = extractTestClassCodeFromJsonResponse(jsonRes); + AthenaClassInfo info = AthenaCodeService.classInfo(testClassCode); + ApplicationManager.getApplication().invokeLater(() -> { + PsiClass clazz = PsiClassUtils.findClassByName(project, info.getPackagePath() + "." + info.getName()); + if (null == clazz) { + //没有package则直接创建 + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiDirectory directory = PsiClassUtils.getTestSourceDirectory(project, moduleName); + directory = PsiClassUtils.createPackageDirectories(directory, info.getPackagePath()); + PsiClassUtils.createClass(project, info.getName(), testClassCode, false, directory); + log.info("create test class:{} success", info.getName()); + }); + } else { + log.info("class {} already exists", info.getName()); + } + }); + }); + break; + } + //快速修复代码 + case "fix_code": { + processJsonObjectAndFixCode(obj, resObj); + break; + } + //执行代码 + case "run_code": { + ApplicationManager.getApplication().invokeLater(() -> ActionEventUtils.executeDefaultRunAction()); + } + //打开代码 + case "open_code": { + String projectName = obj.get("projectName").getAsString(); + String className = obj.get("className").getAsString(); + ApplicationManager.getApplication().invokeLater(() -> { + JavaClassUtils.openClass(ProjectUtils.projectFromManager(projectName), className); + }); + } + //列出project + case "list_project": { + listProject(ctx, resObj); + return; + } + //列出module + case "list_module": { + listModule(ctx, obj, resObj); + return; + } + //执行java程序 + case "execute_java": { + executeJava(obj); + break; + } + //读取code + case "read_code": { + resObj = new ReadCodeHandler().execute(obj, resObj); + break; + } + //创建包路径 + case "create_package": { + createPackage(obj); + break; + } + case "auto_app": { + // 调用jcommen genreateCodeBase + ProjectUtils projectUtils = new ProjectUtils(); + Project project = ProjectUtils.projectFromManager(); + String projectName = obj.get("projectName").getAsString(); + String groupId = obj.get("groupId").getAsString(); + String author = obj.get("author").getAsString(); + Optional autoAppPath = projectUtils.generateProjectBase(project, projectName, "run.mone", groupId, author); + // openProject + autoAppPath.ifPresent(string -> projectUtils.openProject(project, string)); + break; + } + } + } + sendRes(ctx, resObj); + return; + } + + //mp3 + if (uri.contains("audio")) { + ByteBuf jsonBuf = req.content(); + String base64Data = jsonBuf.toString(CharsetUtil.UTF_8); + byte[] bytes = Base64.getDecoder().decode(base64Data); + AudioInputStream a = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes)); + Clip c = AudioSystem.getClip(); + c.open(a); + c.start(); + sendRes(ctx, getObj("ok", "success")); + return; + } + //这里会调用python代码(然后python最后会代用到ai) + if (uri.contains("go")) { + RobotService.consoleMessage(context, RobotReq.builder().param("call go v:" + p.getV()).build()); + String scriptPath = ConfigUtils.getConfig().getMvnPath(); + PythonExecutor.run(scriptPath + "run.sh", p.getV()); + } + //解析出来实际要执行的命令(curl http://127.0.0.1:3458/ai?cmd=在终端执行命令ls -la) + if (uri.contains("ai")) { + RobotService.consoleMessage(context, RobotReq.builder().param("call ai cmd:" + p.getCmd()).build()); + ByteBuf jsonBuf = req.content(); + String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8); + AiReq aiReq = gson.fromJson(jsonStr, AiReq.class); + + String cmd = aiReq.getCmd(); + p.setCmd(cmd); + + if (aiReq.getAi().equals("chatglm")) { + String res = HttpClient.callChatgml(aiReq.getCmd()); + RobotService.consoleMessage(context, RobotReq.builder().param("call glm res:" + res).build()); + String scriptPath = ConfigUtils.getConfig().getMvnPath(); + PythonExecutor.run(scriptPath + "play_run.sh", res); + sendRes(ctx, getObj(res, "success")); + return; + } + + if (aiReq.getAi().equals("chatgpt")) { + String key = ConfigUtils.getConfig().getChatgptKey(); + String proxy = ConfigUtils.getConfig().getChatgptProxy(); + String res = OpenaiCall.call(key, proxy, "%s", aiReq.getCmd()); + RobotService.consoleMessage(context, RobotReq.builder().param("call gpt res:" + res).build()); + String scriptPath = ConfigUtils.getConfig().getMvnPath(); + PythonExecutor.run(scriptPath + "play_run.sh", res); + sendRes(ctx, getObj(res, "success")); + return; + } + + //不执行ai,直接自己解析,方便测试 + else if (cmd.startsWith("run:")) { + RobotService.consoleMessage(context, RobotReq.builder().param("debug pattern").build()); + String[] cmds = cmd.split(":"); + p.setPath(cmds[1]); + if (cmds.length >= 3) { + p.setParam(cmds[2]); + } else { + p.setParam(""); + } + } else { +// Pair res = ChatGptService.callOpenai(Prompt.get("cmd"), cmd); + Pair res = null; + if (res.getKey() != 0) { + RobotService.consoleMessage(context, RobotReq.builder().param(res.getValue()).build()); + FullHttpResponse response = HttpResponseUtils.createResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR, res.getValue()); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + return; + } + RobotService.consoleMessage(context, RobotReq.builder().param("call ai cmd:" + p.getCmd() + " res:" + res).build()); + message = res.getValue(); + Pair pair = p.getPathAndParam(res.getValue()); + p.setPath(pair.getKey()); + p.setParam(pair.getValue()); + } + } + data = RobotService.invoke(p.getPath(), context, RobotReq.builder().param(p.getParam()).build()); + RobotService.consoleMessage(context, RobotReq.builder().param("call robot res:" + data + " param:" + p.getParam() + " method:" + p.getPath()).build()); + MutableObject mo = new MutableObject(data); + SafeRun.run(() -> { + if (null != mo.getValue() && mo.getValue().toString().length() > 0) { + RobotService.consoleMessage(context, RobotReq.builder().param("say res:" + mo.getValue()).build()); + String scriptPath = ConfigUtils.getConfig().getMvnPath(); + PythonExecutor.run(scriptPath + "play_run.sh", mo.getValue().toString()); + } + }); + JsonObject obj = getObj(data, message); // 创建http响应 - sendRes(ctx, new JsonObject()); + sendRes(ctx, obj); + } + + + //执行java代码(比如创建sql 比如创建orm先关的类),有些代码最好是生成的 + private static void executeJava(JsonObject obj) { + log.info("execute java obj:{}", obj); + String className = obj.get("className").getAsString(); + String type = obj.get("type").getAsString(); + JsonObject jsonObj = new JsonObject(); + if (type.equals("create_table")) { + String sql = obj.get("sql").getAsString(); + jsonObj.addProperty("sql", sql); + } else if (type.equals("create_code")) { + if (obj.has("tableName")) { + jsonObj.addProperty("tableName", obj.get("tableName").getAsString()); + } + if (obj.has("pojoName")) { + jsonObj.addProperty("pojoName", obj.get("pojoName").getAsString()); + } + } + jsonObj.addProperty("type", type); + String param = new String(Base64.getEncoder().encode(GsonUtils.gson.toJson(jsonObj).getBytes())); + ActionEventUtils.setupAndExecuteJavaAppConfiguration(className, param, ProjectUtils.projectFromManager(obj.get("projectName").getAsString())); + } + + private void listProject(ChannelHandlerContext ctx, JsonObject resObj) { + resObj.add("data", gson.toJsonTree(ProjectUtils.listOpenProjects())); + sendRes(ctx, resObj); + } + + private void listModule(ChannelHandlerContext ctx, JsonObject obj, JsonObject resObj) { + String projectName = obj.get("projectName").getAsString(); + resObj.add("data", gson.toJsonTree(ProjectUtils.listAllModules(ProjectUtils.projectFromManager(projectName)))); + sendRes(ctx, resObj); + } + + private static void createPackage(JsonObject obj) { + String projectName = obj.get("projectName").getAsString(); + String moduleName = obj.get("moduleName").getAsString(); + String packageName = obj.get("packageName").getAsString(); + CodeService.createPackageInModule(ProjectUtils.getModuleWithName(ProjectUtils.projectFromManager(projectName), moduleName), packageName); + } + + private static void processJsonObjectAndFixCode(JsonObject obj, JsonObject resObj) { + boolean blockOnFailure = false; + try { + // 找到已生成的pojo or service or controller + String projectName = obj.get("projectName").getAsString(); +// String className = obj.get("className").getAsString(); + JsonArray classList = obj.get("classList").getAsJsonArray(); + String packageName = obj.get("packageName").getAsString(); + JsonElement blockJson = obj.get("blockOnFailure"); + if (blockJson != null && "true".equals(blockJson.getAsString())) { + blockOnFailure = true; + } + if (StringUtils.isBlank(projectName)) { + return; + } + for (int i = 0; i < classList.size(); i++) { + String clsName = getFQCN(packageName, classList.get(i).getAsString()); + String code = getCode(projectName, clsName); + // 尝试quick fix + // TODO: not working for now + // ApplicationManager.getApplication().invokeLater(() -> CodeService.tryQuickFix(code, obj, projectName, className)); + // 尝试基于parse的fix + ApplicationManager.getApplication().invokeLater(() -> CodeService.tryParserBasedFix(code, projectName, clsName)); + } + resObj.addProperty("success", "true"); + return; + } catch (Exception e) { + log.error("Error while try to fix code, nested exception is:", e); + } + // HINT: whether to block on failure + if (!blockOnFailure) { + resObj.addProperty("success", "true"); + } + } + + @NotNull + private static List getClassListFromPackage(String packageName, Project project, JsonObject obj) { + List list = null; + if (StringUtils.isNotEmpty(packageName)) { + list = ApplicationManager.getApplication().runReadAction((Computable>) () -> PackageUtils.getClassList(project, packageName)); + } + if (null == list) { + String className = obj.get("className").getAsString(); + list = Lists.newArrayList(className); + } + return list; + } + + private static String getPromptNameFromJsonObject(JsonObject obj) { + String promptName = "test_class_code"; + if (obj.has("promptName")) { + promptName = obj.get("promptName").getAsString(); + } + return promptName; + } + + private static String getPackageNameFromJsonObject(JsonObject obj) { + String packageName = ""; + if (obj.has("packageName")) { + packageName = obj.get("packageName").getAsString(); + } + return packageName; + } + + private static String extractTestClassCodeFromJsonResponse(JsonObject jsonRes) { + String testClassCode = jsonRes.get("data").getAsString(); + testClassCode = MarkDownUtils.extractCodeBlock(testClassCode); + return testClassCode; + } + + private static String getCode(String projectName, String className) { + try { + return ReadAction.compute(() -> { + // 确保我们在正确的上下文中 + if (!ApplicationManager.getApplication().isReadAccessAllowed()) { + throw new IllegalStateException("Read access is not allowed"); + } + PsiClass psiClass = PsiClassUtils.findClassByName(ProjectUtils.projectFromManager(projectName), className); + return psiClass.getText(); + }); + } catch (Throwable e) { + log.error("failed to get code for class: {}, in project:{}", className, projectName); + return ""; + } + } + + private static String getFQCN(String packageName, String className) { + return StringUtils.joinWith(".", packageName, className); } private void sendRes(ChannelHandlerContext ctx, JsonObject obj) { @@ -37,4 +439,5 @@ private static JsonObject getObj(String data, String message) { return obj; } + } \ No newline at end of file diff --git a/athena-all/src/main/java/run/mone/ultraman/UltramanHttpServer.java b/athena-all/src/main/java/run/mone/ultraman/UltramanHttpServer.java deleted file mode 100644 index 553113843..000000000 --- a/athena-all/src/main/java/run/mone/ultraman/UltramanHttpServer.java +++ /dev/null @@ -1,60 +0,0 @@ -package run.mone.ultraman; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpResponseEncoder; -import io.netty.handler.codec.http.cors.CorsConfig; -import io.netty.handler.codec.http.cors.CorsConfigBuilder; -import io.netty.handler.codec.http.cors.CorsHandler; -import io.netty.handler.stream.ChunkedWriteHandler; - -public class UltramanHttpServer { - - private int port; - - public UltramanHttpServer(int port) { - this.port = port; - } - - public void run() throws Exception { - EventLoopGroup bossGroup = new NioEventLoopGroup(); - EventLoopGroup workerGroup = new NioEventLoopGroup(); - try { - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .childHandler(new ChannelInitializer() { - public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast("http-decoder", new HttpRequestDecoder()); - ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65535)); - ch.pipeline().addLast("http-encoder", new HttpResponseEncoder()); - ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); - // Configure CORS - CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin() - .allowedRequestHeaders("X-Requested-With", "Content-Type", "Accept", "Origin", "Authorization", "Referer", "sec-ch-ua", "sec-ch-ua-mobile", "sec-ch-ua-platform") - .allowedRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.OPTIONS) - .build(); - ch.pipeline().addLast("http-cors", new CorsHandler(corsConfig)); - ch.pipeline().addLast("http-server", new HttpServerHandler()); - } - }) - .option(ChannelOption.SO_BACKLOG, 128) - .childOption(ChannelOption.SO_KEEPALIVE, true); - ChannelFuture f = b.bind("0.0.0.0", port).sync(); - f.channel().closeFuture().sync(); - } finally { - bossGroup.shutdownGracefully(); - workerGroup.shutdownGracefully(); - } - } - -} \ No newline at end of file diff --git a/athena-all/src/main/java/run/mone/ultraman/action/AthenaStatusBarAction.java b/athena-all/src/main/java/run/mone/ultraman/action/AthenaStatusBarAction.java new file mode 100644 index 000000000..1aeaae911 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/action/AthenaStatusBarAction.java @@ -0,0 +1,21 @@ +package run.mone.ultraman.action; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import run.mone.ultraman.statusbar.AthenaStatusBarWidget; +import run.mone.ultraman.statusbar.PopUpReq; + +/** + * @author HawickMason@xiaomi.com + * @date 6/22/24 15:16 + */ +public class AthenaStatusBarAction extends AnAction { + + @Override + public void actionPerformed(@NotNull AnActionEvent actionEvent) { + Project project = actionEvent.getProject(); + AthenaStatusBarWidget.popUp(project, null, null, PopUpReq.builder().build()); + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/action/RegenerateCompletionAction.java b/athena-all/src/main/java/run/mone/ultraman/action/RegenerateCompletionAction.java new file mode 100644 index 000000000..40cbe0ae7 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/action/RegenerateCompletionAction.java @@ -0,0 +1,46 @@ +package run.mone.ultraman.action; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.editor.Editor; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import run.mone.ultraman.manager.InlayHintManager; +import run.mone.ultraman.listener.AthenaApplicationActivationListener; + +/** + * @author zhangxiaowei6 + * @Date 2024/6/20 14:36 + */ + +@Slf4j +public class RegenerateCompletionAction extends AnAction { + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + // 获取编辑器实例 + Editor editor = e.getData(CommonDataKeys.EDITOR); + if (editor == null) { + return; + } + // 此时如果有inlay内容则用户输入后dispose + InlayHintManager.ins().dispose(text -> { + if (StringUtils.isNotEmpty(text)) { + CodeService.deleteCode(editor); + CodeService.formatCode(editor.getProject()); + } + }); + // 再次触发 + AthenaApplicationActivationListener.handlePluginInEditor(editor); + } + + @Override + public void update(@NotNull AnActionEvent e) { + // 设置动作在编辑器中可用 + Editor editor = e.getData(CommonDataKeys.EDITOR); + e.getPresentation().setEnabledAndVisible(editor != null); + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/ai/MyCompletionContributor.java b/athena-all/src/main/java/run/mone/ultraman/ai/MyCompletionContributor.java index c3eee7b75..a18d42a58 100644 --- a/athena-all/src/main/java/run/mone/ultraman/ai/MyCompletionContributor.java +++ b/athena-all/src/main/java/run/mone/ultraman/ai/MyCompletionContributor.java @@ -7,8 +7,8 @@ import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.*; import com.intellij.util.ProcessingContext; -import run.mone.m78.ip.common.ProjectCache; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.common.ProjectCache; +import com.xiaomi.youpin.tesla.ip.service.CodeService; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/ultraman/background/AiBackgroundTask.java b/athena-all/src/main/java/run/mone/ultraman/background/AiBackgroundTask.java new file mode 100644 index 000000000..483582af6 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/background/AiBackgroundTask.java @@ -0,0 +1,44 @@ +package run.mone.ultraman.background; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * @author goodjava@qq.com + * @date 2024/6/1 21:10 + */ +public class AiBackgroundTask extends Task.Backgroundable { + + private volatile boolean isCancelled = false; + + private CountDownLatch latch = new CountDownLatch(1); + + public AiBackgroundTask(Project project, String title) { + super(project, title); + } + + @Override + public void run(ProgressIndicator progressIndicator) { + progressIndicator.setIndeterminate(false); + progressIndicator.setFraction(0.0); + while (!isCancelled && !progressIndicator.isCanceled()) { + try { + latch.await(1, TimeUnit.MINUTES); + } catch (Throwable ignore) { + + } finally { + break; + } + } + } + + public void cancel() { + isCancelled = true; + latch.countDown(); + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/background/AiCode.java b/athena-all/src/main/java/run/mone/ultraman/background/AiCode.java index 522d483a3..010cdc51b 100644 --- a/athena-all/src/main/java/run/mone/ultraman/background/AiCode.java +++ b/athena-all/src/main/java/run/mone/ultraman/background/AiCode.java @@ -3,12 +3,13 @@ import com.google.gson.Gson; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.common.ChromeUtils; -import run.mone.m78.ip.common.Safe; -import run.mone.m78.ip.util.UltramanConsole; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; import lombok.Data; +import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; diff --git a/athena-all/src/main/java/run/mone/ultraman/background/AthenaEditorTask.java b/athena-all/src/main/java/run/mone/ultraman/background/AthenaEditorTask.java index 6f76fb1fd..6f0c10d3e 100644 --- a/athena-all/src/main/java/run/mone/ultraman/background/AthenaEditorTask.java +++ b/athena-all/src/main/java/run/mone/ultraman/background/AthenaEditorTask.java @@ -5,11 +5,11 @@ import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsContexts; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.bo.PromptContext; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.bo.PromptContext; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/ultraman/background/AthenaTask.java b/athena-all/src/main/java/run/mone/ultraman/background/AthenaTask.java index 6cb86f1fe..fd73e8a0b 100644 --- a/athena-all/src/main/java/run/mone/ultraman/background/AthenaTask.java +++ b/athena-all/src/main/java/run/mone/ultraman/background/AthenaTask.java @@ -1,34 +1,54 @@ package run.mone.ultraman.background; import com.google.common.base.Function; +import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Stopwatch; +import com.google.common.collect.Sets; +import com.google.gson.JsonObject; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsContexts; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.ModelRes; -import run.mone.m78.ip.bo.PromptContext; -import run.mone.m78.ip.bo.ZAddrRes; -import run.mone.m78.ip.bo.robot.AiChatMessage; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; -import run.mone.m78.ip.bo.robot.Role; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.service.CodeService; -import run.mone.m78.ip.util.UltramanConsole; +import com.xiaomi.youpin.tesla.ip.bo.*; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.bo.z.ZKnowledgeRes; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.EditorUtils; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; +import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.mutable.MutableBoolean; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.bo.AthenaMethodInfo; +import run.mone.ultraman.bo.CodeReq; +import run.mone.ultraman.common.CodeUtils; +import run.mone.ultraman.common.ImportCode; +import run.mone.ultraman.service.AthenaCodeService; +import run.mone.ultraman.state.PromptAndFunctionProcessor; + +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** @@ -51,12 +71,17 @@ public class AthenaTask extends Task.Backgroundable { private String text; - private Map params; + @Getter + private Map params = new HashMap<>(); @Setter private boolean format = true; @Setter + private GenerateCodeReq req; + + @Setter + @Getter private PromptContext promptContext; private static final String METHOD_CONTEXT = "method_context"; @@ -65,13 +90,16 @@ public class AthenaTask extends Task.Backgroundable { private static final String RESOURCE_CONTEXT = "resource_context"; - private static final String CONTEXT = "context"; + private static final String PO_CONTEXT = "po_context"; + + public static final String CONTEXT = "context"; //chat(聊天窗口) editor(ide中) @Setter private String type = "chat"; @Setter + @Getter private Runnable initRunnable; @@ -83,6 +111,10 @@ public AthenaTask(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull this.params = params; } + public AthenaTask(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title) { + super(project, title); + } + @SneakyThrows @Override public void run(@NotNull ProgressIndicator progressIndicator) { @@ -90,15 +122,16 @@ public void run(@NotNull ProgressIndicator progressIndicator) { initRunnable.run(); } + //参数的一些替换,比如翻译用中文 + extractPrefixedUserLabelsToParams(); + String scope = ""; if (null != this.promptContext) { - callResourceContext(); - callMethodContext(); - callModuleContext(); + initContexts(); scope = this.promptContext.getScope(); } - callContextSize(); + calculateAndOptimizeRequestSize(); ZAddrRes zAddrRes = Prompt.zAddrRes(); if (CollectionUtils.isNotEmpty(zAddrRes.getModels())) { @@ -118,15 +151,64 @@ public void run(@NotNull ProgressIndicator progressIndicator) { CountDownLatch countDownLatch = new CountDownLatch(1); UltramanConsole.append(project, "\ncall prompt begin:" + promptName + " scope:" + scope); AiCode aiCode = getAiCode(progressIndicator, countDownLatch); + Stopwatch sw = Stopwatch.createStarted(); - //一点一点的生成代码 - CodeService.generateCodeWithAi5(GenerateCodeReq.builder().format(format).promptName(promptName).project(project).build(), project, promptName, new String[]{text}, params, (p, code) -> { - }, aiCode); - //最多等1分钟 - countDownLatch.await(3, TimeUnit.MINUTES); - String text = aiCode.getMarkDownText(); + String text = ""; + if (!LabelUtils.isOpen(this.project, req.getPromptInfo(), "call_json")) { + //一点一点的生成代码 + CodeService.generateCodeWithAi5(GenerateCodeReq.builder().format(format).promptName(promptName).project(project).build(), project, promptName, new String[]{text}, params, (p, code) -> { + }, aiCode); + //最多等3分钟 + countDownLatch.await(5, TimeUnit.MINUTES); + text = aiCode.getMarkDownText(); + } else { + //直接调用返回json的接口(目前代码补全会走到这里) + JsonObject obj = PromptAndFunctionProcessor.callPrompt(this.project, req.getPromptInfo(), convertMap(params)); + log.info("{}", obj); + text = obj.get("code").getAsString(); + int offset = EditorUtils.moveCursorToMethodEndIfOutside(req.getEditor(), req.getPsiMethod(), req.getOffset()); + CodeService.insertCode(this.project, text, false, offset, req.getEditor()); + } + // 上报生成信息 + String finalText = text; UltramanConsole.append(project, "call prompt finish:" + promptName + " use time:" + sw.elapsed(TimeUnit.SECONDS) + "s\n"); ProjectAiMessageManager.getInstance().appendMsg(project, AiChatMessage.builder().id(aiCode.getMessageId()).role(Role.assistant).message(text).data(text).build()); + + CodeUtils.uploadCodeGenInfo(getInfo(finalText)); + } + + private M78CodeGenerationInfo getInfo(String code){ + M78CodeGenerationInfo info = new M78CodeGenerationInfo(); + info.setCodeLinesCount(CodeUtils.getLineCnt(code, false)); + info.setAnnotation(CodeUtils.checkLineStartsWithComment(this.req.getChatComment())); + info.setProjectName(this.project.getName()); + info.setClassName(this.req.getClassName()); + info.setMethodName("GENERATED"); + return info; + } + + public void initContexts() { + Safe.run(() -> callResourceContext()); + Safe.run(() -> callPoContext()); + Safe.run(() -> callMethodContext()); + Safe.run(() -> callModuleContext()); + } + + private void extractPrefixedUserLabelsToParams() { + Map userLabels = req.getPromptInfo().getLabels(); + if (MapUtils.isNotEmpty(userLabels)) { + userLabels.entrySet().stream().forEach(it -> { + if (it.getKey().startsWith("__")) { + this.params.put(it.getKey(), it.getValue()); + } + }); + } + } + + //把一个Map转换为Map(method) + public Map convertMap(Map stringMap) { + return stringMap.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> (Object) e.getValue())); } @@ -138,13 +220,80 @@ public void run(@NotNull ProgressIndicator progressIndicator) { * @return */ @NotNull - private AiCode getAiCode(@NotNull ProgressIndicator progressIndicator, CountDownLatch countDownLatch) { - return null; + protected AiCode getAiCode(@NotNull ProgressIndicator progressIndicator, CountDownLatch countDownLatch) { + //方法注释 + if (type.equals("method_comment")) { + return new AiCode(progressIndicator, countDownLatch, this.project, message -> { + ImportCode importCode = new ImportCode(); + importCode.setProject(project); + importCode.setEditor(promptContext.getEditor()); + + if (message.getType().equals(AiMessageType.begin)) { + ApplicationManager.getApplication().invokeLater(() -> { + CodeService.moveToMethodAndInsertLine(project); + }); + } + + if (message.getType().equals(AiMessageType.process)) { + importCode.append(message.getText()); + } + }); + } + //在编辑器添加代码(添加到ide中) + else if (type.equals("edit")) { + ImportCode importCode = new ImportCode(); + importCode.setProject(project); + importCode.setEditor(promptContext.getEditor()); + return new AiCode(progressIndicator, countDownLatch, this.project, message -> { + //开始(调整光标位置) + if (message.getType().equals(AiMessageType.begin)) { + String comment = params.get("code"); + ProjectAiMessageManager.getInstance().appendMsg(project, AiChatMessage.builder().role(Role.user).message(comment).data(comment).build()); + + ApplicationManager.getApplication().invokeLater(() -> { + CodeService.moveCaretToEndOfLine(this.promptContext.getEditor()); + CodeService.writeCode2(project, this.promptContext.getEditor(), "\n"); + }); + } + //处理中(添加内容到ide) + if (message.getType().equals(AiMessageType.process)) { + importCode.append(message.getText()); + } + }); + } else { + return new AiCode(progressIndicator, countDownLatch, this.project); + } } //计算请求的size,有写大小需要优化(最终大小需要低于3500) - private void callContextSize() { + public void calculateAndOptimizeRequestSize() { + String resourceContext = this.params.getOrDefault(RESOURCE_CONTEXT, ""); + String poContext = this.params.getOrDefault(PO_CONTEXT, ""); + String moduleContext = this.params.getOrDefault(MODULE_CONTEXT, ""); + String methodContext = this.params.getOrDefault(METHOD_CONTEXT, ""); + //prompt的长度 + int promptSize = 1460; + + int i = resourceContext.length() + methodContext.length() + moduleContext.length() + promptSize; + NotificationCenter.notice(this.project, String.format("Athena Task call size resource:%s class:%s module:%s prompt len:%s total:%s", + resourceContext.length(), methodContext.length(), moduleContext.length(), promptSize, i + ), true); + + if (i > AthenaContext.ins().getMaxTokenNum()) { + moduleContext = ""; + } + + //拼接处完整的上下文 + this.params.put(CONTEXT, Joiner.on("\n\n").join(resourceContext, poContext, moduleContext)); + + if (this.params.get(CONTEXT).length() > 30) { + UltramanConsole.append(this.project, "context:\n" + this.params.get(CONTEXT)); + } + } + + public String getContext() { + return this.params.getOrDefault(CONTEXT, ""); } @@ -157,15 +306,99 @@ private void callContextSize() { }; private void callModuleContext() { - + if ((null != this.promptContext.getScope()) && (this.promptContext.getScope().equals("module") || this.promptContext.getScope().equals("project"))) { + String moduleName = ""; + if (this.promptContext.getScope().equals("module")) { + moduleName = this.promptContext.getModule(); + } + //计算module中的context + List list = AthenaCodeService.getCodeList(CodeReq.builder().projectName(this.promptContext.getProject()).moduleName(moduleName).requirement(promptContext.getComment()).build()); + + if (null != this.promptContext.getResourceBeanList() && (this.promptContext.getResourceBeanList().size() > 0) && (null != list && list.size() > 0)) { + list = list.stream().filter(it -> { + MutableBoolean mb = new MutableBoolean(true); + Safe.run(() -> { + AthenaClassInfo ci = AthenaCodeService.classInfo(it.getContent()); + boolean v = promptContext.getResourceBeanList().stream().map(f).collect(Collectors.toList()).contains(ci.getName()) + || + (Sets.intersection(Sets.newHashSet(promptContext.getResourceBeanList().stream().map(f).collect(Collectors.toList())), Sets.newHashSet(ci.getInterfaceList())).size() > 0); + mb.setValue(!v); + }); + return (boolean) mb.getValue(); + }).collect(Collectors.toList()); + } + //如果codeserver 有相关代码,则相信code server 中的代码(不然数量太大,很难处理) + String moduleContext = ""; + if (null != list && list.size() > 0) { + int limitNum = AthenaContext.ins().gptModel().getModuleClassNum(); + moduleContext = list.stream().limit(limitNum).map(it -> it.getContent()).collect(Collectors.joining("\n")); + UltramanConsole.append(this.project, "\nmodule context:" + moduleContext + "\n"); + } + this.params.put(MODULE_CONTEXT, moduleContext); + } } //引入一些class内部的方法(能起到一定的教学作用) private void callMethodContext() { + //计算引入哪些方法(会调用chatgpt) + if (null != this.promptContext.getMethodCodeList()) { + List list = this.promptContext.getMethodCodeList(); + int methodLimitNum = 2; + if (!AthenaContext.ins().gptModel().isOptimizeTokens()) { + methodLimitNum = 10; + list.stream().forEach(it -> it.setScore(100)); + } else { + list.stream().forEach(it -> { + try { + Map map = new HashMap<>(); + map.put("method", it.getCode()); + map.put("requirement", promptContext.getComment()); + //这里有个问题,调用次数过多,会超过某些module的限制 + int value = Integer.valueOf(AthenaCodeService.callProxy(this.project, map, "requirement", 5).value()); + it.setScore(value); + UltramanConsole.append(this.project, "method score:" + value + "\n" + it.getCode() + "\n\n"); + try { + TimeUnit.MILLISECONDS.sleep(100); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + }); + } + + String fieldCode = this.promptContext.getFieldCodeList().stream().map(it -> it.getCode() + "\n").collect(Collectors.joining()); + List newList = list.stream().sorted((a, b) -> b.getScore() - a.getScore()).filter(it -> it.getScore() > 30).collect(Collectors.toList()); + if (newList.size() == 0) { + newList = list.stream().sorted((a, b) -> b.getScore() - a.getScore()).limit(1).collect(Collectors.toList()); + } else { + newList = list.stream().limit(methodLimitNum).collect(Collectors.toList()); + } + String classCode = newList.stream().map(it -> it.getCode()).collect(Collectors.joining("\n\n")); + classCode = "public class " + promptContext.getClazzName() + "{\n" + fieldCode + classCode + "\n}"; + UltramanConsole.append(this.project, "class:\n" + classCode + "\n" + "size:" + classCode.length() + "\n\n"); + this.params.put("class", classCode); + this.params.put(METHOD_CONTEXT, classCode); + } } private void callResourceContext() { + //计算引入哪些资源(会调用chatgpt) + if (null != this.promptContext.getResourceCode()) { + //获取@Resource引入的代码 + String resource = PromptService.getResourceFromAi(this.project, this.params, this.promptContext, this.promptContext.getResourceCode()); + this.params.put(RESOURCE_CONTEXT, resource); + UltramanConsole.append(project, "resource:\n" + resource + "\n"); + } + } + //计算po的上下文引入 + private void callPoContext() { + if (null != this.promptContext.getPoClassInfos()) { + this.params.put(PO_CONTEXT, Joiner.on("\n").join(this.promptContext.getPoClassInfos().stream().map(it -> it.getCode()).collect(Collectors.toList()))); + UltramanConsole.append(project, "po:\n" + this.params.get(PO_CONTEXT) + "\n"); + } } diff --git a/athena-all/src/main/java/run/mone/ultraman/background/BotTask.java b/athena-all/src/main/java/run/mone/ultraman/background/BotTask.java new file mode 100644 index 000000000..163df35b1 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/background/BotTask.java @@ -0,0 +1,26 @@ +package run.mone.ultraman.background; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NlsContexts; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author goodjava@qq.com + * @date 2024/6/2 22:29 + */ +public class BotTask extends Task.Backgroundable { + + public BotTask(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title) { + super(project, title); + } + + @Override + public void run(@NotNull ProgressIndicator indicator) { + indicator.setIndeterminate(false); + + + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/background/EditorAiCode.java b/athena-all/src/main/java/run/mone/ultraman/background/EditorAiCode.java index a2d1779e4..74130cce3 100644 --- a/athena-all/src/main/java/run/mone/ultraman/background/EditorAiCode.java +++ b/athena-all/src/main/java/run/mone/ultraman/background/EditorAiCode.java @@ -2,9 +2,9 @@ import com.google.gson.Gson; import com.intellij.openapi.progress.ProgressIndicator; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.common.Safe; import lombok.extern.slf4j.Slf4j; import java.time.Duration; diff --git a/athena-all/src/main/java/run/mone/ultraman/bo/AthenaClassInfo.java b/athena-all/src/main/java/run/mone/ultraman/bo/AthenaClassInfo.java index e3fc40f2f..aa0979af3 100644 --- a/athena-all/src/main/java/run/mone/ultraman/bo/AthenaClassInfo.java +++ b/athena-all/src/main/java/run/mone/ultraman/bo/AthenaClassInfo.java @@ -16,6 +16,8 @@ public class AthenaClassInfo { private String name; + private String packagePath; + private String classCode; private String md5; @@ -24,7 +26,13 @@ public class AthenaClassInfo { private List publicMethodList; + private List imports; + @Builder.Default private List interfaceList = new ArrayList<>(); + public String getClassName() { + return this.getPackagePath() + "." + this.getName(); + } + } diff --git a/athena-all/src/main/java/run/mone/ultraman/bo/DesensitizeReq.java b/athena-all/src/main/java/run/mone/ultraman/bo/DesensitizeReq.java new file mode 100644 index 000000000..5388d45ec --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/bo/DesensitizeReq.java @@ -0,0 +1,25 @@ +package run.mone.ultraman.bo; + +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author goodjava@qq.com + * @date 2024/2/4 16:22 + */ +@Data +@Builder +public class DesensitizeReq implements Serializable { + + private String text; + + private String langType; + + private boolean aiDesensitizeFlag; + + private String zzToken; + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/bo/PoClassInfo.java b/athena-all/src/main/java/run/mone/ultraman/bo/PoClassInfo.java new file mode 100644 index 000000000..18ae99e84 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/bo/PoClassInfo.java @@ -0,0 +1,18 @@ +package run.mone.ultraman.bo; + +import lombok.Builder; +import lombok.Data; + +/** + * @author goodjava@qq.com + * @date 2024/1/29 14:24 + */ +@Data +@Builder +public class PoClassInfo { + + private String name; + + private String code; + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/bo/Version.java b/athena-all/src/main/java/run/mone/ultraman/bo/Version.java index 51dbf716c..1c0432b2e 100644 --- a/athena-all/src/main/java/run/mone/ultraman/bo/Version.java +++ b/athena-all/src/main/java/run/mone/ultraman/bo/Version.java @@ -1,15 +1,30 @@ package run.mone.ultraman.bo; +import com.xiaomi.youpin.tesla.ip.common.VersionUtil; +import lombok.Data; + import java.io.Serializable; /** * @author goodjava@qq.com * @date 2023/6/7 14:06 */ +@Data public class Version implements Serializable { + private String ATHENA_TYPE = "IDEA"; + @Override public String toString() { - return "0.0.1:2024-01-12-1"; + return ATHENA_TYPE + ":" + getVersion(); + } + + public String getVersion() { + return VersionUtil.getAthenaPluginVersion(); } + + public String getName() { + return ATHENA_TYPE; + } + } diff --git a/athena-all/src/main/java/run/mone/ultraman/common/ActionEventUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/ActionEventUtils.java index 71ca1055e..1c87f4c38 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/ActionEventUtils.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/ActionEventUtils.java @@ -1,10 +1,21 @@ package run.mone.ultraman.common; +import com.intellij.execution.Executor; +import com.intellij.execution.ExecutorRegistry; +import com.intellij.execution.RunManager; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.application.ApplicationConfiguration; +import com.intellij.execution.application.ApplicationConfigurationType; +import com.intellij.execution.configurations.ConfigurationFactory; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.ui.speedSearch.SpeedSearchSupply; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author goodjava@qq.com @@ -13,6 +24,105 @@ public class ActionEventUtils { + /** + * 进行 Java 应用配置的设置与执行 + * 获取数据上下文和项目 + * 创建运行管理器、配置工厂、配置设置等 + * 设置配置的主类名和程序参数 + * 添加和选择配置 + * 获取执行器,构建执行环境 + * 获取程序运行器,若不为空则异步执行 + */ + public static void setupAndExecuteJavaAppConfiguration(String className, String params, Project _project) { + Project project = null; + + // 获取当前的数据上下文 + if (null == _project) { + DataContext dataContext = DataManager.getInstance().getDataContext(); + project = CommonDataKeys.PROJECT.getData(dataContext); + } else { + project = _project; + } + + if (project == null) { + return; // 如果没有项目,直接返回 + } + + // 获取 RunManager + RunManager runManager = RunManager.getInstance(project); + + // 创建一个新的 Java 应用程序运行配置 + ConfigurationFactory factory = ApplicationConfigurationType.getInstance().getConfigurationFactories()[0]; + RunnerAndConfigurationSettings configurationSettings = runManager.createConfiguration("MioneRun", factory); + ApplicationConfiguration applicationConfiguration = (ApplicationConfiguration) configurationSettings.getConfiguration(); + + // 设置 main 函数的参数 + applicationConfiguration.setMainClassName(className); // 设置主类名 + applicationConfiguration.setProgramParameters(params); // 设置参数 + + // 将新的运行配置添加到 RunManager + runManager.addConfiguration(configurationSettings); + runManager.setSelectedConfiguration(configurationSettings); + + Executor executor = ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID); + + // 创建 ExecutionEnvironment + ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder.create(executor, configurationSettings.getConfiguration()); + ExecutionEnvironment environment = builder.build(); + + // 获取 ProgramRunner + ProgramRunner runner = ProgramRunner.getRunner(DefaultRunExecutor.EXECUTOR_ID, environment.getRunProfile()); + + if (runner != null) { + // 在事件调度线程中执行运行配置 + ApplicationManager.getApplication().invokeLater(() -> { + try { + runner.execute(environment); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + } + + + /** + * 执行默认的运行操作。 + * 首先获取当前的数据上下文,然后获取默认的运行动作。 + * 如果该动作存在,则创建一个动作事件并执行该动作。 + */ + public static void executeDefaultRunAction() { + // 获取当前的数据上下文 + DataContext dataContext = DataManager.getInstance().getDataContext(); + // 获取 "Run" 功能对应的 Action + AnAction runAction = ActionManager.getInstance().getAction(IdeActions.ACTION_DEFAULT_RUNNER); + // 模拟触发 "Run" 功能的 Action + if (runAction != null) { + AnActionEvent event = AnActionEvent.createFromDataContext( + ActionPlaces.UNKNOWN, null, dataContext + ); + runAction.actionPerformed(event); + } + } + + /** + * 启动调试器的方法。首先获取当前数据上下文,然后获取默认的调试器动作。如果该动作存在,则创建一个动作事件并执行该动作。 + */ + public static void startDebugger() { + // 获取当前的数据上下文 + DataContext dataContext = DataManager.getInstance().getDataContext(); + // 获取 "Run" 功能对应的 Action + AnAction runAction = ActionManager.getInstance().getAction(IdeActions.ACTION_DEFAULT_DEBUGGER); + // 模拟触发 "Run" 功能的 Action + if (runAction != null) { + AnActionEvent event = AnActionEvent.createFromDataContext( + ActionPlaces.UNKNOWN, null, dataContext + ); + runAction.actionPerformed(event); + } + } + + public static AnActionEvent createAnAction(Project project, String data) { // 创建一个新的 Presentation 对象 Presentation presentation = new Presentation(); diff --git a/athena-all/src/main/java/run/mone/ultraman/common/Code.java b/athena-all/src/main/java/run/mone/ultraman/common/Code.java index f01dca91a..6a09111d1 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/Code.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/Code.java @@ -9,8 +9,8 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.service.CodeService; import lombok.Data; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/ultraman/common/CodeUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/CodeUtils.java index 6af6d2ea2..4e402f56b 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/CodeUtils.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/CodeUtils.java @@ -1,5 +1,19 @@ package run.mone.ultraman.common; +import com.intellij.openapi.application.ApplicationInfo; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.xiaomi.youpin.infra.rpc.Result; +import com.xiaomi.youpin.tesla.ip.bo.Action; +import com.xiaomi.youpin.tesla.ip.bo.M78CodeGenerationInfo; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.M78Service; +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.Version; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -8,10 +22,13 @@ * @author goodjava@qq.com * @date 2023/4/20 23:01 */ +@Slf4j public class CodeUtils { + private static final int CODE_STATISTICS_SOURCE_IDEA = 1; + public static String format(String code) { - return code.replaceFirst("\n+", "").replaceAll("import.*\n",""); + return code.replaceFirst("\n+", "").replaceAll("import.*\n", ""); } public static String formatRemoveEnter(String code) { @@ -23,17 +40,92 @@ public static String formatRemoveEnter1(String code) { } public static List getImportList(String code) { - return Arrays.stream(code.split("\n|;")).filter(it->it.startsWith("import")).map(it->it.replaceAll(";|import| ","")).collect(Collectors.toList()); + return Arrays.stream(code.split("\n|;")).filter(it -> it.startsWith("import")).map(it -> it.replaceAll(";|import| ", "")).collect(Collectors.toList()); } public static List getImportList2(String code) { - return Arrays.stream(code.split("\n|;")).filter(it->it.startsWith("import")).map(it->it.replaceAll(";|import","")).collect(Collectors.toList()); + return Arrays.stream(code.split("\n|;")).filter(it -> it.startsWith("import")).map(it -> it.replaceAll(";|import", "")).collect(Collectors.toList()); } public static String getComment(String code) { - return code.replaceAll("/\\*\\*|\\*/| +\\* ","").replaceAll("

","\n"); + return code.replaceAll("/\\*\\*|\\*/| +\\* ", "").replaceAll("

", "\n"); + } + + /** + * upload statistics + */ + public static void uploadCodeGenInfo(M78CodeGenerationInfo info) { + SafeRun.run(() -> { + long now = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); + info.setCtime(now); + info.setUtime(now); + info.setSource(CODE_STATISTICS_SOURCE_IDEA); + info.setUsername(AthenaContext.ins().getUserName()); + info.setPluginVersion(new Version().toString()); + info.setIp(AthenaContext.ins().getLocalAddress()); + info.setSystemVersion(System.getProperty("os.name").toLowerCase()); + info.setIdeVersion(ApplicationInfo.getInstance().getBuild().asString()); + Result ok = M78Service.uploadCodeInfo(GsonUtils.gson.toJson(info)); + log.info("upload code info, status:{}", ok); + }); + } + + public static void uploadCodeGenInfo(String code, String comment, String projectName, String className) { + uploadCodeGenInfo(Action.GENERATE_CODE.getCode(), code, comment, projectName, className); + } + + public static void uploadCodeGenInfo(int actionCode, String code, String comment, Project project) { + String projectName = project == null ? "" : project.getName(); + PsiClass psiClass = CodeService.getPsiClassInRead(project); + String className = psiClass == null ? "" : psiClass.getName(); + uploadCodeGenInfo(actionCode, code, comment, projectName, className); } + public static void uploadCodeGenInfo(int actionCode, String code, String comment, String projectName, String className) { + M78CodeGenerationInfo info = new M78CodeGenerationInfo(); + info.setCodeLinesCount(CodeUtils.getLineCnt(code, false)); + info.setAnnotation(CodeUtils.checkLineStartsWithComment(comment)); + info.setProjectName(projectName); + info.setClassName(className); + info.setMethodName("GENERATED"); + info.setAction(actionCode); + uploadCodeGenInfo(info); + } + + public static void uploadCodeGenInfo(int actionCode, String projectName, String className, String methodName) { + M78CodeGenerationInfo info = new M78CodeGenerationInfo(); + info.setClassName(className); + info.setProjectName(projectName); + info.setMethodName(methodName == null ? "" : methodName); + info.setCodeLinesCount(0); + info.setAction(actionCode); + uploadCodeGenInfo(info); + } + + public static int getLineCnt(String code, boolean markDown) { + int lineCount = 1; // 如果字符串不为空至少有一行 + + for (int i = 0; i < code.length(); i++) { + if (code.charAt(i) == '\n') { + lineCount++; + } + } + if (markDown) { + return Math.max(lineCount - 2, 0); + } + return lineCount; + } + + // 帮我生成一个方法,用于判断当前行是否是//开头,如果是,则返回这行,如果不是,返回null。入参是String,返回值是String,注意判断String非空,并且在判断前要trim + public static String checkLineStartsWithComment(String line) { + if (line != null && !line.trim().isEmpty()) { + String trimmedLine = line.trim(); + if (trimmedLine.startsWith("//") || trimmedLine.startsWith("/**")) { + return trimmedLine; + } + } + return null; + } public static void main(String[] args) { String code = " /**\n" + diff --git a/athena-all/src/main/java/run/mone/ultraman/common/FunctionReqUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/FunctionReqUtils.java index 115a370d8..75f069f0e 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/FunctionReqUtils.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/FunctionReqUtils.java @@ -2,8 +2,8 @@ import com.google.common.collect.Maps; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.util.GitUtils; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.util.GitUtils; import run.mone.ultraman.AthenaContext; import java.util.List; diff --git a/athena-all/src/main/java/run/mone/ultraman/common/GitProjectOpener.java b/athena-all/src/main/java/run/mone/ultraman/common/GitProjectOpener.java index b1cd0507c..e8eef319f 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/GitProjectOpener.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/GitProjectOpener.java @@ -10,5 +10,25 @@ public class GitProjectOpener { public static void openGitProject(String projectPath) { + // 获取本地文件系统的实例 + LocalFileSystem localFileSystem = LocalFileSystem.getInstance(); + + // 使用项目路径找到对应的 VirtualFile 实例 + VirtualFile projectDirectory = localFileSystem.refreshAndFindFileByIoFile(new File(projectPath)); + + // 检查项目目录是否存在 + if (projectDirectory == null) { + System.err.println("Project directory not found: " + projectPath); + return; + } + + Project project = ProjectUtil.openOrImport(projectDirectory.getPath(), null, true); + + // 如果项目打开成功,则 project 不为 null + if (project != null) { + System.out.println("Project opened successfully: " + project.getName()); + } else { + System.err.println("Failed to open project: " + projectPath); + } } } diff --git a/athena-all/src/main/java/run/mone/ultraman/common/GsonUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/GsonUtils.java index 276a94da4..71c94caf8 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/GsonUtils.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/GsonUtils.java @@ -1,6 +1,9 @@ package run.mone.ultraman.common; import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.util.function.Supplier; /** * @author goodjava@qq.com @@ -10,4 +13,26 @@ public class GsonUtils { public static Gson gson = new Gson(); + + public static boolean get(JsonObject obj, String key, boolean defaultValue) { + if (obj.has(key)) { + return Boolean.valueOf(obj.get(key).getAsString()); + } + return defaultValue; + } + + public static String get(JsonObject obj, String key, String defaultValue) { + if (obj.has(key)) { + return obj.get(key).getAsString(); + } + return defaultValue; + } + + public static String get(JsonObject obj, String key, Supplier supplier) { + if (obj.has(key)) { + return obj.get(key).getAsString(); + } + return supplier.get(); + } + } diff --git a/athena-all/src/main/java/run/mone/ultraman/common/ImportCode.java b/athena-all/src/main/java/run/mone/ultraman/common/ImportCode.java index cc059a12b..dfacb84b8 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/ImportCode.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/ImportCode.java @@ -2,10 +2,13 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.util.MarkdownFilter; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import java.util.function.Consumer; + /** * @author goodjava@qq.com *

@@ -23,6 +26,13 @@ public class ImportCode { private boolean isImport = false; + private MarkdownFilter markdownFilter = new MarkdownFilter(new Consumer() { + @Override + public void accept(String s) { + CodeService.writeCode2(project, editor, s); + } + }); + public void append(String str) { if (isImportBegin(str)) { isImport = true; @@ -33,7 +43,8 @@ public void append(String str) { } else if (isImport) { importBuilder.append(str); } else { - CodeService.writeCode2(project, editor, str); + //过滤不必要的markdown标签 + markdownFilter.accept(str); } } diff --git a/athena-all/src/main/java/run/mone/ultraman/common/SafeRun.java b/athena-all/src/main/java/run/mone/ultraman/common/SafeRun.java index d5e69d81b..a0626a4d3 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/SafeRun.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/SafeRun.java @@ -1,16 +1,19 @@ package run.mone.ultraman.common; +import lombok.extern.slf4j.Slf4j; + /** * @author goodjava@qq.com * @date 2023/4/19 14:30 */ +@Slf4j public class SafeRun { public static void run(Runnable runnable) { try { runnable.run(); } catch (Throwable ex) { - ex.printStackTrace(); + log.error(ex.getMessage(), ex); } } diff --git a/athena-all/src/main/java/run/mone/ultraman/common/ScopeEnum.java b/athena-all/src/main/java/run/mone/ultraman/common/ScopeEnum.java new file mode 100644 index 000000000..c9323a567 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/common/ScopeEnum.java @@ -0,0 +1,22 @@ +package run.mone.ultraman.common; + +/** + * @author goodjava@qq.com + * @date 2024/6/26 08:54 + */ +public enum ScopeEnum { + + SMethod("method"), + SClass("class"), + SModule("module"), + SProject("project") + ; + + + private String name; + + ScopeEnum(String name) { + this.name = name; + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/common/TemplateUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/TemplateUtils.java index 62ddd7cc4..c80299251 100644 --- a/athena-all/src/main/java/run/mone/ultraman/common/TemplateUtils.java +++ b/athena-all/src/main/java/run/mone/ultraman/common/TemplateUtils.java @@ -2,6 +2,7 @@ import com.google.common.collect.Maps; import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.tuple.Pair; import org.beetl.core.Configuration; import org.beetl.core.Function; import org.beetl.core.GroupTemplate; @@ -23,12 +24,12 @@ public static String renderTemplate(String template, Map m) { return renderTemplate(template, m, Lists.newArrayList()); } - public static String renderTemplate(String template, Map m, List functionList) { + public static String renderTemplate(String template, Map m, List> functionList) { try { StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader(); Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg, cfg.getClass().getClassLoader()); - functionList.forEach(it -> gt.registerFunction(it.toString(), it)); + functionList.forEach(it -> gt.registerFunction(it.getKey(), it.getValue())); Template t = gt.getTemplate(template); m.forEach((k, v) -> t.binding(k, v)); String str = t.render(); diff --git a/athena-all/src/main/java/run/mone/ultraman/common/TestRunnerUtils.java b/athena-all/src/main/java/run/mone/ultraman/common/TestRunnerUtils.java new file mode 100644 index 000000000..07ea2e94b --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/common/TestRunnerUtils.java @@ -0,0 +1,83 @@ +package run.mone.ultraman.common; + +import com.intellij.execution.PsiLocation; +import com.intellij.execution.RunManager; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.junit.JUnitConfiguration; +import com.intellij.execution.junit.JUnitConfigurationType; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import lombok.SneakyThrows; +import org.apache.commons.lang3.tuple.Pair; +import run.mone.ultraman.common.adapter.TestRunnerProcessAdapter; + +import java.util.function.Consumer; + +/** + * @author goodjava@qq.com + * @date 2024/6/29 09:03 + */ +public class TestRunnerUtils { + + /** + * 运行测试的方法 + * 从数据管理器获取数据上下文,得到相关类,获取类名 + * 尝试根据类名获取测试类并获取其方法 + * 对有测试注解的方法进行 JUnit 测试并根据结果显示相应消息框 + * 处理类未找到的异常情况 + */ + @SneakyThrows + public static void runTest(Project project, String methodName, Consumer> consumer) { + PsiClass psiClass = CodeService.getPsiClass(project); + String className = psiClass.getQualifiedName(); + + PsiMethod[] methods = psiClass.getMethods(); + + // 逐个执行测试方法 + for (PsiMethod method : methods) { + if (hasTestAnnotation(method, methodName)) { + RunnerAndConfigurationSettings runSettings = RunManager.getInstance(project).createConfiguration(className + "." + method.getName(), JUnitConfigurationType.getInstance().getConfigurationFactories()[0]); + JUnitConfiguration configuration = (JUnitConfiguration) runSettings.getConfiguration(); + + // 设置测试类和方法 + JUnitConfiguration.Data data = configuration.getPersistentData(); + data.setMainClass(psiClass); + //这个很关键,保证是值测试一个method,而不是class + data.setTestMethod(PsiLocation.fromPsiElement(method)); + data.setTestMethodName(method.getName()); + + ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder + .createOrNull(DefaultRunExecutor.getRunExecutorInstance(), runSettings); + + ExecutionEnvironment environment = builder.build(); + + ProgramRunner runner = ProgramRunner.getRunner(DefaultRunExecutor.EXECUTOR_ID, environment.getRunProfile()); + + //直接执行,并且捕获异常,然后问ai修复 + runner.execute(environment, descriptor -> descriptor.getProcessHandler().addProcessListener(new TestRunnerProcessAdapter(project, consumer))); + + } + } + } + + private static boolean hasTestAnnotation(PsiMethod psiMethod, String methodName) { + if (!psiMethod.getName().equals(methodName)) { + return false; + } + PsiAnnotation[] annotations = psiMethod.getModifierList().getAnnotations(); + for (PsiAnnotation annotation : annotations) { + if (annotation.getQualifiedName() != null && annotation.getQualifiedName().contains("Test")) { + return true; + } + } + return false; + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/common/adapter/TestRunnerProcessAdapter.java b/athena-all/src/main/java/run/mone/ultraman/common/adapter/TestRunnerProcessAdapter.java new file mode 100644 index 000000000..dab25c531 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/common/adapter/TestRunnerProcessAdapter.java @@ -0,0 +1,65 @@ +package run.mone.ultraman.common.adapter; + +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiMethod; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; + +/** + * @author goodjava@qq.com + * @date 2024/6/30 10:47 + */ +@Slf4j +public class TestRunnerProcessAdapter extends ProcessAdapter { + + private List list = new ArrayList<>(); + + private Project project; + + private Consumer> consumer; + + public TestRunnerProcessAdapter(Project project, Consumer> consumer) { + this.project = project; + this.consumer = consumer; + } + + @Override + public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) { + list.add(event.getText()); + + } + + @Override + public void processTerminated(@NotNull ProcessEvent event) { + if (event.getExitCode() == 0) { + log.info("Process finished successfully."); + } else { + log.info("Process finished with errors."); + //发生错误了 + String error = list.stream().filter(it -> it.startsWith("##teamcity[testFailed")).findAny().orElse(""); + //获取当前PsiMethod的方法信息 + String methodStr = ApplicationManager.getApplication().runReadAction((Computable) () -> { + PsiMethod method = CodeService.getMethod(project); + if (!Objects.isNull(method)) { + String methodCode = CodeService.getMethodAndLineNumbers(method); + return methodCode; + } + return ""; + }); + log.info("method:{} \n error:{}", methodStr, error); + consumer.accept(Pair.of(methodStr, error)); + } + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/event/EventListener.java b/athena-all/src/main/java/run/mone/ultraman/event/EventListener.java index 5fdf8c63e..df9866ead 100644 --- a/athena-all/src/main/java/run/mone/ultraman/event/EventListener.java +++ b/athena-all/src/main/java/run/mone/ultraman/event/EventListener.java @@ -1,8 +1,8 @@ package run.mone.ultraman.event; import com.google.common.eventbus.Subscribe; -import run.mone.m78.ip.bo.ClassInfo; -import run.mone.m78.ip.bo.ValueInfo; +import com.xiaomi.youpin.tesla.ip.bo.ClassInfo; +import com.xiaomi.youpin.tesla.ip.bo.ValueInfo; import lombok.Getter; import run.mone.ultraman.bo.PackageInfo; import run.mone.ultraman.bo.ParamsInfo; diff --git a/athena-all/src/main/java/run/mone/ultraman/gutter/AthenaMethodLineMarkerProvider.java b/athena-all/src/main/java/run/mone/ultraman/gutter/AthenaMethodLineMarkerProvider.java new file mode 100644 index 000000000..3bed34f79 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/gutter/AthenaMethodLineMarkerProvider.java @@ -0,0 +1,94 @@ +package run.mone.ultraman.gutter; + +import com.intellij.codeInsight.daemon.LineMarkerInfo; +import com.intellij.codeInsight.daemon.LineMarkerProvider; +import com.intellij.openapi.editor.markup.GutterIconRenderer; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.FunctionUtil; +import com.xiaomi.youpin.tesla.ip.service.PsiMethodUtils; +import com.xiaomi.youpin.tesla.ip.util.EditorUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.ultraman.statusbar.AthenaStatusBarWidget; +import run.mone.ultraman.statusbar.PopUpReq; + +import javax.swing.*; +import java.util.Collection; +import java.util.List; + +import static run.mone.ultraman.statusbar.PopUpReq.POP_ORIGIN_LINE_MARK; + +/** + * @author HawickMason@xiaomi.com + * @date 6/26/24 2:27 PM + */ +public class AthenaMethodLineMarkerProvider implements LineMarkerProvider { + + + private final String icons = "/icons/M2.svg"; + + @Override + public @Nullable LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod) element; + if (isMethodNotConstructor(method)) { + PsiElement firstChild = PsiMethodUtils.getFirstLeafNode(method); + Icon icon = IconLoader.getIcon(icons, getClass()); + TextRange range = method.getNameIdentifier() != null ? method.getNameIdentifier().getTextRange() : method.getModifierList().getTextRange(); + return new LineMarkerInfo<>( + firstChild, + method.getNameIdentifier() != null ? method.getNameIdentifier().getTextRange() : method.getModifierList().getTextRange(), + icon, + FunctionUtil.nullConstant(), + ((mouseEvent, pe) -> { + PsiMethod psiMethod = PsiTreeUtil.getParentOfType(pe, PsiMethod.class); + AthenaStatusBarWidget.popUp(pe.getProject(), null, mouseEvent, PopUpReq.builder().offset(range.getEndOffset()).psiMethod(psiMethod).origin(POP_ORIGIN_LINE_MARK).build()); + }), + GutterIconRenderer.Alignment.LEFT + ); + } + } + + if (element instanceof PsiComment) { + PsiComment psiComment = (PsiComment) element; + PsiElement firstChild = psiComment; + + if (isValidComment(psiComment)) { + Icon icon = IconLoader.getIcon(icons, getClass()); + return new LineMarkerInfo<>( + firstChild, + psiComment.getTextRange(), + icon, + FunctionUtil.nullConstant(), + ((mouseEvent, pc) -> { + AthenaStatusBarWidget.popUp(pc.getProject(), null, mouseEvent, PopUpReq.builder().offset(pc.getTextOffset()).psiComment((PsiComment) pc).origin(POP_ORIGIN_LINE_MARK).build()); + }), + GutterIconRenderer.Alignment.LEFT + ); + } + } + return null; + } + + private static boolean isMethodNotConstructor(PsiMethod method) { + return !method.isConstructor(); + } + + private static boolean isValidComment(PsiComment psiComment) { + return EditorUtils.isNotClassHeaderComment(psiComment) + && EditorUtils.isCommentInsideClass(psiComment) + && !EditorUtils.isCommentInsideMethod(psiComment); + } + + @Override + public void collectSlowLineMarkers(@NotNull List elements, @NotNull Collection> result) { + // No slow line markers to collect + } + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/http/HttpClient.java b/athena-all/src/main/java/run/mone/ultraman/http/HttpClient.java index 065659862..827b01ad4 100644 --- a/athena-all/src/main/java/run/mone/ultraman/http/HttpClient.java +++ b/athena-all/src/main/java/run/mone/ultraman/http/HttpClient.java @@ -4,8 +4,8 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import run.mone.m78.ip.common.ConfigUtils; -import run.mone.m78.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import okhttp3.*; @@ -70,16 +70,19 @@ public static String callHttpServer(String url, String action, String req, boole return callHttpServer(url, action, req, notify, false); } + public static String callHttpServer(String url, String action, String req, boolean notify, boolean useToken) { + return callHttpServer(url, action, req, notify, useToken, 10); + } @SneakyThrows - public static String callHttpServer(String url, String action, String req, boolean notify, boolean useToken) { + public static String callHttpServer(String url, String action, String req, boolean notify, boolean useToken, int timeout) { log.info("call action:{}", action); Stopwatch sw = Stopwatch.createStarted(); try { OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(5, TimeUnit.SECONDS) - .readTimeout(5, TimeUnit.SECONDS) - .writeTimeout(5, TimeUnit.SECONDS) + .connectTimeout(timeout, TimeUnit.SECONDS) + .readTimeout(timeout, TimeUnit.SECONDS) + .writeTimeout(timeout, TimeUnit.SECONDS) .build(); RequestBody body = RequestBody.create(MediaType.parse("application/json"), req); Request.Builder requestBuilder = new Request.Builder(); diff --git a/athena-all/src/main/java/run/mone/ultraman/http/WsClient.java b/athena-all/src/main/java/run/mone/ultraman/http/WsClient.java new file mode 100644 index 000000000..1be8fef4b --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/http/WsClient.java @@ -0,0 +1,112 @@ +package run.mone.ultraman.http; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.AiMessageType; +import com.xiaomi.youpin.tesla.ip.common.Base64Utils; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import run.mone.ultraman.common.GsonUtils; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; + +/** + * @author goodjava@qq.com + * @date 2024/5/29 18:20 + */ +@Slf4j +@Data +public class WsClient { + + private WebSocket ws; + + private String id; + + private String projectName; + + private String url = "ws://127.0.0.1/ws/bot/abc"; + + private CountDownLatch latch; + + public void init(Consumer consumer) { + OkHttpClient client = new OkHttpClient(); + String token = ConfigUtils.getConfig().getzToken(); + Request request = new Request.Builder() + .url(url) + .header("athena-token", token) + .build(); + WebSocketListener listener = new WebSocketListener() { + @Override + public void onOpen(WebSocket webSocket, Response response) { + log.info("ws open"); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + log.info("Received:{}", text); + JsonObject msg = JsonParser.parseString(text).getAsJsonObject(); + String type = GsonUtils.get(msg, "type", ""); + String messageType = GsonUtils.get(msg, "messageType", ""); + + //发生错误了 + if (messageType.equals("BOT_STREAM_FAILURE")) { + String message = GsonUtils.get(msg, "message", ""); + consumer.accept(AiMessage.builder().projectName(projectName).text(message).type(AiMessageType.failure).id(id).build()); + if (null != latch) { + latch.countDown(); + } + return; + } + + if (messageType.equals("BOT_STREAM_BEGIN")) { + consumer.accept(AiMessage.builder().projectName(projectName).text("").type(AiMessageType.begin).id(id).build()); + return; + } + + if (messageType.equals("BOT_STREAM_RESULT")) { + consumer.accept(AiMessage.builder().projectName(projectName).text("").type(AiMessageType.success).id(id).build()); + webSocket.close(1000, null); + if (null != latch) { + latch.countDown(); + } + return; + } + + String message = GsonUtils.get(msg, "message", ""); + + if (messageType.equals("BOT_STREAM_EVENT")) { + //解决中文乱码的问题 + message = Base64Utils.decodeBase64String(message); + log.info("message:{}", message); + consumer.accept(AiMessage.builder().projectName(projectName).code(false).text(message).type(AiMessageType.process).id(id).build()); + } + + } + + @Override + public void onClosing(WebSocket webSocket, int code, String reason) { + webSocket.close(1000, null); + log.info("Closing: " + code + " / " + reason); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + log.error("Error: " + t.getMessage()); + } + }; + ws = client.newWebSocket(request, listener); + log.info("init finish"); + } + + + //发送消息 + public void send(JsonObject req) { + ws.send(req.toString()); + } + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/http/handler/BaseHandler.java b/athena-all/src/main/java/run/mone/ultraman/http/handler/BaseHandler.java new file mode 100644 index 000000000..0a6d58e55 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/http/handler/BaseHandler.java @@ -0,0 +1,29 @@ +package run.mone.ultraman.http.handler; + +import com.google.gson.JsonObject; +import com.intellij.openapi.project.Project; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.common.GsonUtils; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author goodjava@qq.com + * @date 2024/4/28 15:45 + */ +public class BaseHandler { + + public static String getProjectName(JsonObject obj) { + String projectName = GsonUtils.get(obj, "projectName", () -> { + ConcurrentHashMap map = AthenaContext.ins().getProjectMap(); + if (map.size() >= 1) { + return new ArrayList<>(map.values()).get(0).getName(); + } + return ""; + }); + return projectName; + } + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/http/handler/ReadCodeHandler.java b/athena-all/src/main/java/run/mone/ultraman/http/handler/ReadCodeHandler.java new file mode 100644 index 000000000..3073df826 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/http/handler/ReadCodeHandler.java @@ -0,0 +1,156 @@ +package run.mone.ultraman.http.handler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PsiMethodUtils; +import com.xiaomi.youpin.tesla.ip.service.QuickFixInvokeUtil; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.mutable.MutableObject; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.service.AthenaCodeService; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2024/4/28 15:43 + */ +@Slf4j +public class ReadCodeHandler extends BaseHandler { + + + public JsonObject execute(JsonObject obj, JsonObject resObj) { + + log.info("req:{}", obj); + + String projectName = getProjectName(obj); + String packageName = GsonUtils.get(obj, "packageName", () -> ""); + + JsonElement clsJson = obj.get("className"); + JsonElement clsListJson = obj.get("classList"); + + //获取当前打开的类 + boolean openClass = obj.has("openClass"); + + if (StringUtils.isBlank(projectName)) { + return resObj; + } + + Project project = ProjectUtils.projectFromManager(projectName); + + //读取当前打开的class + if (openClass) { + return getJsonObjectWithErrors(resObj, project); + } + + //读取指定method,并且携带行号 + if (obj.has("openMethod")) { + MutableObject mo = new MutableObject(); + ApplicationManager.getApplication().invokeAndWait(()->{ + mo.setValue(getMethodCode(obj, resObj, project)); + }); + return (JsonObject) mo.getValue(); + } + + //replaceMethod + if (obj.has("replaceMethod")) { + return replaceMethodContent(obj, resObj, project); + } + + + if (clsJson != null) { + String className = getFQCN(packageName, clsJson.getAsString()); + resObj.addProperty("data", getCode(projectName, className)); + } else if (clsListJson != null) { + JsonArray classList = clsListJson.getAsJsonArray(); +// Map codeMap = new HashMap(); + JsonArray modifiedClassArray = new JsonArray(); + for (int i = 0; i < classList.size(); i++) { + String clsName = getFQCN(packageName, classList.get(i).getAsString()); + String code = getCode(projectName, clsName); + if (StringUtils.isNotBlank(code)) { + AthenaClassInfo info = AthenaCodeService.classInfo(code); + modifiedClassArray.add(GsonUtils.gson.toJsonTree(info.getClassCode())); + } + } + resObj.add("modifiedClassArray", modifiedClassArray); + } + return resObj; + } + + @NotNull + private static JsonObject replaceMethodContent(JsonObject obj, JsonObject resObj, Project project) { + String methodCode = obj.get("methodCode").getAsString(); + String className = obj.get("className").getAsString(); + String methodName = obj.get("methodName").getAsString(); + ApplicationManager.getApplication().invokeLater(() -> { + log.info("className:{} methodName:{}", className, methodName); + PsiMethod psiMethod = CodeService.getPsiMethod(project, className, methodName); + log.info("get method:{}", psiMethod); + //替换方法内容 + PsiMethodUtils.replacePsiMethod(project, psiMethod, methodCode.trim()); + //打开要修改的类 + CodeService.openJavaClass(project, className); + }); + resObj.addProperty("data", "ok"); + return resObj; + } + + @NotNull + private static JsonObject getMethodCode(JsonObject obj, JsonObject resObj, Project project) { + String className = obj.get("className").getAsString(); + String methodName = obj.get("methodName").getAsString(); + String methodCode = CodeService.getPsiMethodByName(project, className, methodName); + resObj.addProperty("methodCode", methodCode); + return resObj; + } + + @NotNull + private static JsonObject getJsonObjectWithErrors(JsonObject resObj, Project project) { + //获取这个类的错误 + MutableObject code = new MutableObject(); + PsiFile psi = CodeService.getPsiFile(project); + code.setValue(psi.getText()); + List errors = CodeService.invoke(() -> ApplicationManager.getApplication().runReadAction((Computable>) () -> QuickFixInvokeUtil.findAllErrors(project, psi).stream().map(it -> "问题:" + it.getText() + " 问题描述:" + it.getDescription()).collect(Collectors.toList()))); + resObj.addProperty("code", (String) code.getValue()); + resObj.add("error", GsonUtils.gson.toJsonTree(errors)); + return resObj; + } + + + private static String getFQCN(String packageName, String className) { + return StringUtils.joinWith(".", packageName, className); + } + + private static String getCode(String projectName, String className) { + try { + return ReadAction.compute(() -> { + // 确保我们在正确的上下文中 + if (!ApplicationManager.getApplication().isReadAccessAllowed()) { + throw new IllegalStateException("Read access is not allowed"); + } + PsiClass psiClass = PsiClassUtils.findClassByName(ProjectUtils.projectFromManager(projectName), className); + return psiClass.getText(); + }); + } catch (Throwable e) { + log.error("failed to get code for class: {}, in project:{}", className, projectName); + return ""; + } + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/http/handler/WriteCodeHandler.java b/athena-all/src/main/java/run/mone/ultraman/http/handler/WriteCodeHandler.java new file mode 100644 index 000000000..29bbbb225 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/http/handler/WriteCodeHandler.java @@ -0,0 +1,89 @@ +package run.mone.ultraman.http.handler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.util.ProjectUtils; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.bo.AthenaClassInfo; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.http.HttpResponseUtils; +import run.mone.ultraman.service.AthenaCodeService; + +/** + * @author goodjava@qq.com + * @date 2024/4/28 14:53 + */ +@Slf4j +public class WriteCodeHandler extends BaseHandler{ + + public JsonObject execute(JsonObject obj, JsonObject resObj) { + log.info("write code param:\n{}\n", obj); + //如果不传projectName,则自己计算(但如果超过1个,则就去第1个) + String projectName = getProjectName(obj); + String moduleName = GsonUtils.get(obj, "moduleName", () -> ""); + boolean hasCode = obj.has("code"); + //处理单个类的替换 + if (handleCodeReplacement(hasCode, obj, projectName, resObj)) { + return resObj; + } + JsonArray codeList = obj.getAsJsonArray("codeList"); + //这个类的定义(去除public method 的实现部分) + JsonArray codeDefinitionArray = new JsonArray(); + codeList.forEach(it -> Safe.run(() -> { + String code = it.getAsJsonObject().getAsJsonPrimitive("output").getAsString(); + log.debug("create class:\n{}", code); + AthenaClassInfo info = AthenaCodeService.classInfo(code); + codeDefinitionArray.add(GsonUtils.gson.toJsonTree(info.getClassCode())); + Project project = AthenaContext.ins().getProjectMap().get(projectName); + CodeService.invoke(() -> { + WriteCommandAction.runWriteCommandAction(project, () -> { + PsiDirectory directory = PsiClassUtils.getSourceDirectoryWithModule(project, moduleName); + directory = PsiClassUtils.createPackageDirectories(directory, info.getPackagePath()); + PsiClassUtils.createClass(project, info.getName(), code, false, directory); + log.info("create class:{} success", info.getName()); + }); + return null; + }); + })); + log.info("code definition:{}", codeDefinitionArray); + resObj.add("codeDefinitionArray", codeDefinitionArray); + return resObj; + } + + + + + private boolean handleCodeReplacement(boolean hasCode, JsonObject obj, String projectName, JsonObject resObj) { + if (hasCode) { + boolean replace = GsonUtils.get(obj, "replace", false); + if (replace) { + CodeService.invoke(() -> { + String code = obj.get("code").getAsString(); + AthenaClassInfo info = AthenaCodeService.classInfo(code); + PsiClass psiClass = PsiClassUtils.findClassByName(ProjectUtils.projectFromManager(projectName), info.getClassName()); + CodeService.replaceFileContent((PsiFile) psiClass.getParent(), obj.get("code").getAsString()); + resObj.addProperty("data", "success"); + return null; + }); + return true; + } + } + return false; + } + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaApplicationActivationListener.java b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaApplicationActivationListener.java index 72fa8c7a9..aece65369 100644 --- a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaApplicationActivationListener.java +++ b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaApplicationActivationListener.java @@ -1,5 +1,6 @@ package run.mone.ultraman.listener; +import com.google.common.collect.Maps; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.ApplicationActivationListener; @@ -8,45 +9,139 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; +import com.intellij.openapi.editor.actionSystem.TypedAction; +import com.intellij.openapi.editor.actionSystem.TypedActionHandler; import com.intellij.openapi.wm.IdeFrame; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.bo.Action; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import run.mone.ultraman.AthenaInspection; +import run.mone.ultraman.common.CodeUtils; +import run.mone.ultraman.common.SafeRun; +import run.mone.ultraman.listener.bo.CompletionEnum; import run.mone.ultraman.manager.InlayHintManager; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static com.xiaomi.youpin.tesla.ip.common.Const.CONF_M78_CODE_GEN_WITH_ENTER; /** * @author goodjava@qq.com * @date 2023/7/27 22:34 */ +@Slf4j public class AthenaApplicationActivationListener implements ApplicationActivationListener { + //保证只加载一次 private AtomicBoolean init = new AtomicBoolean(false); - @Override public void applicationActivated(@NotNull IdeFrame ideFrame) { if (init.compareAndSet(false, true)) { ApplicationManager.getApplication().executeOnPooledThread(() -> { - //用来捕获 editor中输入enter + + TypedAction typedAction = TypedAction.getInstance(); + TypedActionHandler originalHandler = typedAction.getHandler(); + + //处理输入的,为以后的接口做准备 + typedAction.setupHandler((editor, charTyped, dataContext) -> { + // 在这里处理你的输入字符 + if (Character.isLetterOrDigit(charTyped)) { + // 如果输入的是字母或数字,执行一些操作 + log.debug("Typed letter or digit: " + charTyped); + setActionType(editor, "letterOrDigit"); + + @Nullable AtomicInteger id = editor.getUserData(CaretHoverEditorFactoryListener.EDIT_INCR_ID_KEY); + if (null != id) { + id.incrementAndGet(); + } + + // 此时如果有inlay内容则用户输入后dispose + InlayHintManager.ins().dispose(); + /* InlayHintManager.ins().dispose(text -> { + if (StringUtils.isNotEmpty(text)) { + CodeService.deleteCode(editor); + CodeService.formatCode(editor.getProject()); + } + });*/ + // 再次触发 + handlePluginInEditor(editor); + } + // 确保调用原始处理程序,以便其他功能(如文本输入)不会被破坏 + originalHandler.execute(editor, charTyped, dataContext); + }); + EditorActionManager actionManager = EditorActionManager.getInstance(); - EditorActionHandler originalEnterHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_ENTER); + + //用来捕获 editor中输入回车 + EditorActionHandler enterHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_ENTER); actionManager.setActionHandler(IdeActions.ACTION_EDITOR_ENTER, new EditorActionHandler() { @Override protected void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) { - String text = InlayHintManager.ins().getHintText(); - if (StringUtils.isNotEmpty(text)) { - CodeService.insertCode(editor.getProject(), text, false); - CodeService.deleteCode(editor); - CodeService.formatCode(editor.getProject()); - InlayHintManager.ins().dispose(); - } else { - originalEnterHandler.execute(editor, caret, dataContext); + setActionType(editor, "enter"); + + enterHandler.execute(editor, caret, dataContext); + + if (!ResourceUtils.isOpen(CONF_M78_CODE_GEN_WITH_ENTER)) { + return; + } + String comment = CodeService.getPreviousLineIfComment(editor); + log.info("comment:{}", comment); +// UltramanConsole.append(editor.getProject(), "" + comment, false); + //上一行是注释,并且结尾是(class) + if (check(comment)) { + //直接调用生成代码 + PromptInfo promptInfo = Prompt.getPromptInfo(Const.GENERATE_CODE); + if (AthenaInspection.isBotUsageConfigured(promptInfo)) { + //调用bot生成代码 + HashMap params = Maps.newHashMap(); + params.put("__code", comment.trim()); + params.put("__skip_enter", "true"); + AthenaInspection.invokePrompt(editor.getProject(), promptInfo.getPromptName(), params); + } } } + + private static boolean check(String comment) { + return StringUtils.isNotEmpty(comment) && comment.trim().endsWith(")"); + } + }); + + + //用来捕获 editor中输入tab + EditorActionHandler originalTabHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_TAB); + actionManager.setActionHandler(IdeActions.ACTION_EDITOR_TAB, new EditorActionHandler() { + @Override + protected void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) { + originalTabHandler.execute(editor, caret, dataContext); + InlayHintManager.ins().dispose((text) -> { + if (StringUtils.isNotEmpty(text)) { + CodeService.insertCode(editor.getProject(), text, false, InlayHintManager.ins().getCaretOffsetWhenTriggered(), editor); + CompletionEnum completionType = ConfigUtils.getConfig().getCompletionMode(); + @Nullable CaretHoverPlugin plugin = editor.getUserData(CaretHoverEditorFactoryListener.PLUGIN_KEY); + if (plugin == null || CompletionEnum.MULTI_LINE == completionType) { + //移动到方法末尾 + CodeService.moveCaretToMethodEnd(editor, CodeService.getMethod(editor.getProject())); + } else { + CodeService.moveCaretToEndOfLine(editor); + } + // 代码统计 + CodeUtils.uploadCodeGenInfo(Action.INLAY.getCode(), text, "", editor.getProject()); + } + }); + } }); //用来捕获 editor中输入esc @@ -54,15 +149,53 @@ protected void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataCont actionManager.setActionHandler(IdeActions.ACTION_EDITOR_ESCAPE, new EditorActionHandler() { @Override public void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) { - if (null != InlayHintManager.ins().getInlay()) { - CodeService.deleteCode(editor); - CodeService.formatCode(editor.getProject()); - InlayHintManager.ins().dispose(); - } - originalEscapeHandler.execute(editor, dataContext); + InlayHintManager.ins().dispose(); + /* InlayHintManager.ins().dispose(text -> { + if (StringUtils.isNotEmpty(text)) { + CodeService.deleteCode(editor); + CodeService.formatCode(editor.getProject()); + } else { + originalEscapeHandler.execute(editor, dataContext); + } + });*/ + // 再次触发 + AthenaApplicationActivationListener.handlePluginInEditor(editor); } }); + + EditorActionHandler originalBackspaceHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE); + EditorActionHandler myBackspaceHandler = new EditorActionHandler() { + @Override + protected void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) { + // 在这里处理删除事件 + log.debug("Backspace key pressed"); + // 调用原始处理程序以保持默认行为(保证先影响了) + originalBackspaceHandler.execute(editor, caret, dataContext); + handlePluginInEditor(editor); + + } + }; + actionManager.setActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE, myBackspaceHandler); + + }); } } + + private static void setActionType(Editor editor, String type) { + @Nullable AtomicReference actionType = editor.getUserData(CaretHoverEditorFactoryListener.EDIT_ACTION_TYPE); + if (null != actionType) { + actionType.set(type); + } + } + + public static void handlePluginInEditor(@NotNull Editor editor) { + SafeRun.run(() -> { + CaretHoverPlugin plugin = editor.getUserData(CaretHoverEditorFactoryListener.PLUGIN_KEY); + if (null != plugin) { + //处理退出的逻辑 + plugin.handleCaretPositionChangedEvent(); + } + }); + } } diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileDocumentManagerListener.java b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileDocumentManagerListener.java index d09c99423..0a8b5b6ad 100644 --- a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileDocumentManagerListener.java +++ b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileDocumentManagerListener.java @@ -8,6 +8,9 @@ /** * @author goodjava@qq.com * @date 2023/7/14 10:25 + * + * 保存document的时候,会回调回来,以后做统计用 + * */ @Slf4j public class AthenaFileDocumentManagerListener implements FileDocumentManagerListener { diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileEditorManagerListener.java b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileEditorManagerListener.java index 8d9b2fc75..77d619079 100644 --- a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileEditorManagerListener.java +++ b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaFileEditorManagerListener.java @@ -4,9 +4,9 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.vfs.VirtualFile; -import run.mone.m78.ip.bo.ValueInfo; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.bo.ValueInfo; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Safe; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -31,6 +31,7 @@ public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile f log.info(text); ValueInfo pi = new ValueInfo(); pi.setValue(text); + //自己实现了一套event时间,以后都需要且成ide自带那套 AthenaEventBus.ins().post(pi); } }); diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaProjectManagerListener.java b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaProjectManagerListener.java index 55dd879e0..8f124a684 100644 --- a/athena-all/src/main/java/run/mone/ultraman/listener/AthenaProjectManagerListener.java +++ b/athena-all/src/main/java/run/mone/ultraman/listener/AthenaProjectManagerListener.java @@ -1,13 +1,29 @@ package run.mone.ultraman.listener; +import com.intellij.execution.Executor; +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.execution.process.ProcessOutputTypes; +import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.execution.ui.RunContentManager; +import com.intellij.execution.ui.RunContentWithExecutorListener; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManagerListener; -import run.mone.m78.ip.bo.robot.AiMessageManager; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; -import run.mone.m78.ip.common.ConfigUtils; +import com.intellij.openapi.util.Key; +import com.intellij.util.messages.MessageBusConnection; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.util.NetUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.listener.event.TaskEvent; import run.mone.ultraman.state.FsmManager; import run.mone.ultraman.state.ProjectFsmManager; @@ -22,8 +38,49 @@ public class AthenaProjectManagerListener implements ProjectManagerListener { @Override public void projectOpened(Project project) { log.info("Project reopened: " + project.getName()); + + Safe.run(() -> { + // 订阅事件 + RunContentWithExecutorListener myListener = new RunContentWithExecutorListener() { + @Override + public void contentSelected(RunContentDescriptor descriptor, Executor executor) { + + @Nullable ProcessHandler processHandler = descriptor.getProcessHandler(); + if (processHandler != null) { + // 添加 ProcessListener 来监听输出 + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) { + // 这里可以捕获输出信息 + String text = event.getText(); + // 根据 outputType 区分 stdout 和 stderr + if (outputType == ProcessOutputTypes.STDOUT) { + System.out.println("STDOUT: " + text); + } else if (outputType == ProcessOutputTypes.STDERR) { + System.out.println("STDERR: " + text); + } + } + }); + } + + } + + @Override + public void contentRemoved(RunContentDescriptor descriptor, Executor executor) { + // 处理内容被移除的事件 + } + }; + MessageBusConnection connection = project.getMessageBus().connect(); + connection.subscribe(RunContentManager.TOPIC, myListener); + connection.subscribe(TaskEvent.TOPIC, new TaskEvent.TaskEventListenerImpl(project)); + }); + + AthenaContext.ins().getProjectMap().put(project.getName(), project); AthenaContext.ins().setGptModel(ConfigUtils.getConfig().getModel()); + AthenaContext.ins().setNoChatModel(ConfigUtils.getConfig().getNoChatModel()); + AthenaContext.ins().setLocalAddress(NetUtils.getLocalHost()); + AthenaContext.ins().setLocalPort(ResourceUtils.getAthenaConfig().get(Const.CONF_PORT)); ProjectAiMessageManager.getInstance().putMessageManager(project.getName(), new AiMessageManager()); FsmManager fsmManager = new FsmManager(); fsmManager.setProject(project.getName()); diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverEditorFactoryListener.java b/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverEditorFactoryListener.java new file mode 100644 index 000000000..f2e3482dd --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverEditorFactoryListener.java @@ -0,0 +1,55 @@ +package run.mone.ultraman.listener; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.EditorFactoryEvent; +import com.intellij.openapi.editor.event.EditorFactoryListener; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import org.jetbrains.annotations.NotNull; + +import java.lang.ref.Reference; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author goodjava@qq.com + * @date 2024/5/31 14:51 + */ +public class CaretHoverEditorFactoryListener implements EditorFactoryListener { + + + public static final Key PLUGIN_KEY = new Key<>("plugin_key"); + + public static final Key EDIT_INCR_ID_KEY = new Key<>("edit_incr_id_key"); + + //用来记录操作类型的 + public static final Key> EDIT_ACTION_TYPE = new Key<>("edit_action_type"); + + @Override + public void editorCreated(@NotNull EditorFactoryEvent event) { + Editor editor = event.getEditor(); + Project project = editor.getProject(); + if (project != null) { + CaretHoverPlugin plugin = new CaretHoverPlugin(project, editor); + editor.putUserData(EDIT_INCR_ID_KEY, new AtomicInteger()); + editor.putUserData(PLUGIN_KEY, plugin); + editor.putUserData(EDIT_ACTION_TYPE, new AtomicReference<>("")); + } + } + + @Override + public void editorReleased(@NotNull EditorFactoryEvent event) { + Editor editor = event.getEditor(); + CaretHoverPlugin plugin = editor.getUserData(PLUGIN_KEY); + if (plugin != null) { + // Perform any necessary cleanup in the plugin + plugin.editorReleased(); + // Remove the plugin from the editor's user data + editor.putUserData(PLUGIN_KEY, null); + editor.putUserData(EDIT_INCR_ID_KEY, null); + editor.putUserData(EDIT_ACTION_TYPE, null); + } + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverPlugin.java b/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverPlugin.java new file mode 100644 index 000000000..533402224 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/listener/CaretHoverPlugin.java @@ -0,0 +1,475 @@ +package run.mone.ultraman.listener; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParseResult; +import com.github.javaparser.ast.stmt.Statement; +import com.google.gson.JsonObject; +import com.intellij.codeInsight.completion.CompletionProcess; +import com.intellij.codeInsight.completion.CompletionService; +import com.intellij.codeInsight.lookup.Lookup; +import com.intellij.codeInsight.lookup.LookupEx; +import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.event.CaretEvent; +import com.intellij.openapi.editor.event.CaretListener; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeRegistry; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.Safe; +import com.xiaomi.youpin.tesla.ip.service.BotService; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import net.sf.cglib.beans.BeanCopier; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import run.mone.ultraman.common.ScopeEnum; +import run.mone.ultraman.listener.bo.CompletionEnum; +import run.mone.ultraman.manager.InlayHintManager; + +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author goodjava@qq.com + * @date 2024/5/31 14:52 + */ +@Slf4j +@Data +public class CaretHoverPlugin { + + private Project project; + + private Editor editor; + + private ReentrantLock lock = new ReentrantLock(); + + private ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor(); + + private Future future; + + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + private final BeanCopier PROMPT_COPIER = BeanCopier.create(PromptInfo.class, PromptInfo.class, false); + + /** + * 检查方法 + * 如果指定资源未打开则返回真 + * 如果事件不为空,获取旧位置,返回旧位置行和列是否都为 0 + */ + private static boolean isResourceClosedOrInitialPosition(CaretEvent event) { + //只留下了chat + if (ResourceUtils.checkDisableCodeCompletionStatus()) { + return true; + } + + if (!ResourceUtils.isOpen(Const.INLAY) || CompletionEnum.NONE == ConfigUtils.getConfig().getCompletionMode()) { + return true; + } + + if (event != null) { + //刚进来的不做任何处理 + return event.getOldPosition().line == 0 && event.getOldPosition().column == 0; + } + return false; + } + + + public CaretHoverPlugin(Project project, Editor editor) { + this.project = project; + this.editor = editor; + editor.getCaretModel().addCaretListener(new CaretListener() { + @Override + public void caretPositionChanged(CaretEvent event) { + // config设置为关闭,则不做任何处理 + if (CompletionEnum.NONE.equals(ConfigUtils.getConfig().getCompletionMode())) { + return; + } + if (isResourceClosedOrInitialPosition(event)) { + return; + } + log.debug("caretPositionChanged :{}", event.getCaret()); + try { + lock.lock(); + if (null != future && !future.isDone()) { + future.cancel(true); + } + Pair shouldComplete = shouldComplete(editor, event.getCaret()); + if (shouldComplete.getLeft()) { + int offset = editor.getCaretModel().getOffset(); + InlayHintManager.ins().setCaretOffsetWhenTriggered(offset); + log.info("start timer at offset:{}", offset); + startTimer(editor, event.getCaret(), shouldComplete.getRight()); + } + } finally { + lock.unlock(); + } + } + }); + } + + public void handleCaretPositionChangedEvent() { + if (ResourceUtils.checkDisableCodeCompletionStatus()) return; + ApplicationManager.getApplication().invokeLater(() -> { + if (isResourceClosedOrInitialPosition(null)) { + return; + } + log.debug("handleCaretPositionChangedEvent"); + try { + lock.lock(); + if (null != future) { + log.info("cancel task"); + future.cancel(true); + } + Caret caret = getCurrentCaretClass(this.editor); + InlayHintManager.ins().dispose(); + if (!InlayHintManager.ins().hasInlay() && shouldComplete(editor, caret).getLeft()) { + log.info("start timer"); + startTimer(editor, caret, ConfigUtils.getConfig().getCompletionMode()); + } + } finally { + lock.unlock(); + } + }); + } + + @NotNull + private static String getCurrentLine(Editor editor, Caret caret) { + try { + Document document = editor.getDocument(); + int lineNumber = caret.getLogicalPosition().line; + int lineStartOffset = document.getLineStartOffset(lineNumber); + int lineEndOffset = document.getLineEndOffset(lineNumber); + String lineText = document.getText().substring(lineStartOffset, lineEndOffset).trim(); + return lineText; + } catch (Throwable throwable) { + log.error(throwable.getMessage(), throwable); + return ""; + } + } + + + public static boolean isCompleteStatement(String lineText) { + JavaParser parser = new JavaParser(); + ParseResult result = parser.parseStatement(lineText); + return result.isSuccessful(); + } + + + private void startTimer(Editor editor, Caret caret, CompletionEnum completionMode) { + int delay = Integer.parseInt(ResourceUtils.getAthenaConfig().getOrDefault(Const.INLAY_DELAY, "200")); + log.info("Inlay delay time:{} ms", delay); + Safe.run(() -> this.future = pool.schedule(() -> Safe.run(() -> showInlay(editor, caret, completionMode)), delay, TimeUnit.MILLISECONDS)); + } + + + /** + * 判断是否应该完成代码自动补全。 + * 如果光标不在方法内,返回false。 + * 如果当前行为空或光标在方法内,返回true。 + */ + private Pair shouldComplete(Editor editor, Caret caret) { + if (InlayHintManager.ins().hasInlay()) { + return Pair.of(false, CompletionEnum.NONE); + } + // lookup的时候不触发 + boolean memberCompletion = isMemberCompletion2(editor); + log.debug("isMember :{}", memberCompletion); + if (memberCompletion) { + return Pair.of(false, CompletionEnum.NONE); + } + + // 不在文本编辑区时不触发 + // 非java文件不触发 + AtomicReference psiFile = new AtomicReference<>(); + WriteCommandAction.runWriteCommandAction(project, () -> { + psiFile.set(PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument())); + }); + FileType javaFileType = FileTypeRegistry.getInstance().getFileTypeByExtension("java"); + if (psiFile.get() == null || psiFile.get().getFileType() != javaFileType) { + return Pair.of(false, CompletionEnum.NONE); + } + ApplicationManager.getApplication().invokeLater(() -> { + WriteCommandAction.runWriteCommandAction(project, () -> { + Document document = editor.getDocument(); + PsiDocumentManager.getInstance(project).commitDocument(document); + }); + }); + log.debug("caret:{}", caret); + PsiMethod method = getMethod(editor, psiFile.get()); + if (null != method) { + @NotNull String line = getCurrentLine(editor, caret); + if (StringUtils.isEmpty(line)) { + //上一个操作不是回车,则忽略生成(review代码的时候经常这样) + if ("enter".equals(editor.getUserData(CaretHoverEditorFactoryListener.EDIT_ACTION_TYPE).get())) { + editor.getUserData(CaretHoverEditorFactoryListener.EDIT_ACTION_TYPE).set(null); + } else { + return Pair.of(false, CompletionEnum.NONE); + } + String bodyCode = getMethodBodyWithoutBracesNewlinesAndComments(method); + if (StringUtils.isEmpty(bodyCode)) { + // 当前行是空,并且当前方法体是空,就走多行逻辑 + return Pair.of(true, CompletionEnum.MULTI_LINE); + } + } + + if (singleLineShouldComplete(line, editor)) { + // 当前行不为空、不完整且光标在末尾的情况下才触发补全 + return Pair.of(true, CompletionEnum.SINGLE_LINE); + } + } + return Pair.of(false, CompletionEnum.NONE); + } + + private boolean isCurrentlyInLookup(Project project) { + log.info("begin isCurrentlyInLookup"); + LookupManager lookupManager = LookupManager.getInstance(project); + log.info("lookupManager:{}", lookupManager); + if (lookupManager == null) { + return false; + } + LookupEx activeLookup = lookupManager.getActiveLookup(); + if (activeLookup != null && activeLookup.getCurrentItem() != null) { + log.info("lookup:{}", activeLookup); + boolean memberCompletion = isMemberCompletion(); + log.info("isMemberCompletion:{}", memberCompletion); + return memberCompletion; + } else { + log.info("activeLookup status:{}", activeLookup); + return false; + } + } + + public boolean isMemberCompletion2(Editor editor) { + try { + int offset = editor.getCaretModel().getOffset(); + CharSequence documentText = editor.getDocument().getCharsSequence(); + return documentText.charAt(offset - 1) == '.'; + } catch (Throwable e) { + log.warn("check doc range err:", e.getMessage()); + return false; + } + } + + private static boolean isActiveLookupOrCompletionProcessPresent(Editor editor) { + log.info("in . "); + // Check if there's an active lookup + Project project = editor.getProject(); + if (project != null) { + Lookup activeLookup = LookupManager.getInstance(project).getActiveLookup(); + log.info("activelookup:{}", activeLookup); + if (activeLookup != null) { + return true; + } + } + + // Check if there's an active completion process + CompletionService completionService = CompletionService.getCompletionService(); + CompletionProcess completionProcess = completionService.getCurrentCompletion(); + log.info("completionProcess:{}", completionProcess); + return completionProcess != null; + } + + private boolean isMemberCompletion() { + log.info("in isMemberCompletion"); + CompletionService completionService = CompletionService.getCompletionService(); + CompletionProcess completionProcess = completionService.getCurrentCompletion(); + return completionProcess != null; + } + + /** + * 获取去掉大括号、换行符和单行注释的 PsiMethod body + * + * @param psiMethod 要处理的 PsiMethod + * @return 去掉大括号、换行符和单行注释的 body 字符串 + */ + public static String getMethodBodyWithoutBracesNewlinesAndComments(PsiMethod psiMethod) { + PsiCodeBlock body = psiMethod.getBody(); + if (body == null) { + return null; + } + + // 获取 body 的所有子元素 + PsiElement[] children = body.getChildren(); + StringBuilder bodyContent = new StringBuilder(); + + for (PsiElement child : children) { + String text = child.getText(); + // 跳过大括号、换行符和注释 + if (!(child instanceof PsiComment) && !text.equals("{") && !text.equals("}") && !text.trim().isEmpty()) { + bodyContent.append(text); + } + } + + return bodyContent.toString().trim(); + } + + + //从Editor中获取当前caret(class) + private Caret getCurrentCaretClass(Editor editor) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> editor.getCaretModel().getCurrentCaret()); + } + + + private PsiMethod getMethod(Editor editor, PsiFile psiFile) { + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + CaretModel caretModel = editor.getCaretModel(); + int offset = caretModel.getOffset(); + PsiElement elementAtCaret = psiFile.findElementAt(offset); + PsiMethod method = PsiTreeUtil.getParentOfType(elementAtCaret, PsiMethod.class); + return method; + }); + } + + + private void showInlay(Editor editor, Caret caret, CompletionEnum completionMode) { + int id = editor.getUserData(CaretHoverEditorFactoryListener.EDIT_INCR_ID_KEY).incrementAndGet(); + + JsonObject req = new JsonObject(); + + PromptInfo promptInfo = Prompt.getPromptInfo("code_completion"); + PromptInfo forkedPromptInfo = new PromptInfo(); + PROMPT_COPIER.copy(promptInfo, forkedPromptInfo, null); + GenerateCodeReq generateCodeReq = GenerateCodeReq.builder().project(editor.getProject()).promptInfo(forkedPromptInfo).build(); + PromptService.setReq(generateCodeReq); + //生成单行代码 + if (CompletionEnum.SINGLE_LINE == completionMode) { + // 生成部分代码 (160004) 测试用的100302 + req.addProperty("botId", ResourceUtils.getAthenaConfig().getOrDefault(Const.INLAY_BOT_ID, "160004")); + if (MapUtils.isNotEmpty(forkedPromptInfo.getLabels())) { + forkedPromptInfo.getLabels().remove("analysis_scope"); + } + generateCodeReq.setUserSettingScope(ResourceUtils.getAthenaConfig().getOrDefault(Const.INLAY_SCOPE, ScopeEnum.SMethod.name())); + } else { + //生成全部代码 + //100294(比较单一的) 100317(支持上下文) + req.addProperty("botId", "100317"); + } + @NotNull JsonObject params = BotService.generateParams(generateCodeReq, generateCodeReq.getClassCodeWithMark()); + req.add("params", params); + req.addProperty("input", ""); + + //直接调用m78的bot接口,所以不走stream(open-apis/ai-plugin-new/feature/router/probot/query) + String text = callBotAndGetResult(req); + // TODO mason + log.info("mode:{}, showInlay text:{}", completionMode.getName(), text); + if (StringUtils.isEmpty(text)) { + return; + } + + //又有了新的补全 + if (id < editor.getUserData(CaretHoverEditorFactoryListener.EDIT_INCR_ID_KEY).get()) { + log.info("id:{} cancel", id); + return; + } + + + //关闭代码提示 + invokeCloseCompletion(editor); + + ApplicationManager.getApplication().invokeLater(() -> { + InlayModel inlayModel = editor.getInlayModel(); + int offset = caret.getOffset(); + int lineNumber = editor.getDocument().getLineNumber(offset); + int lineStartOffset = editor.getDocument().getLineStartOffset(lineNumber); + String lineText = editor.getDocument().getText(new TextRange(lineStartOffset, offset)); + String replace = lineText.replace("\t", " "); // 如果有\t转为四个空格,否则有问题 + String indent = replace.replaceAll("\\S", ""); // 获取当前行的缩进 + + //插入空行,为了看起来更美观 + //insertBlankLinesFromRenderer(editor, renderer); + long count = Stream.of(text.split("\n")).count(); + + @Nullable Inlay inlay = null; + if (count <= 1) { + InlayCustomRenderer renderer = new InlayCustomRenderer(text, null); + inlay = inlayModel.addInlineElement(offset, true, renderer); + } else { + InlayCustomRenderer renderer = new InlayCustomRenderer(text, indent); + inlay = inlayModel.addBlockElement(offset, true, false, 0, renderer); + } + InlayHintManager.ins().setInlay(inlay, text); /* @Nullable Inlay inlay = inlayModel.addInlineElement(offset, renderer); + InlayHintManager.ins().setInlay(inlay, text);*/ + }); + + } + + + private static void invokeCloseCompletion(Editor editor) { + if (editor == null || editor.getProject() == null || editor.getProject().isDisposed()) { + return; + } + ApplicationManager.getApplication().invokeLater(() -> CodeService.closeCompletion(editor.getProject())); + } + + private String callBotAndGetResult(JsonObject req) { + String text = ""; + try { + text = BotService.callBot(this.project, req); + } catch (Throwable ignore) { + + } + return text; + } + + private static void insertBlankLinesFromRenderer(Editor editor, InlayCustomRenderer renderer) { + //减去当前空行 + int lineSize = renderer.getLines().size() - 1; + if (lineSize > 0) { + CodeService.insertBlankLinesAtCaret(editor.getProject(), editor, lineSize); + } + } + + private boolean singleLineShouldComplete(String line, Editor editor) { + return StringUtils.isBlank(line) || notBlankLineShouldComplete(line, editor); + } + + private boolean notBlankLineShouldComplete(String line, Editor editor) { + return !CodeService.isCursorInComment(editor) + && !CodeService.isAtMultiCommentEnd(line) + && CodeService.hasValidCharCnt(line) + && !CodeService.isCaretLineOnlyAnnotation(editor) + && CodeService.isCaretAtEndOfLine(editor) + && !CodeService.isPreCharBrace(editor) + && !isCompleteStatement(line); + } + + /** + * 关闭存留的悬浮面板及相关任务 + */ + public void editorReleased() { + try { + lock.lock(); + if (future != null && !future.isDone()) { + future.cancel(true); + } + InlayHintManager.ins().dispose(); + invokeCloseCompletion(editor); + } finally { + lock.unlock(); + } + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/InlayCustomRenderer.java b/athena-all/src/main/java/run/mone/ultraman/listener/InlayCustomRenderer.java new file mode 100644 index 000000000..e0b9f83ea --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/listener/InlayCustomRenderer.java @@ -0,0 +1,117 @@ +package run.mone.ultraman.listener; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorCustomElementRenderer; +import com.intellij.openapi.editor.Inlay; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorFontType; +import com.intellij.openapi.editor.impl.FontInfo; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.ui.JBColor; +import com.intellij.util.ui.UIUtil; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author goodjava@qq.com + * @date 2024/5/31 14:57 + */ +public class InlayCustomRenderer implements EditorCustomElementRenderer { + + + private final String text; + + @Getter + private final List lines; + + private final String indent; + + public InlayCustomRenderer(String text, String indent) { + this.text = text; + this.lines = Stream.of(text.split("\n")).collect(Collectors.toList()); + this.indent = indent; + } + + @Override + public int calcWidthInPixels(@NotNull Inlay inlay) { + FontMetrics metrics = inlay.getEditor().getContentComponent().getFontMetrics(inlay.getEditor().getColorsScheme().getFont(EditorFontType.PLAIN)); + int maxWidth = 0; + for (String line : text.split("\n")) { + int width = 0; + if (StringUtils.isNotEmpty(indent)) { + width = metrics.stringWidth(line + indent); + } else { + width = metrics.stringWidth(line); + } + if (width > maxWidth) { + maxWidth = width; + } + } + return maxWidth; + //return Math.max(getWidth(inlay.getEditor(), text), 1); + + /* FontMetrics fontMetrics = inlay.getEditor().getContentComponent().getFontMetrics(inlay.getEditor().getColorsScheme().getFont(EditorFontType.PLAIN)); + // 计算一个字符的宽度 + int charWidth = fontMetrics.charWidth('m'); // 假设使用 'm' 字符来计算平均字符宽度 + return lines.stream().mapToInt(line -> fontMetrics.stringWidth(line) + charWidth).max().orElse(0);*/ + } + + @Override + public int calcHeightInPixels(@NotNull Inlay inlay) { + FontMetrics metrics = inlay.getEditor().getContentComponent().getFontMetrics(inlay.getEditor().getColorsScheme().getFont(EditorFontType.PLAIN)); + return metrics.getHeight() * text.split("\n").length; + } + + @Override + public void paint(@NotNull Inlay inlay, @NotNull Graphics g, @NotNull Rectangle targetRegion, @NotNull TextAttributes textAttributes) { + //EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + //Color backgroundColor = scheme.getDefaultBackground(); + // 设置自定义元素的背景颜色 + //g.setColor(backgroundColor); + //g.clearRect(targetRegion.x, targetRegion.y, targetRegion.width, targetRegion.height); + // 绘制提示内容时修改为灰色 + g.setColor(JBColor.gray); + Font font = inlay.getEditor().getColorsScheme().getFont(EditorFontType.PLAIN); + g.setFont(font); + FontMetrics fontMetrics = inlay.getEditor().getContentComponent().getFontMetrics(font); + Editor editor = inlay.getEditor(); + int y = 0; + int lineHeight = 0; + if (StringUtils.isNotEmpty(indent)) { + lineHeight = fontMetrics.getHeight(); + y = targetRegion.y + fontMetrics.getAscent(); + } else { + float lineSpacing = editor.getColorsScheme().getLineSpacing(); + lineHeight = (int) (Math.ceil(fontMetrics.getHeight() * lineSpacing)); + y = targetRegion.y + editor.getAscent(); + } + // 绘制多行文本并应用缩进 + for (String line : text.split("\n")) { + if (StringUtils.isNotEmpty(indent)) { + g.drawString(indent + line, targetRegion.x, y); + } else { + g.drawString(line, targetRegion.x, y); + } + y += lineHeight; + } + /*// 获取编辑器的行间距 + Editor editor = inlay.getEditor(); + float lineSpacing = editor.getColorsScheme().getLineSpacing(); + + // Draw each line, adjusting the y position for each line + int lineHeight = (int) (Math.ceil(fontMetrics.getHeight() * lineSpacing)); + int y = targetRegion.y + editor.getAscent(); + for (String line : lines) { + g.drawString(indent + line, targetRegion.x, y); + y += lineHeight; + }*/ + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/bo/CompletionEnum.java b/athena-all/src/main/java/run/mone/ultraman/listener/bo/CompletionEnum.java new file mode 100644 index 000000000..7dae00eee --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/listener/bo/CompletionEnum.java @@ -0,0 +1,74 @@ +package run.mone.ultraman.listener.bo; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author HawickMason@xiaomi.com + * @date 6/4/24 10:00 AM + */ +public enum CompletionEnum { + + NONE(-1, "disable_line_completion", "关闭", true), + + OPEN(2, "open", "开启", true), + + SINGLE_LINE(0, "single_line_completion", "单行(方法内实时触发)", false), + + MULTI_LINE(1, "multi_line_completion", "多行(空方法内触发)", false); + + private final int code; + private final String name; + + private final String desc; + + private final boolean display; + + private static final Map valMap = Arrays.stream(values()).collect(Collectors.toMap(CompletionEnum::getCode, Function.identity())); + + private static final Map nameMap = Arrays.stream(values()).collect(Collectors.toMap(CompletionEnum::getName, Function.identity())); + + private static final Map descMap = Arrays.stream(values()).collect(Collectors.toMap(CompletionEnum::getDesc, Function.identity())); + + CompletionEnum(int code, String name, String desc, boolean display) { + this.code = code; + this.name = name; + this.desc = desc; + this.display = display; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public boolean isDisplay() { + return display; + } + + public static CompletionEnum getTypeEnumByCode(int code) { + return valMap.getOrDefault(code, NONE); + } + + public static CompletionEnum getTypeEnumByName(String name) { + return nameMap.getOrDefault(name, NONE); + } + + public static CompletionEnum getTypeEnumByDesc(String desc) { + return descMap.getOrDefault(desc, NONE); + } + + public static List getDisplayList() { + return Arrays.stream(values()).filter(CompletionEnum::isDisplay).map(CompletionEnum::getDesc).collect(Collectors.toList()); + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/listener/event/TaskEvent.java b/athena-all/src/main/java/run/mone/ultraman/listener/event/TaskEvent.java new file mode 100644 index 000000000..7e5665934 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/listener/event/TaskEvent.java @@ -0,0 +1,57 @@ +package run.mone.ultraman.listener.event; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.util.messages.Topic; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.background.AiBackgroundTask; + +/** + * @author goodjava@qq.com + * @date 2024/6/1 21:48 + */ +@Data +@Builder +@Slf4j +public class TaskEvent { + + public static final Topic TOPIC = Topic.create("TaskEvent", TaskEventListener.class); + + private String message; + + private long time; + + + public interface TaskEventListener { + void onEvent(TaskEvent event); + } + + public static class TaskEventListenerImpl implements TaskEventListener { + + private Project project; + + private AiBackgroundTask task; + + public TaskEventListenerImpl(Project project) { + this.project = project; + } + + @Override + public void onEvent(TaskEvent event) { + if (event.getMessage().equals("begin")) { + this.task = new AiBackgroundTask(project, "Athena"); + ProgressManager.getInstance().run(task); + } + if (event.getMessage().equals("end")) { + if (null != this.task) { + this.task.cancel(); + log.info("use time:{} s", event.getTime()); + } + } + } + } + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/manager/AthenaTypedActionHandler.java b/athena-all/src/main/java/run/mone/ultraman/manager/AthenaTypedActionHandler.java index 499acf12b..0b5d666e1 100644 --- a/athena-all/src/main/java/run/mone/ultraman/manager/AthenaTypedActionHandler.java +++ b/athena-all/src/main/java/run/mone/ultraman/manager/AthenaTypedActionHandler.java @@ -19,5 +19,23 @@ public class AthenaTypedActionHandler extends TypedHandlerDelegate { return super.charTyped(c, project, editor, file); } + // @Override +// public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) { +// if (c == '\u001B') { // ESC 键 +// // 处理取消操作 +//// Inlay inlay = InlayHintManager.addInlayHint(editor,"abc"); // 获取你的 Inlay 对象 +//// inlay.dispose(); // 移除 Inlay +// System.out.println("-->Esc"); +// } else if (c == '\n') { // ENTER 键 +// // 处理确认操作 +//// String hintText = ; // 获取你的预输入内容 +//// int offset = editor.getCaretModel().getOffset(); // 获取当前的插入点位置 +//// editor.getDocument().insertString(offset, hintText); // 插入预输入内容 +// System.out.println("-->Enter"); +// } else { +// // 如果按下的不是 ESC 或 ENTER 键,就按照默认的行为处理 +// originalHandler.execute(editor, c, dataContext); +// } +// } } diff --git a/athena-all/src/main/java/run/mone/ultraman/manager/InlayHintManager.java b/athena-all/src/main/java/run/mone/ultraman/manager/InlayHintManager.java index b1dfa8dd3..8afe8d401 100644 --- a/athena-all/src/main/java/run/mone/ultraman/manager/InlayHintManager.java +++ b/athena-all/src/main/java/run/mone/ultraman/manager/InlayHintManager.java @@ -3,21 +3,52 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Inlay; import com.intellij.openapi.editor.InlayModel; -import lombok.Getter; +import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.render.AthenaInlayRenderer; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + /** * @author goodjava@qq.com * @date 2023/7/21 14:07 */ public class InlayHintManager { - @Getter private Inlay inlay; - @Getter private String hintText; + private AtomicInteger caretOffsetWhenTriggered = new AtomicInteger(); + + + public synchronized Inlay getInlay() { + return inlay; + } + + + public synchronized void setInlay(Inlay inlay, String hintText) { + this.inlay = inlay; + this.hintText = hintText; + } + + public void removeBlockInlay() { + if (inlay != null) { + inlay.dispose(); + } + } + + public synchronized boolean hasInlay() { + return null != this.inlay; + } + + public int getCaretOffsetWhenTriggered() { + return caretOffsetWhenTriggered.get(); + } + + public void setCaretOffsetWhenTriggered(int offset) { + this.caretOffsetWhenTriggered.set(offset); + } private static final class LazyHolder { private static final InlayHintManager ins = new InlayHintManager(); @@ -27,14 +58,31 @@ public static final InlayHintManager ins() { return LazyHolder.ins; } - public void dispose() { + public synchronized void dispose() { if (null != inlay) { inlay.dispose(); + inlay = null; this.hintText = null; } } + public synchronized void dispose(Consumer consumer) { + if (null != inlay) { + if (StringUtils.isEmpty(this.hintText)) { + this.hintText = "null"; + } + consumer.accept(this.hintText); + inlay.dispose(); + inlay = null; + this.hintText = null; + } else { + consumer.accept(""); + } + } + + + public Inlay addInlayHint(Editor editor, int offset, String hintText) { InlayModel inlayModel = editor.getInlayModel(); this.hintText = hintText; diff --git a/athena-all/src/main/java/run/mone/ultraman/quickfix/M78Inspection.java b/athena-all/src/main/java/run/mone/ultraman/quickfix/M78Inspection.java new file mode 100644 index 000000000..f0694ae0b --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/quickfix/M78Inspection.java @@ -0,0 +1,54 @@ +package run.mone.ultraman.quickfix; + +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.JavaElementVisitor; +import com.intellij.psi.PsiElementVisitor; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * @author goodjava@qq.com + * @date 2024/4/21 11:58 + */ +public class M78Inspection extends LocalInspectionTool { + + + @Override + public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { + return new MyVisitor(holder); + } + + + private static class MyVisitor extends JavaElementVisitor { + + private String packageStr = ""; + + private String className = ""; + + private final ProblemsHolder holder; + + public MyVisitor(ProblemsHolder holder) { + this.holder = holder; + } + + } + + + + @Override + public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getDisplayName() { + return "MyInspection"; + } + + @Override + public @NonNls @NotNull String getShortName() { + return "MyInspection"; + } + + @Override + public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getGroupDisplayName() { + return "MyInspection"; + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/quickfix/MethoNameLocalQuickFix.java b/athena-all/src/main/java/run/mone/ultraman/quickfix/MethoNameLocalQuickFix.java new file mode 100644 index 000000000..67a6763c7 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/quickfix/MethoNameLocalQuickFix.java @@ -0,0 +1,32 @@ +package run.mone.ultraman.quickfix; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.util.IntentionFamilyName; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiIdentifier; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; + +/** + * @author goodjava@qq.com + * @date 2024/4/21 12:41 + */ +public class MethoNameLocalQuickFix implements LocalQuickFix { + @Override + public @IntentionFamilyName @NotNull String getFamilyName() { + return "Method Name Inspection"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiElement element = descriptor.getPsiElement(); + if (element instanceof PsiIdentifier) { + PsiMethod method = (PsiMethod)element.getParent(); + String methodName = method.getName(); + String newMethodName = methodName.replaceAll("\\d", ""); + method.setName(newMethodName); + } + } +} diff --git a/athena-all/src/main/java/run/mone/ultraman/render/AthenaInlayRenderer.java b/athena-all/src/main/java/run/mone/ultraman/render/AthenaInlayRenderer.java index 7ff97b6c3..d1e7626ce 100644 --- a/athena-all/src/main/java/run/mone/ultraman/render/AthenaInlayRenderer.java +++ b/athena-all/src/main/java/run/mone/ultraman/render/AthenaInlayRenderer.java @@ -7,7 +7,9 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.ex.util.EditorUtil; +import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.markup.TextAttributes; +import com.xiaomi.youpin.tesla.ip.service.CodeService; import org.jetbrains.annotations.NotNull; import java.awt.*; @@ -25,6 +27,7 @@ public class AthenaInlayRenderer implements EditorCustomElementRenderer { public AthenaInlayRenderer(String hintText, Editor editor) { this.hintText = hintText; this.editor = editor; + } @Override diff --git a/athena-all/src/main/java/run/mone/ultraman/service/AgentService.java b/athena-all/src/main/java/run/mone/ultraman/service/AgentService.java new file mode 100644 index 000000000..9ecd030e0 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/service/AgentService.java @@ -0,0 +1,30 @@ +package run.mone.ultraman.service; + +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; + +/** + * @author goodjava@qq.com + * @date 2024/2/27 14:31 + */ +public class AgentService { + + + /** + * 关闭项目中所有打开的文件。 + * + * @param project 当前操作的项目对象 + */ + public static void closeAllOpenFilesInProject(Project project) { + FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + // 获取所有打开的文件 + VirtualFile[] openFiles = fileEditorManager.getOpenFiles(); + // 循环关闭每一个打开的文件 + for (VirtualFile openFile : openFiles) { + fileEditorManager.closeFile(openFile); + } + } + + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/service/AiCodeService.java b/athena-all/src/main/java/run/mone/ultraman/service/AiCodeService.java index a6d1d9024..92947cb95 100644 --- a/athena-all/src/main/java/run/mone/ultraman/service/AiCodeService.java +++ b/athena-all/src/main/java/run/mone/ultraman/service/AiCodeService.java @@ -1,25 +1,37 @@ package run.mone.ultraman.service; +import com.google.gson.JsonObject; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.ConfigUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import lombok.extern.slf4j.Slf4j; +import run.mone.ultraman.bo.DesensitizeReq; +import run.mone.ultraman.common.GsonUtils; +import run.mone.ultraman.http.HttpClient; /** * @author goodjava@qq.com * @date 2023/12/10 15:28 */ +@Slf4j public class AiCodeService { public static void generateBizCode(String scope, Project project, String comment) { ApplicationManager.getApplication().invokeLater(() -> PromptService.dynamicInvoke(getGenerateCodeReq(project, scope, comment))); } + //计算两数和(method) + + + public static GenerateCodeReq getGenerateCodeReq(Project project, String scope, String comment) { - PromptInfo promptInfo = Prompt.getPromptInfo("biz_sidecar"); + PromptInfo promptInfo = Prompt.getPromptInfo(Const.GENERATE_CODE); return GenerateCodeReq.builder() .scope(scope) .chatComment(comment) @@ -31,5 +43,24 @@ public static GenerateCodeReq getGenerateCodeReq(Project project, String scope, .build(); } + /** + * Desensitizes a given Java code snippet by sending it to a configured AI proxy service and returns the desensitized version if the service responds with success; otherwise, returns the original snippet. + */ + public static String desensitizeCode(String codeSnippet) { + try { + String url = ConfigUtils.getConfig().getAiProxy() + "/desensitize"; + DesensitizeReq req = DesensitizeReq.builder().text(codeSnippet).langType("java").aiDesensitizeFlag(false).zzToken(ConfigUtils.getConfig().getzToken()).build(); + String rst = HttpClient.post(url, GsonUtils.gson.toJson(req)); + JsonObject res = GsonUtils.gson.fromJson(rst, JsonObject.class); + int code = res.get("code").getAsInt(); + if (code == 0) { + return res.get("data").getAsString(); + } + return codeSnippet; + } catch (Throwable ex) { + log.error(ex.getMessage()); + return codeSnippet; + } + } } diff --git a/athena-all/src/main/java/run/mone/ultraman/service/AthenaCodeService.java b/athena-all/src/main/java/run/mone/ultraman/service/AthenaCodeService.java index 74ba3d2f9..a157f156a 100644 --- a/athena-all/src/main/java/run/mone/ultraman/service/AthenaCodeService.java +++ b/athena-all/src/main/java/run/mone/ultraman/service/AthenaCodeService.java @@ -3,19 +3,24 @@ import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.ImportDeclaration; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.PackageDeclaration; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.comments.Comment; +import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithPrivateModifier; import com.google.common.hash.Hashing; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.AiMessage; -import run.mone.m78.ip.bo.MessageConsumer; -import run.mone.m78.ip.bo.z.EmbeddingStatus; -import run.mone.m78.ip.bo.z.ZKnowledgeRes; -import run.mone.m78.ip.bo.z.ZResult; -import run.mone.m78.ip.common.NotificationCenter; -import run.mone.m78.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.bo.AiMessage; +import com.xiaomi.youpin.tesla.ip.bo.MessageConsumer; +import com.xiaomi.youpin.tesla.ip.bo.z.EmbeddingStatus; +import com.xiaomi.youpin.tesla.ip.bo.z.ZKnowledgeRes; +import com.xiaomi.youpin.tesla.ip.bo.z.ZResult; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.service.CodeService; import it.unimi.dsi.fastutil.Pair; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -53,32 +58,151 @@ public static String getCodeServer() { @SneakyThrows public static Pair callProxy(Project project, Map map, String promptName, int timeout) { - return null; + CountDownLatch latch = new CountDownLatch(1); + StringBuilder sb = new StringBuilder(); + CodeService.generateCodeWithAi4(project, promptName, new String[]{}, map, (p, msg) -> { + }, new MessageConsumer() { + @Override + public void onEvent(AiMessage message) { + sb.append(message.getText()); + } + + @Override + public void end(AiMessage message) { + latch.countDown(); + } + }); + latch.await(timeout, TimeUnit.SECONDS); + String str = sb.toString(); + return Pair.of(str.length(), str); } //解析代码,返回一个列表,每个元素包含一个类信息和对应的代码字符串 public static List> parseCode(String code) { - return null; + JavaParser javaParser = new JavaParser(); + CompilationUnit cu = javaParser.parse(code).getResult().get(); + List> res = new ArrayList<>(); + cu.findAll(ClassOrInterfaceDeclaration.class).stream().forEach(c -> { + String classCode = c.toString(); + String md5 = md5(classCode); + + AthenaClassInfo ci = AthenaClassInfo.builder().name(c.getNameAsString()).md5(md5).classCode(classCode).build(); + res.add(AthenaPair.of(ci, classCode)); + }); + return res; } - public static AthenaClassInfo classInfo(String code) { - return null; + public static AthenaClassInfo classInfoWithDetail(String code, boolean needDetail) { + int len = code.length(); + + JavaParser javaParser = new JavaParser(); + ParseResult pr = javaParser.parse(code); + if (!pr.isSuccessful()) { + System.out.println(pr.getProblems()); + return null; + } + CompilationUnit cu = pr.getResult().get(); + Optional classOptional = cu.findAll(ClassOrInterfaceDeclaration.class).stream().findFirst(); + + String packagePath = ""; + + // 获取包声明 + Optional packageDeclaration = cu.getPackageDeclaration(); + if (packageDeclaration.isPresent()) { + // 获取包的完整路径 + packagePath = packageDeclaration.get().getNameAsString(); + } + + //只保留public method的函数定义 + List methodList = cu.findAll(MethodDeclaration.class).stream().filter(it -> it.isPublic()).map(it -> { + if (it.getBody().isPresent()) { + it.remove(it.getBody().get()); + } + return it.toString(); + }).collect(Collectors.toList()); + + + //干掉所有private的函数 + cu.findAll(MethodDeclaration.class).stream().filter(NodeWithPrivateModifier::isPrivate).forEach(Node::removeForced); + + //干掉构造函数 + cu.findAll(ConstructorDeclaration.class).stream().forEach(Node::removeForced); + + cu.findAll(InitializerDeclaration.class, InitializerDeclaration::isStatic).forEach(Node::removeForced); + + if (len > 5000) { + //删除所有字段 + cu.findAll(FieldDeclaration.class).stream().forEach(Node::removeForced); + } + + String name = classOptional.isPresent() ? classOptional.get().getNameAsString() : ""; + + List list = new ArrayList<>(); + List annoList = new ArrayList<>(); + if (classOptional.isPresent()) { + annoList = classOptional.get().getAnnotations().stream().map(AnnotationExpr::getNameAsString).collect(Collectors.toList()); + list = classOptional.get().getImplementedTypes().stream().map(Node::toString).collect(Collectors.toList()); + } + + AthenaClassInfo athenaClassInfo = AthenaClassInfo.builder().name(name).packagePath(packagePath).interfaceList(list).annoList(annoList).publicMethodList(methodList).classCode(cu.toString()).build(); + + if (needDetail) { + List imports = cu.getImports().stream().map(ImportDeclaration::getNameAsString).collect(Collectors.toList()); + athenaClassInfo.setImports(imports); + } + + return athenaClassInfo; } + public static AthenaClassInfo classInfo(String code) { + return classInfoWithDetail(code, false); + } public static String parseAndSkipCode(String code) { + JavaParser javaParser = new JavaParser(); + CompilationUnit cu = javaParser.parse(code).getResult().get(); + List list = cu.findAll(MethodDeclaration.class).stream().filter(it -> { + Optional comment = it.getComment(); + if (comment.isPresent()) { + comment.stream().filter(it2 -> { + if (it2.isLineComment() && it2.toString().startsWith("//skip")) { + return false; + } + return true; + }); + } + return true; + }).collect(Collectors.toList()); return ""; } //解析方法代码,返回一个包含AthenaMethodInfo对象的列表 public static List parseMethodCode(String code) { - return null; + JavaParser javaParser = new JavaParser(); + CompilationUnit cu = javaParser.parse(code).getResult().get(); + return cu.findAll(MethodDeclaration.class).stream().map(it -> { + String methodCode = it.toString(); + return AthenaMethodInfo.builder() + .name(it.getNameAsString()) + .md5(md5(methodCode)) + .code(methodCode).build(); + }) + .collect(Collectors.toList()); } //解析方法代码,返回一个包含AthenaMethodInfo对象的列表 public static List parseFieldCode(String code) { - return null; + JavaParser javaParser = new JavaParser(); + CompilationUnit cu = javaParser.parse(code).getResult().get(); + return cu.findAll(FieldDeclaration.class).stream().map(it -> { + String fieldCode = it.toString(); + return AthenaFieldInfo.builder() + .name(fieldCode) + .md5(md5(fieldCode)) + .code(fieldCode).build(); + }) + .collect(Collectors.toList()); } @@ -89,31 +213,73 @@ public static String md5(String code) { //上传方法代码的实现 public static void uploadMethodCode(CodeReq req) { + if (!openCodeServer) { + return; + } + List list = parseMethodCode(req.getCode()); + req.setData(gson.toJson(list)); + HttpClient.asyncCallHttpServer(getCodeServer() + "/upload/method", "upload_method_code", gson.toJson(req), (msg) -> NotificationCenter.notice(null, "biz code upload success", true)); } //获取方法代码列表 public static List getMethodCodeList(CodeReq req) { - return null; + if (!openCodeServer) { + return Lists.newArrayList(); + } + String res = HttpClient.callHttpServer(getCodeServer() + "/code/method", "get_method_code", req.getRequirement()); + Type typeOfT = new TypeToken>() { + }.getType(); + return gson.fromJson(res, typeOfT); } public static EmbeddingStatus embeddingStatus(CodeReq req) { - return null; + String res = HttpClient.callHttpServer(getCodeServer() + "/api/z/open/athena/code/embedding/status", "embedding_status", gson.toJson(req)); + Type typeOfT = new TypeToken>() { + }.getType(); + ZResult zres = gson.fromJson(res, typeOfT); + return zres.getData(); } //上传代码到服务器(那边的服务器会计算向量) public static void uploadCode(CodeReq req) { + if (!openCodeServer) { + return; + } + List> list = parseCode(req.getCode()).stream().collect(Collectors.toList()); + req.setData(gson.toJson(list)); + HttpClient.asyncCallHttpServer(getCodeServer() + "/api/z/open/athena/code/embedding", "upload_code", gson.toJson(req), (msg) -> NotificationCenter.notice(null, "biz code upload success", true)); } //获取和这次业务相关的代码(根据需求取回相应的代码片段) public static List getCodeList(CodeReq req) { + if (!openCodeServer) { + return Lists.newArrayList(); + } + log.info("project name:{} module name:{}", req.getProjectName(), req.getModuleName()); + try { + String res = HttpClient.callHttpServer(getCodeServer() + "/api/z/open/athena/code/similarQuery", "get_code", gson.toJson(req)); + Type typeOfT = new TypeToken>>() { + }.getType(); + ZResult> result = gson.fromJson(res, typeOfT); + return result.getData(); + } catch (Throwable ex) { + log.error(ex.getMessage(), ex); + } return Lists.newArrayList(); } public static List callSimilar(CodeReq req) { - return null; + if (!openCodeServer) { + return Lists.newArrayList(); + } + String res = HttpClient.callHttpServer(getCodeServer() + "/api/z/open/athena/code/similarQuery3", "get_code", gson.toJson(req)); + Type typeOfT = new TypeToken>>() { + }.getType(); + ZResult> result = gson.fromJson(res, typeOfT); + return result.getData(); } diff --git a/athena-all/src/main/java/run/mone/ultraman/service/AutoFlushBizService.java b/athena-all/src/main/java/run/mone/ultraman/service/AutoFlushBizService.java index e5288ae6c..8c1aa6c73 100644 --- a/athena-all/src/main/java/run/mone/ultraman/service/AutoFlushBizService.java +++ b/athena-all/src/main/java/run/mone/ultraman/service/AutoFlushBizService.java @@ -5,11 +5,13 @@ import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import run.mone.m78.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; import lombok.extern.slf4j.Slf4j; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** * @author wmin @@ -23,10 +25,47 @@ public class AutoFlushBizService { static String CHANGED = "changed"; public static void notifyDocumentChanged(VirtualFile file){ + + if (null == file) { + return; + } + + try { + if (LabelUtils.getLabelValue(null, "auto_biz_write", "false").equals("true") && file.getFileType() == JavaFileType.INSTANCE) { + String filePath = file.getPath(); + if (fileChangeStatus.containsKey(filePath)){ + Stack oldStack = fileChangeStatus.get(filePath); + if (null==oldStack || oldStack.empty()){ + Stack stack = new Stack<>(); + stack.push(CHANGED); + fileChangeStatus.put(filePath, stack); + } + } else { + Stack stack = new Stack<>(); + stack.push(CHANGED); + fileChangeStatus.put(filePath, stack); + } + } + } catch (Exception e){ + log.error("notifyDocumentChanged error."+file.getPath(), e); + } } public static void notifyDocumentClosed(VirtualFile file, Project project){ - + try { + if (LabelUtils.getLabelValue(null, "auto_biz_write", "false").equals("true") && file.getFileType() == JavaFileType.INSTANCE) { + String filePath = file.getPath(); + if (fileChangeStatus.containsKey(filePath)){ + Stack oldStack = fileChangeStatus.get(filePath); + if (null!=oldStack && !oldStack.empty() && CHANGED.equals(oldStack.pop())){ + log.info("file closed after changed, filePath:{}", filePath); + autoFlushBiz(file, project); + } + } + } + } catch (Exception e){ + log.error("notifyDocumentClosed error."+file.getPath(), e); + } } public static void autoFlushBiz(VirtualFile file, Project project){ @@ -34,4 +73,13 @@ public static void autoFlushBiz(VirtualFile file, Project project){ ModuleService.uploadFileText(project, module, file); } +// public void init(){ +// Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { +// if (LabelUtils.getLabelValue(null, "auto_biz_write", "false").equals("true")){ +// fileChangeStatus.entrySet().forEach(i ->{ +// +// }); +// } +// }, 5, 10, TimeUnit.MINUTES); +// } } diff --git a/athena-all/src/main/java/run/mone/ultraman/service/ModuleService.java b/athena-all/src/main/java/run/mone/ultraman/service/ModuleService.java index be46af1be..38bd1756e 100644 --- a/athena-all/src/main/java/run/mone/ultraman/service/ModuleService.java +++ b/athena-all/src/main/java/run/mone/ultraman/service/ModuleService.java @@ -16,11 +16,11 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiManager; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.common.NotificationCenter; -import run.mone.m78.ip.service.TextService; -import run.mone.m78.ip.util.LabelUtils; -import run.mone.m78.ip.util.PsiClassUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.NotificationCenter; +import com.xiaomi.youpin.tesla.ip.service.TextService; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import run.mone.ultraman.background.AthenaTask; @@ -39,13 +39,18 @@ public class ModuleService { /** * 上传单个java file 到 code server - * * @param project * @param module * @param file */ public static void uploadFileText(Project project, Module module, VirtualFile file) { - + Task.Backgroundable task = new Task.Backgroundable(project, "Upload code to code server.") { + @Override + public void run(@NotNull ProgressIndicator indicator) { + ApplicationManager.getApplication().invokeLater(() -> sendToCodeServer(Lists.newArrayList(javaFileText(project, module, file)), project, module, "virtual file")); + } + }; + AthenaTask.start(task); } @@ -56,21 +61,80 @@ public static void uploadFileText(Project project, Module module, VirtualFile fi * @param module */ public static void uploadModelText(Project project, Module module) { - + Task.Backgroundable task = new Task.Backgroundable(project, "Upload code to code server.") { + @Override + public void run(@NotNull ProgressIndicator indicator) { + ApplicationManager.getApplication().invokeLater(() -> { + List list = new ArrayList<>(); + ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); + for (VirtualFile contentRoot : contentRoots) { + projectFileIndex.iterateContentUnderDirectory(contentRoot, virtualFile -> { + if (virtualFile.getFileType() == JavaFileType.INSTANCE) { + String str = javaFileText(project, module, virtualFile); + list.add(str); + } + return true; + }); + } + sendToCodeServer(list, project, module, "module"); + }); + + } + }; + AthenaTask.start(task); } private static void sendToCodeServer(List list, Project project, Module module, String type) { + String str = Joiner.on("\n\n").join(list); + + //上传到code 服务器 + new Thread(() -> { + log.info("upload code {} type:{}", list.size(), type); + AthenaCodeService.uploadCode(CodeReq.builder().projectName(project.getName()) + .moduleName(module.getName()) + .code(str) + .build()); + }).start(); + + + NotificationCenter.notice(project, "biz code size:" + str.length() + " module name:" + module.getName() + " type:" + type, true); + //一次性写入 + if (LabelUtils.getLabelValue(null, "biz_write", "false").equals("true")) { + TextService.writeContent(project, Const.MODULE_FILE_NAME, module.getName(), () -> { + }, "```\n" + str + "\n```"); + } } public static String javaFileText(Project project, Module module, VirtualFile virtualFile) { - return ""; + PsiManager psiManager = PsiManager.getInstance(project); + PsiFile psiFile = psiManager.findFile(virtualFile); + + List list = new ArrayList<>(); + if (psiFile instanceof PsiJavaFile) { + PsiJavaFile psiJavaFile = (PsiJavaFile) psiFile; + //跳过测试类 + if (psiJavaFile.getName().endsWith("Test.java")) { + return ""; + } + PsiClass[] psiClasses = psiJavaFile.getClasses(); + for (PsiClass psiClass : psiClasses) { + //跳过接口 + if (psiClass.isInterface()) { + continue; + } + list.add(classText(project, psiClass)); + } + } + return Joiner.on("\n\n").join(list); } public static String classText(Project project, PsiClass psiClass) { - return ""; + String text = PsiClassUtils.getInterfaceText(project, psiClass); + return text; } } diff --git a/athena-all/src/main/java/run/mone/ultraman/startup/AthenaStartupActivity.java b/athena-all/src/main/java/run/mone/ultraman/startup/AthenaStartupActivity.java new file mode 100644 index 000000000..bed4d57d9 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/startup/AthenaStartupActivity.java @@ -0,0 +1,32 @@ +//package run.mone.ultraman.startup; +// +//import com.intellij.openapi.project.Project; +//import com.intellij.openapi.startup.ProjectActivity; +//import kotlin.Unit; +//import kotlin.coroutines.Continuation; +//import lombok.extern.slf4j.Slf4j; +//import org.jetbrains.annotations.NotNull; +//import org.jetbrains.annotations.Nullable; +// +///** +// * @author goodjava@qq.com +// * @date 2024/5/29 09:20 +// */ +//@Slf4j +//public class AthenaStartupActivity implements ProjectActivity { +// +// @Nullable +// @Override +// public Object execute(@NotNull Project project, @NotNull Continuation continuation) { +// log.info("open project:{}", project.getName()); +//// TerminalExecutionConsole terminalConsole = new TerminalExecutionConsole(project, new JBTerminalWidget(project)); +//// terminalConsole.getTerminalWidget().addMessageFilter(new Filter() { +//// @Override +//// public @Nullable Result applyFilter(@NotNull String line, int entireLength) { +//// return null; +//// } +//// }); +// +// return null; +// } +//} diff --git a/athena-all/src/main/java/run/mone/ultraman/state/AthenaEvent.java b/athena-all/src/main/java/run/mone/ultraman/state/AthenaEvent.java index d2c118ee6..e8b38b304 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/AthenaEvent.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/AthenaEvent.java @@ -1,7 +1,7 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.PromptType; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/ultraman/state/CalState.java b/athena-all/src/main/java/run/mone/ultraman/state/CalState.java index 1fa8c3735..0438b473d 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/CalState.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/CalState.java @@ -1,6 +1,6 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; /** * @author goodjava@qq.com diff --git a/athena-all/src/main/java/run/mone/ultraman/state/FsmManager.java b/athena-all/src/main/java/run/mone/ultraman/state/FsmManager.java index 020ce5acb..264ae0f8a 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/FsmManager.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/FsmManager.java @@ -1,6 +1,6 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; diff --git a/athena-all/src/main/java/run/mone/ultraman/state/GlobalState.java b/athena-all/src/main/java/run/mone/ultraman/state/GlobalState.java index d746440a3..a8931ad94 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/GlobalState.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/GlobalState.java @@ -1,6 +1,6 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.util.UltramanConsole; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.common.GsonUtils; @@ -28,8 +28,8 @@ public class GlobalState extends AthenaState { @Override public void execute(StateReq req, StateContext context) { //10秒一打印 - if (System.currentTimeMillis() - lastUpdateTime > 10000) { - log.info("project:{} state:{}", context.getProject(), this.fsm.getCurrentState()); + if (System.currentTimeMillis() - lastUpdateTime > 100000) { + log.debug("project:{} state:{}", context.getProject(), this.fsm.getCurrentState()); if (StringUtils.isNotEmpty(context.getProject())) { UltramanConsole.append(context.getProject(), "ai fsm state:" + this.fsm.getCurrentState() + " step:(" + context.getStep() + "/" + context.getFinishStep() + ") question:" + context.getQuestion() + "(" + context.getPromptStep() + "/" + context.getFinishPromptStep() + ")"); } diff --git a/athena-all/src/main/java/run/mone/ultraman/state/InitQuestionState.java b/athena-all/src/main/java/run/mone/ultraman/state/InitQuestionState.java index 9d0ce48d9..881d9569f 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/InitQuestionState.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/InitQuestionState.java @@ -1,7 +1,7 @@ package run.mone.ultraman.state; import com.google.common.base.Splitter; -import run.mone.m78.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; import org.apache.commons.lang3.StringUtils; import run.mone.ultraman.common.GsonUtils; diff --git a/athena-all/src/main/java/run/mone/ultraman/state/PromptAndFunctionProcessor.java b/athena-all/src/main/java/run/mone/ultraman/state/PromptAndFunctionProcessor.java index cd665f745..1fc201c0f 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/PromptAndFunctionProcessor.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/PromptAndFunctionProcessor.java @@ -3,22 +3,24 @@ import com.google.common.base.Stopwatch; import com.google.gson.JsonObject; import com.intellij.openapi.project.Project; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.PromptContext; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.bo.chatgpt.Completions; -import run.mone.m78.ip.bo.chatgpt.Format; -import run.mone.m78.ip.bo.chatgpt.Message; -import run.mone.m78.ip.bo.robot.*; -import run.mone.m78.ip.common.ChromeUtils; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.service.AiService; -import run.mone.m78.ip.service.PromptService; -import run.mone.m78.ip.service.RobotService; -import run.mone.m78.ip.util.ResourceUtils; -import run.mone.m78.ip.util.UltramanConsole; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptContext; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Completions; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Format; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Message; +import com.xiaomi.youpin.tesla.ip.bo.robot.*; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.service.AiService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.service.RobotService; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.util.ResourceUtils; +import com.xiaomi.youpin.tesla.ip.util.UltramanConsole; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import run.mone.ultraman.AthenaContext; import run.mone.ultraman.common.FunctionReqUtils; @@ -32,6 +34,8 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static com.xiaomi.youpin.tesla.ip.common.Const.USE_BOT_MODEL; + /** * @author goodjava@qq.com * @date 2023/12/4 17:53 @@ -71,7 +75,15 @@ public static JsonObject callPrompt(Project project, PromptInfo promptInfo, Map< Completions completions = Completions.builder().stream(false).response_format(Format.builder().build()).messages(messageList).build(); UltramanConsole.append(project, "call ai prompt:" + promptInfo.getPromptName()); Stopwatch swCallAi = Stopwatch.createStarted(); - JsonObject jsonObj = AiService.call(GsonUtils.gson.toJson(completions), Long.parseLong(promptInfo.getLabels().getOrDefault("timeout", "50000")), vip); + + boolean jsonResult = promptInfo.open("json_result", "true"); + //如果是local,使用自己定义的模型 + if (LabelUtils.open(Const.OPEN_AI_TEST)) { + completions.setModel(ResourceUtils.getAthenaConfig().getOrDefault(Const.OPEN_AI_MODEL, "gpt4_o")); + } else { + completions.setModel(StringUtils.isNotBlank(AthenaContext.ins().getNoChatModel()) || !USE_BOT_MODEL.equals(AthenaContext.ins().getNoChatModel()) ? AthenaContext.ins().getNoChatModel() : "gpt4_o"); + } + JsonObject jsonObj = AiService.call(GsonUtils.gson.toJson(completions), Long.parseLong(promptInfo.getLabels().getOrDefault("timeout", "50000")), vip, jsonResult); UltramanConsole.append(project, "call ai prompt:" + promptInfo.getPromptName() + " finish res:" + jsonObj + " use time:" + swCallAi.elapsed(TimeUnit.SECONDS) + "s"); return jsonObj; } diff --git a/athena-all/src/main/java/run/mone/ultraman/state/QuestionState.java b/athena-all/src/main/java/run/mone/ultraman/state/QuestionState.java index df48464ee..fa299f3b7 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/QuestionState.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/QuestionState.java @@ -1,10 +1,10 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.bo.robot.AiChatMessage; -import run.mone.m78.ip.bo.robot.MessageType; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; -import run.mone.m78.ip.bo.robot.Role; -import run.mone.m78.ip.common.ChromeUtils; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.MessageType; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.common.ChromeUtils; import lombok.extern.slf4j.Slf4j; /** diff --git a/athena-all/src/main/java/run/mone/ultraman/state/StateReq.java b/athena-all/src/main/java/run/mone/ultraman/state/StateReq.java index c1e4b9e3e..4d7c0a332 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/StateReq.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/StateReq.java @@ -1,7 +1,7 @@ package run.mone.ultraman.state; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.common.PromptType; import lombok.Builder; import lombok.Data; diff --git a/athena-all/src/main/java/run/mone/ultraman/state/WaitQuestionState.java b/athena-all/src/main/java/run/mone/ultraman/state/WaitQuestionState.java index 5f32daa83..d1d5f802a 100644 --- a/athena-all/src/main/java/run/mone/ultraman/state/WaitQuestionState.java +++ b/athena-all/src/main/java/run/mone/ultraman/state/WaitQuestionState.java @@ -1,9 +1,9 @@ package run.mone.ultraman.state; import com.google.gson.reflect.TypeToken; -import run.mone.m78.ip.bo.robot.AiChatMessage; -import run.mone.m78.ip.bo.robot.ProjectAiMessageManager; -import run.mone.m78.ip.bo.robot.Role; +import com.xiaomi.youpin.tesla.ip.bo.robot.AiChatMessage; +import com.xiaomi.youpin.tesla.ip.bo.robot.ProjectAiMessageManager; +import com.xiaomi.youpin.tesla.ip.bo.robot.Role; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidget.java b/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidget.java index d1fe65ccb..d34cb67c4 100644 --- a/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidget.java +++ b/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidget.java @@ -1,6 +1,11 @@ package run.mone.ultraman.statusbar; +import com.google.common.collect.ImmutableList; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; @@ -11,29 +16,42 @@ import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Consumer; -import run.mone.m78.ip.bo.GenerateCodeReq; -import run.mone.m78.ip.bo.PromptInfo; -import run.mone.m78.ip.common.Const; -import run.mone.m78.ip.common.Prompt; -import run.mone.m78.ip.common.PromptType; -import run.mone.m78.ip.service.PromptService; -import run.mone.m78.ip.util.LabelUtils; +import com.xiaomi.youpin.tesla.ip.bo.GenerateCodeReq; +import com.xiaomi.youpin.tesla.ip.bo.PromptInfo; +import com.xiaomi.youpin.tesla.ip.bo.Tag; +import com.xiaomi.youpin.tesla.ip.common.Const; +import com.xiaomi.youpin.tesla.ip.common.Prompt; +import com.xiaomi.youpin.tesla.ip.common.PromptType; +import com.xiaomi.youpin.tesla.ip.service.CodeService; +import com.xiaomi.youpin.tesla.ip.service.PromptService; +import com.xiaomi.youpin.tesla.ip.util.EditorUtils; +import com.xiaomi.youpin.tesla.ip.util.LabelUtils; +import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import run.mone.ultraman.AthenaContext; +import run.mone.ultraman.AthenaInspection; import run.mone.ultraman.bo.ClientData; import run.mone.ultraman.statusbar.bo.PopupItem; import java.awt.*; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; +import static com.xiaomi.youpin.tesla.ip.common.Const.GENERATE_CODE; +import static com.xiaomi.youpin.tesla.ip.common.Const.UNIT_TEST; +import static run.mone.ultraman.statusbar.PopUpReq.POP_ORIGIN_LINE_MARK; +import static run.mone.ultraman.statusbar.PopUpReq.POP_ORIGIN_STATUS_BAR; + /** * @author goodjava@qq.com * @date 2023/7/18 23:41 */ +@Slf4j public class AthenaStatusBarWidget implements StatusBarWidget { private final Project project; @@ -66,48 +84,22 @@ public void dispose() { @Override public @Nullable @NlsContexts.Tooltip String getTooltipText() { - return "Athena"; + return Const.PLUGIN_NAME; } @Override public @Nullable Consumer getClickConsumer() { return (MouseEvent e) -> { - if (!LabelUtils.open(Const.ENABLE_ATHENA_STATUS_BAR)) { return; } - - List collectedList = Prompt.getCollected(); - collectedList.addAll(Prompt.getPromptInfoByTag("system")); - List list = collectedList.stream().filter(it -> it.getTags().stream().map(i -> i.getName()).collect(Collectors.toList()).contains("popup")).map(it -> PopupItem.builder().name(it.getPromptName()).desc(it.getDesc()).build()).collect(Collectors.toList()); - ListPopup listPopup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Prompt", list) { - @Override - public PopupStep onChosen(PopupItem selectedValue, boolean finalChoice) { - ApplicationManager.getApplication().invokeLater(() -> { - PromptInfo info = Prompt.getPromptInfo(selectedValue.getName()); - PromptType type = Prompt.getPromptType(info); - ClientData clientData = AthenaContext.ins().getClientData(project.getName()); - PromptService.dynamicInvoke(GenerateCodeReq.builder() - .scope(clientData.getScope()) - .project(project) - .projectName(project.getName()) - .promptInfo(info).promptType(type) - .promptName(selectedValue.getName()) - .build()); - }); - return super.onChosen(selectedValue, finalChoice); - } - }); - Rectangle r = statusBar.getComponent().getBounds(); - Point p = new Point(r.x + r.width, r.y + r.height); - RelativePoint showPoint = new RelativePoint(statusBar.getComponent(), p); - listPopup.show(showPoint); + popUp(project, statusBar, e, PopUpReq.builder().build()); }; } @Override public @NotNull @NlsContexts.Label String getText() { - return "Athena"; + return Const.PLUGIN_NAME; } @Override @@ -116,4 +108,108 @@ public float getAlignment() { } }; } + + + //弹出插件的界面 + public static void popUp(Project project, StatusBar statusBar, MouseEvent mouseEvent, PopUpReq req) { + if (!Objects.isNull(req.getPsiMethod())) { + CodeService.moveCaretToMethod(CodeService.getEditor(project), req.getPsiMethod()); + } + if (!Objects.isNull(req.getPsiComment())) { + CodeService.moveCaretToOffset(CodeService.getEditor(project), req.getOffset()); + } + + List collectedList = new ArrayList<>(); + if (POP_ORIGIN_STATUS_BAR == req.getOrigin()) { + collectedList.add(Prompt.getPromptInfo(GENERATE_CODE)); + collectedList.addAll(Prompt.getPromptInfoByTag("method_inspection")); + collectedList.addAll(Prompt.getPromptInfoByTag("status_bar")); + } else if (POP_ORIGIN_LINE_MARK == req.getOrigin()) { + if (req.getPsiComment() != null) { + collectedList.add(Prompt.getPromptInfo(GENERATE_CODE)); + } else { + collectedList.addAll(Prompt.getPromptInfoByTag("method_inspection")); + } + } + if (collectedList.isEmpty()) { + collectedList.add(PromptInfo.builder() + .tags(ImmutableList.of(Tag.builder().name("popup").build())) + .promptName("无操作") + .desc("无操作") + .build()); + } + List list = collectedList.stream() + .filter(it -> it.getTags() + .stream() + .map(Tag::getName) + .toList() + .contains("popup")) + .map(it -> PopupItem.builder().name(it.getPromptName()).desc(it.getDesc()).build()).collect(Collectors.toList()); + ListPopup listPopup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<>("Mione AI Code助手", list) { + @Override + public PopupStep onChosen(PopupItem selectedValue, boolean finalChoice) { + String pName = selectedValue.getName(); + //移动光标位置 + if (GENERATE_CODE.equals(pName)) { + EditorUtils.moveCaretToCommentEnd(EditorUtils.getEditor(project)); + } + if (UNIT_TEST.equals(pName)) { + doFinalStep(() -> ApplicationManager.getApplication().runReadAction(() -> { + executePrompt(pName, project); + })); + } else { + ApplicationManager.getApplication().executeOnPooledThread(() -> { + executePrompt(pName, project); + }); + } + return super.onChosen(selectedValue, finalChoice); + } + }); + + if (mouseEvent != null) { + listPopup.showInScreenCoordinates(mouseEvent.getComponent(), mouseEvent.getLocationOnScreen()); + } else if (statusBar != null) { + Rectangle r = statusBar.getComponent().getBounds(); + Point p = new Point(r.x + r.width, r.y + r.height); + RelativePoint showPoint = new RelativePoint(statusBar.getComponent(), p); + listPopup.show(showPoint); + } else { + Editor editor = EditorUtils.getEditor(project); + if (editor instanceof EditorEx) { + EditorEx editorEx = (EditorEx) editor; + LogicalPosition logicalPosition = editorEx.getCaretModel().getLogicalPosition(); + VisualPosition visualPosition = editorEx.logicalToVisualPosition(logicalPosition); + Point point = editorEx.visualPositionToXY(visualPosition); + RelativePoint showPoint = new RelativePoint(editorEx.getContentComponent(), point); + listPopup.show(showPoint); + } + } + } + + private static void executePrompt(String promptName, Project project) { + PromptInfo promptInfo = Prompt.getPromptInfo(promptName); + PromptType promptType = Prompt.getPromptType(promptInfo); + ClientData clientData = AthenaContext.ins().getClientData(project.getName()); + if (AthenaInspection.isBotUsageConfigured(promptInfo)) { + promptType = PromptType.executeBot; + } + PromptService.dynamicInvoke(GenerateCodeReq.builder() + .scope(clientData.getScope()) + .project(project) + .projectName(project.getName()) + .promptInfo(promptInfo) + .promptType(promptType) + .promptName(promptName) + .build()); + } + + private static boolean isCursorInComment(Project project) { + Editor editor = CodeService.getEditor(project); + if (null != editor) { + boolean isInComment = CodeService.isCursorInComment(editor); + log.debug("is in comment:{}", isInComment); + return isInComment; + } + return false; + } } diff --git a/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidgetFactory.java b/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidgetFactory.java index c1a3e69a8..6e344d059 100644 --- a/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidgetFactory.java +++ b/athena-all/src/main/java/run/mone/ultraman/statusbar/AthenaStatusBarWidgetFactory.java @@ -4,6 +4,7 @@ import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.openapi.wm.StatusBarWidgetFactory; +import com.xiaomi.youpin.tesla.ip.common.Const; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -20,7 +21,7 @@ public class AthenaStatusBarWidgetFactory implements StatusBarWidgetFactory { @Override public @Nls @NotNull String getDisplayName() { - return "Athena"; + return Const.PLUGIN_NAME; } @Override diff --git a/athena-all/src/main/java/run/mone/ultraman/statusbar/PopUpReq.java b/athena-all/src/main/java/run/mone/ultraman/statusbar/PopUpReq.java new file mode 100644 index 000000000..23c41fb33 --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/statusbar/PopUpReq.java @@ -0,0 +1,38 @@ +package run.mone.ultraman.statusbar; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiMethod; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author goodjava@qq.com + * @date 2024/6/27 13:01 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PopUpReq implements Serializable { + + public static final int POP_ORIGIN_STATUS_BAR = 0; + + public static final int POP_ORIGIN_LINE_MARK = 1; + + private PsiMethod psiMethod; + + private PsiComment psiComment; + + private Editor editor; + + private int offset; + + @Builder.Default + private int origin = POP_ORIGIN_STATUS_BAR; + +} diff --git a/athena-all/src/main/java/run/mone/ultraman/visitor/M78Visitor.java b/athena-all/src/main/java/run/mone/ultraman/visitor/M78Visitor.java new file mode 100644 index 000000000..4b427670b --- /dev/null +++ b/athena-all/src/main/java/run/mone/ultraman/visitor/M78Visitor.java @@ -0,0 +1,153 @@ +package run.mone.ultraman.visitor; + +import com.google.common.collect.Lists; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.psi.*; +import com.xiaomi.youpin.tesla.ip.util.ImportUtils; +import com.xiaomi.youpin.tesla.ip.util.PsiClassFixer; +import com.xiaomi.youpin.tesla.ip.util.PsiClassUtils; +import org.apache.commons.collections.CollectionUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author goodjava@qq.com + * @date 2024/4/21 21:19 + */ +public class M78Visitor extends JavaElementVisitor { + + private String packageStr = ""; + + private String className = ""; + + private PsiJavaFile javaFile; + + private List missedImports; // HINT: 如果想要添加其他的import,须在配置访问者前设置该map + + private List wildCardImportPackages; // HINT: xxx.* 导入 + + + @Override + public void visitJavaFile(@NotNull PsiJavaFile file) { + this.javaFile = file; + this.packageStr = file.getPackageName(); + + @Nullable PsiImportList importList = file.getImportList(); + if (null != importList) { + this.visitImportList(importList); + } + + PsiClass[] classes = file.getClasses(); + Arrays.stream(classes).forEach(it -> { + this.visitClass(it); + }); + + } + + @Override + public void visitPackageStatement(@NotNull PsiPackageStatement statement) { + String text = statement.getPackageName(); + System.out.println("packcage:" + text); + this.packageStr = text; + } + + //如果缺少相应的字段,则直接添加这些字段 + @Override + public void visitClass(@NotNull PsiClass psiClass) { + String className = psiClass.getQualifiedName(); + System.out.println("class:" + className); + this.className = className; + + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + + Map annotationMap = Arrays.stream(psiClass.getAnnotations()).collect(Collectors.toMap(PsiAnnotation::getQualifiedName, Function.identity())); + if (!annotationMap.containsKey("lombok.Data") && !annotationMap.containsKey("Data")) { + WriteCommandAction.runWriteCommandAction(this.javaFile.getProject(), () -> { + psiClass.getModifierList().addAnnotation("Data"); + }); + } + + + //psiClass.ggetFields 转换成map key = name + Map fieldMap = Arrays.stream(psiClass.getFields()) + .collect(Collectors.toMap(PsiField::getName, Function.identity())); + + System.out.println(fieldMap); + if (!fieldMap.containsKey("id1")) { + ApplicationManager.getApplication().invokeLater(() -> { + + PsiField idField = elementFactory.createField("id1", PsiTypes.intType()); + // 将注解添加到字段上 + idField.getModifierList().addAnnotation("Id"); + PsiClassFixer.addFields(psiClass, Lists.newArrayList(idField)); + }); + } + } + + @Override + public void visitMethod(PsiMethod method) { + String methodName = method.getName(); + System.out.println("methodName:" + methodName); + } + + + //处理有没导入的类 + @Override + public void visitImportList(@NotNull PsiImportList list) { + Map map = Arrays.stream(list.getImportStatements()).collect(Collectors.toMap(PsiImportStatement::getQualifiedName, Function.identity())); + if (!map.containsKey("lombok.Data")) { + //添加进来缺失的lombok.Data + ApplicationManager.getApplication().invokeLater(() -> { + WriteCommandAction.runWriteCommandAction(this.javaFile.getProject(), () -> { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(list.getProject()); + PsiClass psiClass = ImportUtils.createPsiClass(elementFactory, "lombok.Data"); + PsiImportStatement importStatement = elementFactory.createImportStatement(psiClass); + javaFile.getImportList().add(importStatement); + if (CollectionUtils.isNotEmpty(missedImports)) { + // 添加其他确实的import + for (String missingClass : missedImports) { + PsiClass other = ImportUtils.createPsiClass(elementFactory, missingClass); + PsiImportStatement otherImport = elementFactory.createImportStatement(other); + javaFile.getImportList().add(otherImport); + } + + } + if (CollectionUtils.isNotEmpty(wildCardImportPackages)) { + // 添加 wildcard import + for (String packageName : wildCardImportPackages) { + PsiImportStatement wildCardImport = elementFactory.createImportStatementOnDemand(packageName); + javaFile.getImportList().add(wildCardImport); + } + } + }); + }); + } + + } + + + //添加注解 + @Override + public void visitField(@NotNull PsiField field) { + String name = field.getName(); + if (name.equals("id")) { + @Nullable PsiAnnotation anno = field.getAnnotation("dev.morphia.annotations.Id"); + System.out.println("field:" + anno); + } + } + + public void setMissedImports(List missedImports) { + this.missedImports = missedImports; + } + + public void setWildCardImportPackages(List wildCardImportPackages) { + this.wildCardImportPackages = wildCardImportPackages; + } +} diff --git a/athena-all/src/main/resources/META-INF/plugin.xml b/athena-all/src/main/resources/META-INF/plugin.xml index b139a0e38..f5d27ec99 100644 --- a/athena-all/src/main/resources/META-INF/plugin.xml +++ b/athena-all/src/main/resources/META-INF/plugin.xml @@ -4,13 +4,23 @@ Athena - mone - - - - + mone + + + + Mione Ai, an AI programming assistant. Produced by Mione +

    +
  • 功能入口统一至 "Suggestion":默认快捷键Alt+Enter(Windows/Linux) Opt + Enter(Mac)
  • +
  • 改进行内提示功能: 多行(空方法时触发),单行(方法内触发), 触发时间2s
  • +
  • 修复了若干已知问题
  • +
+

Version 2024.06.19.2

+ ]]> + JUnit + org.jetbrains.plugins.terminal - + - + - + + + + implementationClass="run.mone.ultraman.quickfix.M78Inspection"/> + + + + implementationClass="run.mone.ultraman.AthenaInspection"/> + + + + + + + + + + + + implementation="com.xiaomi.youpin.tesla.ip.search.AthenaSearchEverywhereContributorFactory"/> - + - + - + - + - + @@ -90,7 +117,7 @@ - run.mone.m78.ip.component.project.AthenaProjectComment + com.xiaomi.youpin.tesla.ip.component.project.AthenaProjectComment @@ -99,20 +126,16 @@ - run.mone.m78.ip.component.PluginComponent + com.xiaomi.youpin.tesla.ip.component.PluginComponent - run.mone.m78.ip.component.TeslaAppComponent + com.xiaomi.youpin.tesla.ip.component.TeslaAppComponent - run.mone.m78.ip.component.VersionComponent - - - - run.mone.m78.ip.component.UltramanComponent + com.xiaomi.youpin.tesla.ip.component.VersionComponent @@ -120,15 +143,14 @@ - - - - - - + + + + + - + diff --git a/athena-all/src/main/resources/athena.properties b/athena-all/src/main/resources/athena.properties new file mode 100644 index 000000000..58c68da71 --- /dev/null +++ b/athena-all/src/main/resources/athena.properties @@ -0,0 +1 @@ +pluginVersion = 2024.07.17.1 diff --git a/athena-all/src/main/resources/icons/M-2.svg b/athena-all/src/main/resources/icons/M-2.svg new file mode 100644 index 000000000..c1352e38c --- /dev/null +++ b/athena-all/src/main/resources/icons/M-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/athena-all/src/main/resources/icons/M.svg b/athena-all/src/main/resources/icons/M.svg new file mode 100644 index 000000000..006677108 --- /dev/null +++ b/athena-all/src/main/resources/icons/M.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/athena-all/src/main/resources/icons/M2.svg b/athena-all/src/main/resources/icons/M2.svg new file mode 100644 index 000000000..f54b7dcce --- /dev/null +++ b/athena-all/src/main/resources/icons/M2.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/athena-all/src/test/java/run/mone/ultraman/test/AiTest.java b/athena-all/src/test/java/run/mone/ultraman/test/AiTest.java index bcad78290..a3ef47323 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/AiTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/AiTest.java @@ -3,11 +3,15 @@ import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.JsonObject; -import run.mone.m78.ip.bo.chatgpt.Completions; -import run.mone.m78.ip.bo.chatgpt.Format; -import run.mone.m78.ip.bo.chatgpt.Message; -import run.mone.m78.ip.service.LocalAiService; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Completions; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Format; +import com.xiaomi.youpin.tesla.ip.bo.chatgpt.Message; +import com.xiaomi.youpin.tesla.ip.service.LocalAiService; +import lombok.SneakyThrows; import org.junit.Test; +import run.mone.openai.StreamListener; + +import java.util.concurrent.TimeUnit; /** * @author goodjava@qq.com @@ -23,9 +27,27 @@ public void testCall() { Completions completions = Completions.builder() .stream(false) .response_format(Format.builder().build()) - .model("gpt-4-1106-preview").messages(Lists.newArrayList(Message.builder().role("system").content("你是我的ai助手,请返回json格式数据").build(),Message.builder().role("user").content("1+1=?").build())).build(); +// .model("gpt-4-1106-preview") + .model("gpt-4o") + .messages(Lists.newArrayList(Message.builder().role("system").content("你是我的ai助手,请返回json格式数据").build(),Message.builder().role("user").content("1+1=?").build())).build(); JsonObject res = LocalAiService.call(gson.toJson(completions)); System.out.println(res); } + @SneakyThrows + @Test + public void testCall2() { + Completions completions = Completions.builder() + .stream(true) + .response_format(Format.builder().build()) +// .model("gpt-4-1106-preview") + .model("gpt-4o") + .messages(Lists.newArrayList(Message.builder().role("system").content("你是我的ai助手,请返回json格式数据").build(),Message.builder().role("user").content("1+1=?").build())).build(); + LocalAiService.completions(gson.toJson(completions), str -> { + System.out.println(str); + }); + + TimeUnit.MINUTES.sleep(1); + } + } diff --git a/athena-all/src/test/java/run/mone/ultraman/test/AthenaCodeServiceTest.java b/athena-all/src/test/java/run/mone/ultraman/test/AthenaCodeServiceTest.java index a955f065a..0050c3378 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/AthenaCodeServiceTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/AthenaCodeServiceTest.java @@ -7,11 +7,16 @@ import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.InitializerDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.Statement; +import com.xiaomi.youpin.tesla.ip.util.FixCodeUtils; import lombok.SneakyThrows; import org.junit.Test; import run.mone.ultraman.bo.AthenaClassInfo; import run.mone.ultraman.bo.AthenaFieldInfo; import run.mone.ultraman.bo.AthenaMethodInfo; +import run.mone.ultraman.bo.AthenaPair; +import run.mone.ultraman.listener.CaretHoverPlugin; import run.mone.ultraman.service.AthenaCodeService; import java.nio.file.Files; @@ -34,17 +39,57 @@ public void testParseMethod() { @SneakyThrows @Test public void testClassInfo() { - String code = Files.readString(Paths.get("/tmp/o.java")); + String code = Files.readString(Paths.get("src/main/java/run/mone/ultraman/AthenaContext.java")); AthenaClassInfo info = AthenaCodeService.classInfo(code); System.out.println(info); System.out.println(info.getClassCode().length()); + + System.out.println("--------"); + info.getPublicMethodList().forEach(it -> { + System.out.println(it); + }); + System.out.println("-------"); + System.out.println(info.getClassCode()); + } + + @SneakyThrows + @Test + public void testAddDataAnnotationForClass() { + String code = Files.readString(Paths.get("/your path/PageBase.java")); + AthenaClassInfo athenaClassInfo = AthenaCodeService.classInfoWithDetail(code, true); + String newCode = FixCodeUtils.addDataAnnotationForClass(code, athenaClassInfo); + + System.out.println(newCode); + } + + @SneakyThrows + @Test + public void testAddBasicImportForClass() { + String code = Files.readString(Paths.get("/your path/SlaServiceImpl.java")); + AthenaClassInfo athenaClassInfo = AthenaCodeService.classInfoWithDetail(code, true); + String newCode = FixCodeUtils.addBasicImportForClass(code, athenaClassInfo); + + System.out.println(newCode); + } + + + @SneakyThrows + @Test + public void testParseCode() { + + String code = Files.readString(Paths.get("/your path/PageBase.java")); +// String code = Files.readString(Paths.get("/tmp/k")); +// String code = Files.readString(Paths.get("/tmp/o.java")); + List> info = AthenaCodeService.parseCode(code); + + System.out.println(info); } @SneakyThrows @Test public void testRemove() { - String code = Files.readString(Paths.get("/tmp/T.java")); + String code = Files.readString(Paths.get("/your path/T.java")); JavaParser javaParser = new JavaParser(); ParseResult pr = javaParser.parse(code); if (!pr.isSuccessful()) { @@ -52,10 +97,10 @@ public void testRemove() { } CompilationUnit cu = pr.getResult().get(); cu.findAll(MethodDeclaration.class).stream().filter(it -> it.isPrivate()).forEach(it -> it.removeForced()); - cu.findAll(ConstructorDeclaration.class).stream().forEach(it->it.getBody().removeForced()); + cu.findAll(ConstructorDeclaration.class).stream().forEach(it -> it.getBody().removeForced()); cu.findAll(InitializerDeclaration.class, init -> init.isStatic()).forEach(it -> it.removeForced()); - cu.findAll(FieldDeclaration.class).stream().forEach(it->it.removeForced()); + cu.findAll(FieldDeclaration.class).stream().forEach(it -> it.removeForced()); System.out.println(cu.toString()); } @@ -63,8 +108,33 @@ public void testRemove() { @SneakyThrows @Test public void testParseField() { - String code = Files.readString(Paths.get("/tmp/AthenaClassInfo.java")); + String code = Files.readString(Paths.get("/your path/AthenaClassInfo.java")); List fieldList = AthenaCodeService.parseFieldCode(code); System.out.println(fieldList); } + + + @Test + public void test1() { + String line = "for(int i=0;i<3;i++) {}"; + System.out.println(CaretHoverPlugin.isCompleteStatement("for(int i=0;i<3;i++) {}")); + } + + + + + private boolean containsUnclosedStructures(String lineText) { + int openBraces = 0; + int closeBraces = 0; + for (char c : lineText.toCharArray()) { + if (c == '{') { + openBraces++; + } else if (c == '}') { + closeBraces++; + } + } + return openBraces > closeBraces; + } + + } diff --git a/athena-all/src/test/java/run/mone/ultraman/test/Base64Test.java b/athena-all/src/test/java/run/mone/ultraman/test/Base64Test.java index 991612847..76af18a41 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/Base64Test.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/Base64Test.java @@ -24,6 +24,7 @@ public class Base64Test { + @Test public void testa() throws InterruptedException { Instant begin = new Date().toInstant(); diff --git a/athena-all/src/test/java/run/mone/ultraman/test/BotTest.java b/athena-all/src/test/java/run/mone/ultraman/test/BotTest.java new file mode 100644 index 000000000..70a3e664d --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/BotTest.java @@ -0,0 +1,103 @@ +package run.mone.ultraman.test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonObject; +import lombok.SneakyThrows; +import okhttp3.*; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * @author goodjava@qq.com + * @date 2024/6/19 17:06 + */ +public class BotTest { + + @SneakyThrows + @Test + public void postBotQuery() throws IOException { + String url = ""; + + OkHttpClient client = new OkHttpClient(); + MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + + Map jsonMap = new HashMap<>(); + jsonMap.put("botId", "100336"); + jsonMap.put("userName", "zzy"); + jsonMap.put("input", ""); + jsonMap.put("params", ImmutableMap.of("input","hi")); + + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(jsonMap); + + RequestBody body = RequestBody.create(JSON, jsonString); + Request request = new Request.Builder() + .url(url) + .post(body) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } + System.out.println(response.body().string()); + } + } + + + @SneakyThrows + @Test + public void websocketBot() { + String url = ""; + + OkHttpClient client = new OkHttpClient(); + + JsonObject jsonReq = new JsonObject(); + jsonReq.addProperty("botId", ""); + jsonReq.addProperty("input", "hi"); + jsonReq.addProperty("topicId", UUID.randomUUID().toString()); + + Request request = new Request.Builder() + .url(url) + .header("athena-token", "") + .build(); + + WebSocketListener listener = new WebSocketListener() { + @Override + public void onOpen(WebSocket webSocket, Response response) { + System.out.println("WebSocket opened: " + response); + } + + @Override + public void onMessage(WebSocket webSocket, String text) { + System.out.println("Received message: " + text); + // 处理返回的信息 + } + + @Override + public void onClosing(WebSocket webSocket, int code, String reason) { + webSocket.close(1000, null); + System.out.println("WebSocket closing: " + code + " / " + reason); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + t.printStackTrace(); + } + }; + + WebSocket webSocket = client.newWebSocket(request, listener); + + webSocket.send(jsonReq.toString()); + + TimeUnit.SECONDS.sleep(40); + client.dispatcher().executorService().shutdown(); + } + +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/CommonUtilsTest.java b/athena-all/src/test/java/run/mone/ultraman/test/CommonUtilsTest.java index 31243cd4c..d59a3925b 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/CommonUtilsTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/CommonUtilsTest.java @@ -1,7 +1,6 @@ package run.mone.ultraman.test; import com.google.common.collect.Lists; -import run.mone.mone.ultraman.grpc.CommonUtils; import org.junit.Test; import java.util.Arrays; @@ -16,16 +15,6 @@ */ public class CommonUtilsTest { - @Test - public void testGetIntersection() { - CommonUtils commonUtils = new CommonUtils(); - List list1 = Arrays.asList("a", "b", "c", "d"); - List list2 = Arrays.asList("c", "d", "e", "f"); - List expected = Arrays.asList("c", "d"); - List actual = commonUtils.getIntersection(list1, list2); - assertEquals(expected, actual); - } - @Test public void testSubList() { diff --git a/athena-all/src/test/java/run/mone/ultraman/test/GsonTest.java b/athena-all/src/test/java/run/mone/ultraman/test/GsonTest.java index d13ac2298..69e9f6139 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/GsonTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/GsonTest.java @@ -18,7 +18,6 @@ public void test1() { System.out.println(jsonObject.get("a").getAsString()); } - //计算两数和1 diff --git a/athena-all/src/test/java/run/mone/ultraman/test/MarkdownFilterTest.java b/athena-all/src/test/java/run/mone/ultraman/test/MarkdownFilterTest.java new file mode 100644 index 000000000..09941a1e3 --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/MarkdownFilterTest.java @@ -0,0 +1,45 @@ +package run.mone.ultraman.test; + +import com.xiaomi.youpin.tesla.ip.util.MarkdownFilter; +import org.junit.Test; + +/** + * @author goodjava@qq.com + * @date 2024/1/31 11:30 + */ +public class MarkdownFilterTest { + + @Test + public void testFilter() { + MarkdownFilter filter = new MarkdownFilter(System.out::print); + + filter.accept("Here is some text "); + filter.accept("and here is a code block: ```"); + filter.accept("java"); + filter.accept("System.out.println(\"Hello, world!\");"); + filter.accept("``` and now we're back to text."); + } + + @Test + public void testFilter2() { + MarkdownFilter filter = new MarkdownFilter(System.out::print); + filter.accept(""); + filter.accept("```"); + filter.accept("go"); + filter.accept("public void p(){"); + filter.accept("System.out.println(\"Hello, world! ```\");"); + filter.accept("}"); + filter.accept("```"); + filter.accept("\nend"); + System.out.println(""); + } + + @Test + public void testFilter3() { + MarkdownFilter filter = new MarkdownFilter(System.out::print); + filter.accept("public void p(){"); + filter.accept("System.out.println(\"Hello, world! ```\");"); + filter.accept("}"); + System.out.println(""); + } +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/NetUtilsTest.java b/athena-all/src/test/java/run/mone/ultraman/test/NetUtilsTest.java new file mode 100644 index 000000000..ddfb57e8f --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/NetUtilsTest.java @@ -0,0 +1,19 @@ +package run.mone.ultraman.test; + +import com.xiaomi.youpin.tesla.ip.util.NetUtils; +import org.junit.Test; + +import java.net.InetAddress; + +/** + * @author HawickMason@xiaomi.com + * @date 6/25/24 2:40 PM + */ +public class NetUtilsTest { + + @Test + public void testGetLocalAddress() { + String localAddress = NetUtils.getLocalHost(); + System.out.println("local ip:" + localAddress); + } +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/ScriptServiceTest.java b/athena-all/src/test/java/run/mone/ultraman/test/ScriptServiceTest.java index 47dcbc044..b61b1e8df 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/ScriptServiceTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/ScriptServiceTest.java @@ -5,7 +5,7 @@ import com.google.common.collect.Maps; import com.google.common.io.Resources; import com.google.gson.Gson; -import run.mone.m78.ip.service.ScriptService; +import com.xiaomi.youpin.tesla.ip.service.ScriptService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; diff --git a/athena-all/src/test/java/run/mone/ultraman/test/StringUtilsTest.java b/athena-all/src/test/java/run/mone/ultraman/test/StringUtilsTest.java new file mode 100644 index 000000000..091cf455f --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/StringUtilsTest.java @@ -0,0 +1,53 @@ +package run.mone.ultraman.test; + +import com.xiaomi.youpin.tesla.ip.common.StringUtils; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author goodjava@qq.com + * @date 2024/6/14 10:49 + */ +public class StringUtilsTest { + + + @Test + public void test1() { + String str = StringUtils.extractEndingKeyword("abc(class)"); + System.out.println(str); + } + + @Test + public void testExtractEndingKeyword() { + // Test case 1: Input string contains "(class)" + String input1 = "abc(class)"; + String result1 = StringUtils.extractEndingKeyword(input1); + System.out.println(result1); + + // Test case 2: Input string contains "(method)" + String input2 = "xyz(method)"; + String result2 = StringUtils.extractEndingKeyword(input2); + System.out.println(result2); + + // Test case 3: Input string contains "(project)" + String input3 = "test(project)"; + String result3 = StringUtils.extractEndingKeyword(input3); + System.out.println(result3); + // Test case 5: Input string does not contain any matching pattern + String input5 = "noMatch"; + String result5 = StringUtils.extractEndingKeyword(input5); + System.out.println("result5:" + result5); + + // Test case 6: Input string is aaa(class)bb + String input6 = "aaa(class)bb"; + String result6 = StringUtils.extractEndingKeyword(input6); + System.out.println("result6:" + result6); + + // Test case 7: Input string is xx\module + String input7 = "xx\\module"; + String result7 = StringUtils.extractEndingKeyword(input7); + System.out.println("result7:" + result7); + } + +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/TemplateTest.java b/athena-all/src/test/java/run/mone/ultraman/test/TemplateTest.java index 3231a47e3..c842bd469 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/TemplateTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/TemplateTest.java @@ -1,8 +1,12 @@ package run.mone.ultraman.test; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import org.apache.commons.lang3.tuple.Pair; +import org.beetl.core.Context; +import org.beetl.core.Function; import org.junit.Test; import run.mone.ultraman.common.TemplateUtils; @@ -15,6 +19,19 @@ public class TemplateTest { + @Test + public void testCustomFunction() { + String result = TemplateUtils.renderTemplate("${greeting} ${customFunction('World')}", ImmutableMap.of("greeting", "Hello"), + Lists.newArrayList(Pair.of("customFunction", new Function() { + @Override + public Object call(Object[] paras, Context ctx) { + return "hahahaha:" + paras[0]; + } + }))); + System.out.println(result); + } + + @Test public void renderAndPrintTemplate() { String str = TemplateUtils.renderTemplate("${name} hi", ImmutableMap.of("name", "zzy")); @@ -40,15 +57,17 @@ public void printByteArrayAsString() { String v = (new String(data)); System.out.println(v); } - class A{ + + class A { public String x; public String y; } + @Test public void testOS() { System.out.println(System.getProperty("os.name")); - A a=new A(); - a.x="a"; + A a = new A(); + a.x = "a"; System.out.println(new Gson().toJson(a)); System.out.println(new GsonBuilder().serializeNulls().create().toJson(a)); } diff --git a/athena-all/src/test/java/run/mone/ultraman/test/VersionUtilTest.java b/athena-all/src/test/java/run/mone/ultraman/test/VersionUtilTest.java new file mode 100644 index 000000000..4815ab754 --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/VersionUtilTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Xiaomi + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 run.mone.ultraman.test; + +import com.xiaomi.youpin.tesla.ip.common.VersionUtil; +import org.junit.Test; + +/** + * @author shanwb + * @date 2024-06-18 + */ +public class VersionUtilTest { + @Test + public void testCompareVersions() { + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2024.06.18.1") == 0); + System.out.println(VersionUtil.compareVersions("2024.7.18.1", "2024.06.18.1") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.2", "2024.06.18.1") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2024.06.18.2") < 0); + System.out.println(VersionUtil.compareVersions("2024.06.19.1", "2024.06.18.1") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2024.06.19.1") < 0); + System.out.println(VersionUtil.compareVersions("2025.06.18.1", "2024.06.18.1") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2025.06.18.1") < 0); + System.out.println(VersionUtil.compareVersions("2024.07.18.1", "2024.06.18.1") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2024.07.18.1") < 0); + System.out.println(VersionUtil.compareVersions("2024.06.18.1", "2024.06.18") > 0); + System.out.println(VersionUtil.compareVersions("2024.06.18", "2024.06.18.1") < 0); + } + +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/WsClientTest.java b/athena-all/src/test/java/run/mone/ultraman/test/WsClientTest.java new file mode 100644 index 000000000..23acb9108 --- /dev/null +++ b/athena-all/src/test/java/run/mone/ultraman/test/WsClientTest.java @@ -0,0 +1,46 @@ +package run.mone.ultraman.test; + +import com.google.gson.JsonObject; +import lombok.SneakyThrows; +import org.junit.Test; +import run.mone.ultraman.http.WsClient; + +/** + * @author goodjava@qq.com + * @date 2024/5/30 13:38 + */ +public class WsClientTest { + + @SneakyThrows + @Test + public void test1() { + WsClient wc = new WsClient(); + wc.init(msg -> { + System.out.println(msg); + }); + wc.send(new JsonObject()); + System.in.read(); + } + + @SneakyThrows + public static void main(String[] args) { + WsClient wc = new WsClient(); + wc.init(msg->{ + System.out.println(msg); + }); + + JsonObject req = new JsonObject(); + + //req.addProperty("cmd","ping"); + + req.addProperty("botId", ""); + req.addProperty("input", "System.out.println(123);"); + req.addProperty("topicId", "123"); + + + wc.send(req); + + System.in.read(); + } + +} diff --git a/athena-all/src/test/java/run/mone/ultraman/test/XmlUtilsTest.java b/athena-all/src/test/java/run/mone/ultraman/test/XmlUtilsTest.java index 799c3146f..ddc3fc58f 100644 --- a/athena-all/src/test/java/run/mone/ultraman/test/XmlUtilsTest.java +++ b/athena-all/src/test/java/run/mone/ultraman/test/XmlUtilsTest.java @@ -1,6 +1,6 @@ package run.mone.ultraman.test; -import run.mone.m78.ip.util.XmlUtils; +import com.xiaomi.youpin.tesla.ip.util.XmlUtils; import org.junit.Test; import java.util.Map; @@ -13,12 +13,12 @@ public class XmlUtilsTest { @Test public void test1() { - XmlUtils.updateGeneratorConfig("/tmp/generatorConfig.xml","Abc"); + XmlUtils.updateGeneratorConfig("/your path/generatorConfig.xml","Abc"); } @Test public void test2() { - Map m = XmlUtils.getMysqlConfigFromMybatisConfig("/tmp/generatorConfig.xml"); + Map m = XmlUtils.getMysqlConfigFromMybatisConfig("/your path/generatorConfig.xml"); System.out.println(m); } } diff --git a/jcommon/codecheck/src/test/java/com/xiaomi/youpin/codecheck/test/CodeCheckTest.java b/jcommon/codecheck/src/test/java/com/xiaomi/youpin/codecheck/test/CodeCheckTest.java index bd2048db1..0388f5821 100644 --- a/jcommon/codecheck/src/test/java/com/xiaomi/youpin/codecheck/test/CodeCheckTest.java +++ b/jcommon/codecheck/src/test/java/com/xiaomi/youpin/codecheck/test/CodeCheckTest.java @@ -32,10 +32,18 @@ public class CodeCheckTest { @Test public void testCheckIP() { CodeCheck codeCheck = new CodeCheck(); - Map> map = codeCheck.check("/home/work/code/dubbo-demo/springboot-nacos-client-demo"); + Map> map = codeCheck.check("/home/work/mycode/ultraman"); map.entrySet().stream().forEach(it -> { System.out.println(it.getKey()); - it.getValue().stream().forEach(it1->System.out.println(it1)); + it.getValue().stream().forEach(it1->{ + String level = it1.getLevel(); + String name = it1.getName(); + if(!name.contains("idea-sandbox")) { + if (level.contains("ERROR")) { + System.out.println(it1); + } + } + }); System.out.println("\n"); }); } diff --git a/jcommon/codegen/pom.xml b/jcommon/codegen/pom.xml index a21ae573b..cfc3d4421 100644 --- a/jcommon/codegen/pom.xml +++ b/jcommon/codegen/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 run.mone @@ -61,5 +62,17 @@ + + org.mybatis.generator + mybatis-generator-core + 1.4.0 + + + mysql + mysql-connector-java + 8.0.26 + + + diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/CodeGenerator.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/CodeGenerator.java new file mode 100644 index 000000000..57483329f --- /dev/null +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/CodeGenerator.java @@ -0,0 +1,114 @@ +package run.mone.ai.codegen; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import run.mone.ai.codegen.util.TemplateUtils; + +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +public class CodeGenerator { + + private final static Gson gson = new Gson(); + + private static String className = "E"; + + private static String testName = "T"; + + private static String serviceName = "s"; + + private static String basePath = "/Users/wodiwudi/java/nr-car-account"; + + private static boolean createPojo = false; + + private static boolean createVo = false; + + private static boolean createTransfer = false; + + private static boolean createService = false; + + private static boolean createTest = true; + + private static boolean createController = false; + + /** + * 主方法 + * 判断输入参数长度是否大于 0,调用方法处理参数并提取数据 + * 如果类名字符串为空则返回 + * 创建数据映射,放入相关数据 + * 根据模板文件和数据渲染并写入到相应文件(pojo.java、vo.java 等) + */ + public static void main(String[] args) { + Map map = null; + //方便ai调用的时候,设置表名 + if (args.length > 0) { + map = parseArgsAndExtractData(args); + className = map.get("pojoName"); + testName = map.get("testName"); + serviceName = map.get("serviceName"); + } + if (StringUtils.isEmpty(className)) { + return; + } + Map data = new HashMap<>(); + data.put("className", className); + data.put("author", "goodjava@qq.com"); + data.put("serviceName", serviceName); + Optional first = Arrays.stream(testName.split("\\.")).findFirst(); + data.put("testName", first.get()); + // 调用方法并获取结果 + if (createPojo) { + String pojo = TemplateUtils.renderTemplateFromFile("tlp/pojo.java", data); + TemplateUtils.writeStringToFile(pojo, basePath + "/your project/src/main/java/run/mone/model/po/" + className + ".java"); + } + + if (createVo) { + String vo = TemplateUtils.renderTemplateFromFile("tlp/vo.java", data); + TemplateUtils.writeStringToFile(vo, basePath + "/your project/src/main/java/run/mone/api/vo/" + className + "VO.java"); + } + + if (createTransfer) { + String transfer = TemplateUtils.renderTemplateFromFile("tlp/transfer.java", data); + TemplateUtils.writeStringToFile(transfer, basePath + "/your project/src/main/java/run/mone/model/transfer/" + className + "Transfer.java"); + } + + if (createService) { + String service = TemplateUtils.renderTemplateFromFile("tlp/service.java", data); + TemplateUtils.writeStringToFile(service, basePath + "/your project/src/main/java/run/mone/service/" + className + "Service.java"); + } + + if (createTest) { + String cn = testName; + System.out.println("create test:" + cn); + String test = TemplateUtils.renderTemplateFromFile("tlp/test.java", data); + TemplateUtils.writeStringToFile(test, basePath + "/your project/src/test/java/com/xiaomi/nr/car/account/constant/" + cn); + + } + + if (createController) { + String controller = TemplateUtils.renderTemplateFromFile("tlp/controller.java", data); + TemplateUtils.writeStringToFile(controller, basePath + "/your project/src/main/java/run/mone/controller/" + className + "Controller.java"); + } + } + + + private static Map parseArgsAndExtractData(String[] args) { + String jsonStr = args[0]; + Type typeOfT = new TypeToken>() { + }.getType(); + + jsonStr = new String(Base64.getDecoder().decode(jsonStr)); + log.info("jsonStr:{}", jsonStr); + + Map map = gson.fromJson(jsonStr, typeOfT); + log.info("map:{}", map); + return map; + } +} diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/FeatureGenerator.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/FeatureGenerator.java index 38812927d..e9ae8222d 100644 --- a/jcommon/codegen/src/main/java/run/mone/ai/codegen/FeatureGenerator.java +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/FeatureGenerator.java @@ -37,6 +37,7 @@ public static void generateWithTemplate(FeatureGenerateBo featureGenerateBo) { //配置数据源 HikariDataSource dataSource = new HikariDataSource(); + dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setJdbcUrl(featureGenerateBo.getJdbcUrl()); dataSource.setUsername(featureGenerateBo.getUserName()); dataSource.setPassword(featureGenerateBo.getPassword()); diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/MybatisGenerator.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/MybatisGenerator.java new file mode 100644 index 000000000..fdc0b99a5 --- /dev/null +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/MybatisGenerator.java @@ -0,0 +1,129 @@ +package run.mone.ai.codegen; + +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.generator.api.MyBatisGenerator; +import org.mybatis.generator.config.CommentGeneratorConfiguration; +import org.mybatis.generator.config.Configuration; +import org.mybatis.generator.config.Context; +import org.mybatis.generator.config.JDBCConnectionConfiguration; +import org.mybatis.generator.config.JavaClientGeneratorConfiguration; +import org.mybatis.generator.config.JavaModelGeneratorConfiguration; +import org.mybatis.generator.config.ModelType; +import org.mybatis.generator.config.PluginConfiguration; +import org.mybatis.generator.config.SqlMapGeneratorConfiguration; +import org.mybatis.generator.config.TableConfiguration; +import org.mybatis.generator.internal.DefaultShellCallback; +import run.mone.ai.codegen.bo.FeatureGenerateBo; + +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Objects; + +@Slf4j +public class MybatisGenerator { + + private static final Gson gson = new Gson(); + + public static void main(String[] args) { + FeatureGenerateBo featureGenerateBo = null; + //方便ai调用的时候,设置表名 + if (args.length > 0) { + featureGenerateBo = parseArgsAndExtractData(args); + } + generateMyBatisFiles(featureGenerateBo); + } + + // 使用mybatis-generator生成指定表对应的XML、Mapper和Entity类 + public static void generateMyBatisFiles(FeatureGenerateBo featureGenerateBo) { + if (Objects.isNull(featureGenerateBo.getTableName())) { + log.warn("Table name is empty, cannot generate MyBatis files!"); + return; + } + // 配置MyBatis Generator + List warnings = new ArrayList<>(); + boolean overwrite = true; + Configuration config = new Configuration(); + + Context context = new Context(ModelType.FLAT); + context.setId("MyBatis3"); + context.setTargetRuntime("MyBatis3"); + + // 配置JDBC连接 + JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration(); + jdbcConnectionConfiguration.setDriverClass("com.mysql.cj.jdbc.Driver"); + jdbcConnectionConfiguration.setConnectionURL(featureGenerateBo.getJdbcUrl()); + jdbcConnectionConfiguration.setUserId(featureGenerateBo.getUserName()); + jdbcConnectionConfiguration.setPassword(featureGenerateBo.getPassword()); + context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration); + + // 配置Java模型生成器 + JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration(); + javaModelGeneratorConfiguration.setTargetPackage(featureGenerateBo.getMybatisDaoPath()); + javaModelGeneratorConfiguration.setTargetProject(featureGenerateBo.getMybatisDaoModule() + "/src/main/java"); + context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration); + + // 配置SQL映射生成器 + SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration(); + sqlMapGeneratorConfiguration.setTargetPackage(featureGenerateBo.getMybatisXMLPath()); + sqlMapGeneratorConfiguration.setTargetProject(featureGenerateBo.getMybatisDaoModule() + "/src/main/resources"); + context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration); + + // 配置Java客户端生成器 + JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration(); + javaClientGeneratorConfiguration.setTargetPackage(featureGenerateBo.getMybatisDaoPath()); + javaClientGeneratorConfiguration.setTargetProject(featureGenerateBo.getMybatisDaoModule() + "/src/main/java"); + javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER"); + context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration); + + // 配置表 + TableConfiguration tableConfiguration = new TableConfiguration(context); + tableConfiguration.setTableName(featureGenerateBo.getTableName()); + tableConfiguration.setCountByExampleStatementEnabled(false); + tableConfiguration.setDeleteByExampleStatementEnabled(false); + tableConfiguration.setSelectByExampleStatementEnabled(false); + tableConfiguration.setUpdateByExampleStatementEnabled(false); + context.addTableConfiguration(tableConfiguration); + + // 配置 Comment Generator + CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration(); + commentGeneratorConfiguration.addProperty("suppressAllComments", "true"); + context.setCommentGeneratorConfiguration(commentGeneratorConfiguration); + + // 配置自定义插件 + PluginConfiguration lombokConfiguration = new PluginConfiguration(); + lombokConfiguration.setConfigurationType("run.mone.ai.codegen.plugin.LombokPlugin"); + context.addPluginConfiguration(lombokConfiguration); + + PluginConfiguration removeGetSetMethodsPlugin = new PluginConfiguration(); + removeGetSetMethodsPlugin.setConfigurationType("run.mone.ai.codegen.plugin.RemoveGetSetMethodsPlugin"); + context.addPluginConfiguration(removeGetSetMethodsPlugin); + + config.addContext(context); + + DefaultShellCallback callback = new DefaultShellCallback(overwrite); + MyBatisGenerator myBatisGenerator; + try { + myBatisGenerator = new MyBatisGenerator(config, callback, warnings); + myBatisGenerator.generate(null); + } catch (Exception e) { + log.error("Error generating MyBatis files", e); + } + + if (!warnings.isEmpty()) { + warnings.forEach(log::warn); + } + } + + private static FeatureGenerateBo parseArgsAndExtractData(String[] args) { + String jsonStr = args[0]; + + jsonStr = new String(Base64.getDecoder().decode(jsonStr)); + log.info("jsonStr:{}", jsonStr); + + FeatureGenerateBo bo = gson.fromJson(jsonStr, FeatureGenerateBo.class); + log.info("map:{}", bo); + return bo; + } +} diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGeneratType.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGeneratType.java index 2773cc4e0..ba66ed583 100644 --- a/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGeneratType.java +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGeneratType.java @@ -15,7 +15,9 @@ public enum FeatureGeneratType { CODE_WITH_TEMPLATE(2, "使用预制模板生成"), - TABLE(3, "创建表"); + TABLE(3, "创建表"), + + CODE_WITH_MYBATIS_GENERATOR(4,"使用mybatis-generator生成"); private final int code; diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGenerateBo.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGenerateBo.java index cce56c8e3..e8c0fd450 100644 --- a/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGenerateBo.java +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/bo/FeatureGenerateBo.java @@ -4,6 +4,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.ToString; /** * @author goodjava@qq.com, HawickMason@xiaomi.com @@ -13,6 +14,7 @@ @AllArgsConstructor @Data @Builder +@ToString public class FeatureGenerateBo { @Builder.Default @@ -72,5 +74,17 @@ public class FeatureGenerateBo { @Builder.Default private boolean createController = false; - + + /** + * 目前使用module所在的绝对路径 + */ + @Builder.Default + private String mybatisDaoModule = ""; + @Builder.Default + private String mybatisXMLPath = ""; + @Builder.Default + private String mybatisDaoPath = ""; + @Builder.Default + private String mybatisEntityPath = ""; + } diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/LombokPlugin.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/LombokPlugin.java new file mode 100644 index 000000000..2458125d9 --- /dev/null +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/LombokPlugin.java @@ -0,0 +1,31 @@ +package run.mone.ai.codegen.plugin; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.TopLevelClass; + +import java.util.List; + +public class LombokPlugin extends PluginAdapter { + + @Override + public boolean validate(List warnings) { + // 该插件不需要任何配置,因此总是返回 true + return true; + } + + @Override + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + // 为生成的实体类添加 @Data 注解 + FullyQualifiedJavaType dataAnnotation = new FullyQualifiedJavaType("lombok.*"); + topLevelClass.addImportedType(dataAnnotation); + topLevelClass.addAnnotation("@Data"); + topLevelClass.addAnnotation("@ToString"); + topLevelClass.addAnnotation("@Builder"); + topLevelClass.addAnnotation("@AllArgsConstructor"); + topLevelClass.addAnnotation("@NoArgsConstructor"); + return true; + } +} + diff --git a/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/RemoveGetSetMethodsPlugin.java b/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/RemoveGetSetMethodsPlugin.java new file mode 100644 index 000000000..71929604b --- /dev/null +++ b/jcommon/codegen/src/main/java/run/mone/ai/codegen/plugin/RemoveGetSetMethodsPlugin.java @@ -0,0 +1,32 @@ +package run.mone.ai.codegen.plugin; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.TopLevelClass; + +import java.util.Iterator; +import java.util.List; + +public class RemoveGetSetMethodsPlugin extends PluginAdapter { + + @Override + public boolean validate(List warnings) { + // 该插件不需要任何配置,因此总是返回 true + return true; + } + + @Override + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + // 移除 get 和 set 方法 + Iterator methodIterator = topLevelClass.getMethods().iterator(); + while (methodIterator.hasNext()) { + Method method = methodIterator.next(); + if (method.getName().startsWith("get") || method.getName().startsWith("set")) { + methodIterator.remove(); + } + } + return true; + } +} + diff --git a/jcommon/codegen/src/test/java/com/xiaomi/youpin/codegen/test/FeatureGeneratorTest.java b/jcommon/codegen/src/test/java/com/xiaomi/youpin/codegen/test/FeatureGeneratorTest.java new file mode 100644 index 000000000..6acd2ef75 --- /dev/null +++ b/jcommon/codegen/src/test/java/com/xiaomi/youpin/codegen/test/FeatureGeneratorTest.java @@ -0,0 +1,49 @@ +package com.xiaomi.youpin.codegen.test; + +import org.junit.Test; +import run.mone.ai.codegen.FeatureGenerator; +import run.mone.ai.codegen.MybatisGenerator; +import run.mone.ai.codegen.bo.FeatureGeneratType; +import run.mone.ai.codegen.bo.FeatureGenerateBo; + +public class FeatureGeneratorTest { + + private String dbUrl = ""; + private String dbUser = ""; + private String dbPwd = ""; + + @Test + public void testCreateTable() { + FeatureGenerateBo featureGenerateBo = new FeatureGenerateBo(); + featureGenerateBo.setType(FeatureGeneratType.TABLE); + featureGenerateBo.setJdbcUrl(dbUrl); + featureGenerateBo.setUserName(dbUser); + featureGenerateBo.setPassword(dbPwd); + String sql = "CREATE TABLE IF NOT EXISTS `user` (\n" + + " `id` INT NOT NULL AUTO_INCREMENT,\n" + + " `name` VARCHAR(255) NOT NULL,\n" + + " `age` INT,\n" + + " PRIMARY KEY (`id`)\n" + + ");"; + featureGenerateBo.setSql(sql); + FeatureGenerator.generateWithTemplate(featureGenerateBo); + } + + @Test + public void testGenerateWithMybatis() { + FeatureGenerateBo featureGenerateBo = new FeatureGenerateBo(); + featureGenerateBo.setType(FeatureGeneratType.CODE_WITH_MYBATIS_GENERATOR); + featureGenerateBo.setJdbcUrl(dbUrl); + featureGenerateBo.setUserName(dbUser); + featureGenerateBo.setPassword(dbPwd); + featureGenerateBo.setTableName("user"); + + featureGenerateBo.setMybatisDaoModule("/your/path/mone/jcommon/codegen"); + featureGenerateBo.setMybatisXMLPath("com.xiaomi.dao.mapper"); + featureGenerateBo.setMybatisDaoPath("com.xiaomi.dao.mapper"); + featureGenerateBo.setMybatisEntityPath("com.xiaomi.dao.entity"); + + MybatisGenerator.generateMyBatisFiles(featureGenerateBo); + } + +}