AI编程可视化Java项目拆解第一弹,解析本地Java项目
之前分享过一篇使用 AI 可视化 Java 项目的文章,同步在 AI 破局星球、知乎、掘金等地方都分享了。
原文在这里AI 编程:可视化 Java 项目
有很多人感兴趣,我打算写一个系列文章拆解这个项目,大家多多点赞支持~
今天分享的是第一篇:如何使用 Spoon + JavaParser 工具解析一个本地的 Java 项目。
解析这一步骤是整个项目的基础,是为了获得整个 Java 项目的元数据。
这个元数据包含什么呢?1)整个项目的所有的类信息;2)整个项目的所有方法信息
方法信息
| 序号 | 字段名称 | 字段描述 |
|---|---|---|
| 1 | method_id | 方法唯一id标识 |
| 2 | project_name | |
| 3 | method_name | 方法名 |
| 4 | class_id | 方法所属类名 |
| 5 | param_type | 参数类型 |
| 6 | response_type | 返回类型 |
| 7 | begin_line | 方法内容开始行 |
| 8 | end_line | 方法内容结束行 |
| 9 | branch | 分支 |
| 10 | method_desc | 方法描述 |
| 11 | chat_desc | GPT 描述 |
| 12 | invoke_count | 被调用数量 |
| 13 | mermaid_flow_graph | 流程图数据 |
| 14 | flow_graph_ignored | 是否忽略流程图 |
| 15 | annotation_info | 注解信息 |
| 16 | annotation_type | 注解类型 |
| 17 | access_modifier | 修饰符 |
类信息
| 序号 | 字段名称 | 字段描述 |
|---|---|---|
| 1 | class_id | 类唯一标识 |
| 2 | class_name | 类名 |
| 3 | project_name | 项目唯一标识 |
| 4 | package_name | 包名 |
| 5 | branch | 分支 |
| 6 | class_type | 类的类型 |
| 7 | chat_desc | GPT 类描述 |
| 8 | class_desc | 类注释 |
| 9 | annotation_info | 类注解 |
| 10 | method_annotation_info | 方法注解信息 |
| 11 | annotation_type | 注解类型 |
怎么拿到整个项目的类信息和方法信息呢?
首先我们需要一个类解析器、一个方法解析器。使用 Java 的反射,我们就能拿到具体类和方法的详细信息。
类解析器代码:
public void execute(List<CtType<?>> elements) {classStructs = Lists.newArrayList();for (CtType<?> type : elements) {try {// 匿名内部类和泛型会跳过解析if (type.isAnonymous()) {continue;}if (Objects.isNull(type.getPackage())) {continue;}// 获取类的简单类名String simpleClassName = type.getSimpleName();// GPT 接口获取解释String chatDesc = "";// 获取类所属包String packageName = type.getPackage().getQualifiedName();// 获取类注释信息String classComment = type.getDocComment();// 判断接口还是类ClassType classType = getClassType(type);// 获取类注解信息List<AnnotationInfo> annotationInfos = Lists.newArrayList();List<CtAnnotation<?>> annotations = type.getAnnotations();for (CtAnnotation<?> annotation : annotations) {AnnotationInfo annotationInfo = new AnnotationInfo();String annotationName = annotation.getAnnotationType().getSimpleName();annotationInfo.setAnnotationName(annotationName);Map<String, CtExpression> annotationValues = annotation.getValues();for (Map.Entry<String, CtExpression> entry : annotationValues.entrySet()) {String attributeName = entry.getKey();Object attributeValue = entry.getValue();annotationInfo.addAttributeName(attributeName, attributeValue.toString());}annotationInfos.add(annotationInfo);}// 构造类元信息ClassStruct classStruct = buildClassStruct(simpleClassName, packageName, classType,classComment, annotationInfos, chatDesc);classStructs.add(classStruct);} catch (Exception e) {log.error("class parse error, className ==>{}, errMsg ==>", type.getSimpleName(), e);}}// 类元信息入库}
方法解析器
public void execute(List<CtType<?>> elements) {methodStructs = Lists.newArrayList();for (CtType<?> element : elements) {if (element.isAnonymous()) {continue;}if (Objects.isNull(element.getPackage())) {continue;}// 获取包名String packageName = element.getPackage().getQualifiedName();// 获取类名String className = element.getSimpleName();// 获取方法列表Set<CtMethod<?>> methods = element.getMethods();for (CtMethod<?> method : methods) {try {// 获取简单方法名String methodName = method.getSimpleName();// 获取全限定参数String signatureParameters = method.getSignature();int firstIndex = method.getSignature().indexOf("(");int lastIndex = method.getSignature().indexOf(")");String parameters = signatureParameters.substring(firstIndex + 1, lastIndex);List<String> methodParameters = Splitter.on(",").omitEmptyStrings().splitToList(parameters);// 获取响应体类型String responseType = method.getType().getQualifiedName();// 获取方法开始的行int startLine = method.getPosition().getLine();// 获取方法结束的行int endLine = method.getPosition().getEndLine();// 获取方法注释String methodComment = method.getDocComment();// 获取方法包含的注解信息List<AnnotationInfo> annotationInfos = Lists.newArrayList();List<CtAnnotation<?>> annotations = method.getAnnotations();for (CtAnnotation<?> annotation : annotations) {AnnotationInfo annotationInfo = new AnnotationInfo();String annotationName = annotation.getAnnotationType().getSimpleName();annotationInfo.setAnnotationName(annotationName);Map<String, CtExpression> annotationValues = annotation.getValues();for (Map.Entry<String, CtExpression> entry : annotationValues.entrySet()) {String attributeName = entry.getKey();Object attributeValue = entry.getValue();annotationInfo.addAttributeName(attributeName, attributeValue.toString());}annotationInfos.add(annotationInfo);}// 获取方法的访问修饰符String accessModifier = "";if (Objects.isNull(method.getVisibility())) {accessModifier = "default";} else {accessModifier = method.getVisibility().toString();}String methodId = generateIdentityUtil.generateMethodId(MethodSignature.builder().packagePath(packageName).className(className).methodName(methodName).parameterTypeString(methodParameters).build(), endLine - startLine + 1);MethodStruct old = null;// 基于规则判断一波是否需要询问chatint lineCount = endLine - startLine;MethodStruct methodStruct = MethodStruct.builder().appCode(GlobalVariableUtil.getAppCodeName()).methodId(methodId).methodName(methodName).classId(generateIdentityUtil.generateClassId(className, packageName, GlobalVariableUtil.getAppCodeName())).paramTypes(methodParameters).responseType(responseType).beginLine(startLine).endLine(endLine).branch(GlobalVariableUtil.getBranch()).methodDesc(methodComment).annotationInfos(annotationInfos).accessModifier(accessModifier).invokeCount(old == null ? 0 : old.getInvokeCount()).mermaidFlowGraph(old == null ? "" : old.getMermaidFlowGraph()).build();if (old == null) {methodStructs.add(methodStruct);}} catch (Exception e) {log.error("method parse error, className ==>{}, methodName ==>{}, errMsg ==>",className, method.getSimpleName(), e);}}}
// 方法元信息入库}
通过这种方式,我们就能拿到整个 Java 项目的方法信息。
需要注意的是,我们这个时候还没有使用 AI 技术,所以这个元信息中部分字段是空的。
我们看到类解析器和方法解析器方法的入参都是 List<CtType<?>> elements。
那么,这个信息从哪里来的呢?
我这里使用的是 Spoon 工具。
Spoon 是什么?
Spoon 框架常被用于解析和处理 Java 源代码。Spoon 是一个强大的源码分析与转换工具,它通过构建抽象语法树(Abstract Syntax Tree, AST)来表示 Java 源代码,并提供了一套丰富的 API 供开发者操作 AST。
Spoon 能够完整且准确地捕获源代码的所有细节,所以它非常适合于进行复杂的静态代码分析、重构、自动插入代码逻辑等工作。
Spoon 不会用?没关系,AI 可以帮你写代码。

我们可以看到,GPT 直接帮我们生成完整代码,我们只需要在对应的地方,替换成我们的类解析器和方法解析器即可。
提示词如下:
你是一个Java技术专家。
我需要解析本地的一个 Java 项目,获得这个项目中的类信息和方法信息。我会给你提供这个 Java 项目的绝对路径。
请你使用 Spoon 生成解析代码
写到这里,我要告诉你的是,其实类解析器和方法解析的代码,也可以交给 AI 来完成哟~ 你可以试试看,如果有问题,随时找阿七给你解答。
到这里,我们今天的内容就结束啦。
下一篇,我们分享使用 AI 生成方法的流程图,请期待~
相关文章:
AI编程可视化Java项目拆解第一弹,解析本地Java项目
之前分享过一篇使用 AI 可视化 Java 项目的文章,同步在 AI 破局星球、知乎、掘金等地方都分享了。 原文在这里AI 编程:可视化 Java 项目 有很多人感兴趣,我打算写一个系列文章拆解这个项目,大家多多点赞支持~ 今天分享的是第一…...
使用arcgis pro是类似的控件样式 WPF
1.资源加载 <controls:ProWindow.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><extensions:DesignOnlyResourceDictionary Source"pack://application:,,,/ArcGIS.Desktop.Framework;component\Themes\Default.xaml&quo…...
C语言所有字符串函数举例如何使用
strcpy: 将一个字符串复制到另一个字符串中 char source[] "Hello"; char destination[10]; strcpy(destination, source);strcat: 将一个字符串连接到另一个字符串的末尾 char str1[20] "Hello"; char str2[] "World"; strcat(str1, str2)…...
ArcGIS Pro 如何新建布局
你是否已经习惯了在ArcGIS中数据视图和布局视图之间来回切换,到了ArcGIS Pro中却找不到二者之间切换的按钮,即使新建布局后却发现地图怎么却是一片空白。 这一切的一切都是因为ArcGIS Pro的功能框架完全不同,这里为大家介绍一下在ArcGIS Pro…...
如何解决态势感知中的“时隐时现”问题
解决态势感知中的“时隐时现”问题有以下几个方法: 1、确保所有关键的监控设备和传感器正常运行,能够及时和准确地检测到各种异常情况。 2、引入先进的技术手段。例如使用人工智能和机器学习算法来识别和分析大量的数据,快速发现异常和威胁&a…...
为什么JavaScript中0.1 + 0.2 ≠ 0.3
JavaScript中的浮点数运算有时候会出现一点偏差。下面解释为什么0.1 0.2 ≠ 0.3,以及如果你需要精确运算应该怎么做。 如果1 2 3,那么为什么在JavaScript中0.1 0.2 ≠ 0.3?这个原因与计算机科学和浮点数运算有关。 我建议你打开浏览器的控制台,输入0.1 0.2来查看结果。…...
Unity关于纹理图片格式带来的内存问题和对预制体批量格式和大小减半处理
我们经常会遇到内存问题,这次就是遇到很多图片的默认格式被改成了RGB32,导致Android打包后运行内存明显增加。 发生了什么 打包Android后,发现经常崩溃,明显内存可能除了问题,看了内存后发现了问题。 见下图…...
2024美赛数学建模思路 - 案例:ID3-决策树分类算法
文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法,就是频繁模…...
GitHub图床搭建
1 准备Github账号 如果没有Github账号需要先在官网注册一个账号 2 创建仓库 在github上创建一个仓库,随便一个普通的仓库就行,选择公共仓库 并且配置github仓库的pages,选择默认访问的分支及默认路径 3 github token获取 github token创…...
DQN、Double DQN、Dueling DQN、Per DQN、NoisyDQN 学习笔记
文章目录 DQN (Deep Q-Network)说明伪代码应用范围 Double DQN说明伪代码应用范围 Dueling DQN实现原理应用范围伪代码 Per DQN (Prioritized Experience Replay DQN)应用范围伪代码 NoisyDQN伪代码应用范围 部分内容与图片摘自:JoyRL 、 EasyRL DQN (Deep Q-Networ…...
C++ 编程需要什么样的开发环境?
C 编程需要什么样的开发环境? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!&#…...
Unity文字游戏开发日志(1)—— 打字机效果
作者是一名OIer,因为兴趣,想在寒假期间开发一款文字游戏的demo。 本博客仅用作记录,马蜂极度不符合规范。 但是,可以用来避坑。 1.等待功能——使用的是协程函数,且调用与常规调用函数不同。 private IEnumerator Sco(){isScoe…...
从0开始python学习-48.pytest框架之断言
目录 1. 响应进行断言 1.1 在yaml用例中写入断言内容 1.2 封装断言方法 1.3 在执行流程中加入断言判断内容 2. 数据库数据断言 2.1 在yaml用例中写入断言内容 2.2 连接数据库并封装执行sql的方法 2.3 封装后校验方法是否可执行 2.4 使用之前封装的断言方法,…...
学习JavaEE的日子 day13补 深入类加载机制及底层
深入类加载机制 初识类加载过程 使用某个类时,如果该类的class文件没有加载到内存时,则系统会通过以下三个步骤来对该类进行初始化 1.类的加载(Load) → 2.类的连接(Link) → 3.类的初始化(In…...
C# WebApi传参及Postman调试
概述 欢迎来到本文,本篇文章将会探讨C# WebApi中传递参数的方法。在WebApi中,参数传递是一个非常重要的概念,因为它使得我们能够从客户端获取数据,并将数据传递到服务器端进行处理。WebApi是一种使用HTTP协议进行通信的RESTful服…...
npm install 卡住不动的六种解决方法
1.重装 检查网络设置,删除node_modules重新npm install 2. 配置npm代理 // 配置nmp代理来提高速度,如设置淘宝镜像 npm config set registry https://registry.npm.taobao.org// 查看配置是否成功 npm config get registry// 成功后重新npm install安…...
Vue高级(二)
3.搭建vuex环境 创建文件:src/store/index.js //引入Vue核心库import Vue from vue//引入Vueximport Vuex from vuex//应用Vuex插件Vue.use(Vuex)//准备actions对象——响应组件中用户的动作const actions {}//准备mutations对象——修改state中的数据const mutat…...
MongoDB面试系列-02
1. MongoDB 中必须调用 getLastError 来确保写操作生效吗? MongoDB中不管有没有调用getLastError(又称为Safe Mode),服务器执行的操作都会一样。 而调用getLastError只是为了确认写操作是否成功提交,但是写操作的安全…...
2024.1.17
今天我已经回家了,感觉家就像我的温柔乡一样,一到了家,就不想学习了,这是很不对的事情,不该如此堕落,还是要像在学校一样该干什么干什么,所以说还是复习和写了一下曾经写过的代码。 #define _C…...
openssl3.2 - 官方demo学习 - encrypt - rsa_encrypt.c
文章目录 openssl3.2 - 官方demo学习 - encrypt - rsa_encrypt.c概述笔记END openssl3.2 - 官方demo学习 - encrypt - rsa_encrypt.c 概述 从内存中的DER共钥数据构造pub_key, 用公钥加密明文, 输出密文. 非对称加密 从内存中的DER私钥数据构造priv_key, 用私钥解密密文, 输出…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
