OpenRewrite:如何用JavaTemplate将单条语句替换为多条语句?
解决OpenRewrite替换单条语句为多条语句的问题
问题根源
直接用oldMockStatement.getCoordinates().replace()替换单条语句为多条时,若未正确配置JavaTemplate,OpenRewrite会将模板内容当作单个语法节点处理,导致多条语句解析失败,出现类似Templategiven(...)的语法错误,同时触发"替换单条语句为多条无效"的报错。
正确实现方法
核心是让JavaTemplate明确识别模板内容为多条语句序列,并使用正确的坐标进行替换。
方法1:单模板直接替换(推荐)
通过statements(true)声明模板为多条语句,同时清理模板格式避免多余缩进:
// 定义多条语句模板,用trimIndent()移除多余缩进 String NEW_MOCK_STATEMENTS = """ given(methodToMock1).willReturn(expectedResponse1); given(methodToMock2).willReturn(expectedResponse2); """.trimIndent(); // 构建模板时明确指定为语句序列 JavaTemplate javaTemplate = JavaTemplate.builder(NEW_MOCK_STATEMENTS) .statements(true) // 关键:告知模板这是多条语句 .build(); // 替换原单条语句为多条新语句 methodDeclarationWhereApplyingChanges = methodDeclarationWhereApplyingChanges.withBody( javaTemplate.apply( getCursor(), // 直接使用当前cursor,无需新建 oldMockStatement.getCoordinates().replace() ) );
方法2:分步替换(兼容复杂场景)
如果单模板替换仍有问题,可拆分为"替换原语句为第一条新语句" + "插入第二条新语句"两步:
// 第一步:替换原语句为第一条新mock语句 JavaTemplate firstMockTemplate = JavaTemplate.builder("given(methodToMock1).willReturn(expectedResponse1);").build(); methodDeclarationWhereApplyingChanges = firstMockTemplate.apply( getCursor(), oldMockStatement.getCoordinates().replace() ); // 第二步:在第一条新语句后插入第二条mock语句 // 先获取刚插入的第一条语句(可通过语法树查询定位) Statement firstNewMock = methodDeclarationWhereApplyingChanges.getBody().getStatements() .stream() .filter(s -> s instanceof ExpressionStmt) .map(s -> (ExpressionStmt) s) .filter(e -> e.getExpression().toString().startsWith("given(methodToMock1)")) .findFirst() .orElseThrow(() -> new IllegalArgumentException("First mock statement not found")); JavaTemplate secondMockTemplate = JavaTemplate.builder("given(methodToMock2).willReturn(expectedResponse2);").build(); methodDeclarationWhereApplyingChanges = secondMockTemplate.apply( getCursor(), firstNewMock.getCoordinates().insertAfter() );
关键注意事项
- 模板内容必须是合法的Java语句,每条语句结尾要有分号。
- 使用
trimIndent()清理模板的多余缩进,避免生成格式混乱的代码。 - 当替换单条语句为多条时,必须通过
statements(true)声明模板类型,否则OpenRewrite会将整个模板内容当作单个表达式解析,导致语法错误。
内容的提问来源于stack exchange,提问作者Sergio García
相关产品推荐
相关产品推荐

