Files

373 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# jdtls (Java Language Server) 使用指南
> 通过 Serena MCP 工具调用 jdtls 进行 Java 代码分析
## 前置条件
### 1. 确保 jdtls 已安装
jdtls 通常通过 VS Code 的 Java 扩展自动安装,或者手动安装:
```bash
# 检查 jdtls 路径
which jdtls
# 或
ls ~/.vscode/extensions/redhat.java-*/server/
```
### 2. 项目结构要求
jdtls 需要以下文件来识别 Java 项目:
- Maven: `pom.xml`
- Gradle: `build.gradle` 或 `build.gradle.kts`
- Eclipse: `.project` 和 `.classpath`
---
## 通过 Serena 使用 jdtls
### 激活项目
```yaml
# Step 1: 激活 Java 项目
tool: mcp__serena__activate_project
params:
project: "/path/to/java/project"
# 返回: 项目已激活,jdtls 已初始化
```
### 验证配置
```yaml
# 检查当前配置
tool: mcp__serena__get_current_config
# 确认输出包含:
# - active_project: /path/to/java/project
# - language_server: jdtls
```
---
## 符号提取操作
### 获取文件符号概览
```yaml
# 获取单个文件的符号列表(不含代码体)
tool: mcp__serena__get_symbols_overview
params:
relative_path: "src/main/java/com/example/OrderController.java"
depth: 1 # 0=仅顶层, 1=含直接成员, 2=含嵌套成员
# 返回示例:
# Classes:
# - OrderController (class) [59-1241]
# Methods:
# - getOrderList (method) [120-145]
# - createOrder (method) [150-180]
# - updateOrder (method) [185-210]
```
### 查找符号
```yaml
# 按名称模式查找符号
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderController" # 可以是部分名称
relative_path: "src/main/java/" # 限定搜索范围
include_body: false # 是否包含代码体
include_info: true # 是否包含 hover 信息
depth: 1 # 包含成员的深度
# 名称模式规则:
# - "OrderController" -> 匹配任何包含此名称的符号
# - "controller/OrderController" -> 匹配此路径后缀
# - "/com.example.OrderController" -> 精确匹配完整路径
# - "OrderController/getOrderList" -> 匹配类中的方法
# - "OrderController[0]" -> 匹配重载方法的第一个
```
### 获取符号详情(含代码体)
```yaml
# 获取完整的符号定义(含代码)
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
include_body: true
depth: 0
# 返回包含:
# - 方法签名
# - Javadoc 注释
# - 完整方法体
# - 行号范围
```
---
## 引用分析操作
### 查找符号引用
```yaml
# 查找某个符号被哪些地方引用
tool: mcp__serena__find_referencing_symbols
params:
name_path: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
include_info: true
# 返回示例:
# References (5 found):
# - OrderController.createOrder [180:12-180:35]
# snippet: "orderService.saveOrder(dto)"
# - OrderController.updateOrder [210:12-210:35]
# snippet: "orderService.saveOrder(updated)"
# - OrderServiceTest.testSave [45:8-45:30]
# snippet: "service.saveOrder(testDto)"
```
### 模式搜索(补充 LSP)
```yaml
# 当 LSP 无法找到时,使用模式搜索
tool: mcp__serena__search_for_pattern
params:
substring_pattern: "orderService\\.save"
paths_include_glob: "**/*.java"
restrict_search_to_code_files: true
context_lines_before: 2
context_lines_after: 2
# 适用场景:
# - 动态调用 (反射)
# - 字符串拼接的方法名
# - 注解中的引用
```
---
## 调用链构建
### 构建向下调用链 (callee)
```python
# 伪代码: 递归构建调用链
def build_callee_chain(symbol_path, file_path, depth, max_depth):
if depth > max_depth:
return None
# Step 1: 获取方法体
symbol = find_symbol(
name_path_pattern=symbol_path,
relative_path=file_path,
include_body=True
)
# Step 2: 在方法体中查找调用
# 使用 LSP 或正则匹配
calls = extract_method_calls(symbol.body)
# Step 3: 对每个调用递归
callees = []
for call in calls:
# 尝试定位被调用方法
target = find_symbol(
name_path_pattern=call.method_name,
relative_path=call.potential_file
)
if target:
callees.append({
'symbol': target,
'evidence': call.location,
'children': build_callee_chain(
target.path, target.file, depth + 1, max_depth
)
})
return {
'symbol': symbol,
'callees': callees
}
```
### 实际操作步骤
```yaml
# 1. 获取入口方法
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderController/createOrder"
relative_path: "src/main/java/com/example/controller/"
include_body: true
depth: 0
# 2. 分析方法体中的调用
# 从返回的 body 中提取: orderService.saveOrder(dto)
# 3. 定位被调用方法
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderService/saveOrder"
relative_path: "src/main/java/"
include_body: true
# 4. 查找该方法的引用(验证调用关系)
tool: mcp__serena__find_referencing_symbols
params:
name_path: "OrderService/saveOrder"
relative_path: "src/main/java/com/example/service/OrderService.java"
# 5. 递归处理下一层
```
---
## Java 特有处理
### 注解识别
```yaml
# 常见注解及其语义含义
API 入口点注解:
- "@RestController": REST API 控制器
- "@Controller": MVC 控制器
- "@RequestMapping": 请求映射
- "@GetMapping": GET 请求
- "@PostMapping": POST 请求
- "@PutMapping": PUT 请求
- "@DeleteMapping": DELETE 请求
服务层注解:
- "@Service": 业务服务
- "@Component": 通用组件
- "@Transactional": 事务方法
数据层注解:
- "@Repository": 数据访问
- "@Mapper": MyBatis Mapper
- "@Table": JPA 表映射
- "@Entity": JPA 实体
数据对象注解:
- "@Data": Lombok 数据类
- "@Getter/@Setter": Lombok 访问器
- "@Builder": Lombok 构建器
```
### MyBatis Mapper 处理
```yaml
# MyBatis Mapper 接口无法通过 LSP 追踪到 SQL
# 需要关联 XML 文件
# 1. 找到 Mapper 接口
tool: mcp__serena__find_symbol
params:
name_path_pattern: "OrderMapper"
relative_path: "src/main/java/"
# 2. 查找对应的 XML
tool: mcp__serena__search_for_pattern
params:
substring_pattern: "OrderMapper"
paths_include_glob: "**/*.xml"
# 3. 读取 XML 获取 SQL 定义
tool: mcp__serena__list_dir
params:
relative_path: "src/main/resources/mapper/"
```
---
## LSP SymbolKind 映射
```yaml
# jdtls 返回的 SymbolKind 数值对照
1: File
2: Module
3: Namespace
4: Package
5: Class # 类
6: Method # 方法
7: Property
8: Field # 字段
9: Constructor # 构造函数
10: Enum # 枚举
11: Interface # 接口
12: Function # 函数
13: Variable # 变量
14: Constant # 常量
15: String
16: Number
17: Boolean
18: Array
19: Object
20: Key
21: Null
22: EnumMember # 枚举值
23: Struct
24: Event
25: Operator
26: TypeParameter # 泛型参数
```
---
## 常见问题
### Q: jdtls 启动慢
```
A: 首次打开项目时,jdtls 需要构建索引。
- Maven 项目: 会下载依赖
- 大项目: 索引可能需要几分钟
建议: 等待 Serena 报告项目就绪
```
### Q: 找不到符号
```
A: 可能原因:
1. 项目未正确识别 (缺少 pom.xml 或 build.gradle)
2. 编译错误导致索引不完整
3. 符号在排除目录中
解决:
1. 确保项目根目录正确
2. 先执行 mvn compile 或 gradle build
3. 使用 search_for_pattern 作为备选
```
### Q: 引用结果不完整
```
A: jdtls 的 references 可能遗漏:
1. 反射调用
2. 字符串拼接的方法名
3. 动态代理
解决:
使用 search_for_pattern 补充搜索
```
---
## 最佳实践
1. **先概览后详细** - 用 `get_symbols_overview` 了解文件结构,再用 `find_symbol` 获取详情
2. **限定搜索范围** - 总是传入 `relative_path` 以提高效率
3. **分批处理** - 大项目分模块处理,避免一次性加载全部
4. **缓存结果** - 符号信息变化不频繁,可以缓存复用
5. **结合搜索** - LSP 不足时用 `search_for_pattern` 补充