From f9fd034692c5121ea36de006638274fad0a05a92 Mon Sep 17 00:00:00 2001 From: Kun Li <122563761+kunli2@users.noreply.github.com> Date: Thu, 1 Jun 2023 13:09:36 -0700 Subject: [PATCH] Update JavaTemplate for rewrite8.0 (#366) * Update javaTemplate * revert some change * fix ConditionalOnBeanAnyNestedCondition * fix OutputCaptureExtension * fix AutowiredFieldIntoConstructorParameterVisitor * fix MigrateMvcConfigureAdapter * fixed indentation * revert to fix UpgradeExplicitSpringBootDependencies * fix AddSetUseTrailingSlashMatch * removed comment * fix ReplaceSupportClassWithItsInterface * changed new Cursor to updateCursor * TODO: disabled tests temporally until dependency updated * Fix failing `WebSecurityConfigurerAdapterTest` * fix UpdateRequestCache --------- Co-authored-by: joanvr Co-authored-by: Knut Wannheden --- ...dFieldIntoConstructorParameterVisitor.java | 38 +++++++++--- .../java/spring/DeleteSpringProperty.java | 8 +-- .../amqp/UseTlsAmqpConnectionString.java | 22 ++++--- .../spring/batch/MigrateItemWriterWrite.java | 23 +++---- .../batch/MigrateJobBuilderFactory.java | 23 +++---- .../ReplaceSupportClassWithItsInterface.java | 20 ++++--- ...ConfigurationAnnotationIfBeansPresent.java | 15 ++--- .../ConditionalOnBeanAnyNestedCondition.java | 24 +++++--- ...omponentAndBeanInitializationOrdering.java | 30 ++++++---- .../java/spring/boot2/GetErrorAttributes.java | 32 +++++----- .../MigrateActuatorMediaTypeToApiVersion.java | 13 ++-- ...teDiskSpaceHealthIndicatorConstructor.java | 11 ++-- .../MigrateLocalServerPortAnnotation.java | 40 ++++++------- .../boot2/MigrateMultipartConfigFactory.java | 19 +++--- ...igrateRestTemplateBuilderTimeoutByInt.java | 14 ++--- .../MoveAutoConfigurationToImportsFile.java | 6 +- .../spring/boot2/OutputCaptureExtension.java | 15 +++-- ...ReplaceDeprecatedEnvironmentTestUtils.java | 13 ++-- ...laceExtendWithAndContextConfiguration.java | 13 ++-- .../RestTemplateBuilderRequestFactory.java | 4 +- .../boot3/AddSetUseTrailingSlashMatch.java | 41 +++++-------- .../ConfigurationOverEnableSecurity.java | 15 +++-- .../java/spring/data/MigrateJpaSort.java | 19 +++--- .../data/MigrateQuerydslJpaRepository.java | 22 ++++--- .../data/UseTlsJdbcConnectionString.java | 16 +++-- .../framework/EnvironmentAcceptsProfiles.java | 13 ++-- ...ntiationAwareBeanPostProcessorAdapter.java | 22 +++---- .../MigrateWebMvcConfigurerAdapter.java | 17 +++--- ...lobalMethodSecurityWithMethodSecurity.java | 16 ++--- .../UpdateArgon2PasswordEncoder.java | 7 ++- .../UpdatePbkdf2PasswordEncoder.java | 18 +++--- .../UpdateSCryptPasswordEncoder.java | 6 +- .../security5/UseNewSecurityMatchers.java | 4 +- .../WebSecurityConfigurerAdapter.java | 60 ++++++++++++------- .../spring/security6/UpdateRequestCache.java | 31 +++++----- ...UpgradeExplicitSpringBootDependencies.java | 2 + .../SpringBoot2JUnit4to5MigrationTest.java | 3 + 37 files changed, 380 insertions(+), 315 deletions(-) diff --git a/src/main/java/org/openrewrite/java/spring/AutowiredFieldIntoConstructorParameterVisitor.java b/src/main/java/org/openrewrite/java/spring/AutowiredFieldIntoConstructorParameterVisitor.java index 35d4ae656..21519b306 100644 --- a/src/main/java/org/openrewrite/java/spring/AutowiredFieldIntoConstructorParameterVisitor.java +++ b/src/main/java/org/openrewrite/java/spring/AutowiredFieldIntoConstructorParameterVisitor.java @@ -165,15 +165,27 @@ public J visitBlock(Block block, ExecutionContext p) { + classDecl.getSimpleName() + "(" + typeFqn.getClassName() + " " + fieldName + ") {\n" + "this." + fieldName + " = " + fieldName + ";\n" + "}\n" - ).context(getCursor()); + ).contextSensitive(); FullyQualified fq = TypeUtils.asFullyQualified(type.getType()); if (fq != null) { template.imports(fq.getFullyQualifiedName()); maybeAddImport(fq); } Optional firstMethod = block.getStatements().stream().filter(MethodDeclaration.class::isInstance).findFirst(); - return firstMethod.map(statement -> (J) block.withTemplate(template.build(), getCursor(), statement.getCoordinates().before())) - .orElseGet(() -> block.withTemplate(template.build(), getCursor(), block.getCoordinates().lastStatement())); + + return firstMethod.map(statement -> + (J) template.build() + .apply(getCursor(), + statement.getCoordinates().before() + ) + ) + .orElseGet(() -> + template.build() + .apply( + getCursor(), + block.getCoordinates().lastStatement() + ) + ); } } } @@ -205,12 +217,24 @@ public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, Execut String paramsStr = Stream.concat(params.stream() .map(s -> "#{}"), Stream.of(methodType + " " + fieldName)).collect(Collectors.joining(", ")); - JavaTemplate.Builder paramsTemplate = JavaTemplate.builder(paramsStr).context(getCursor()); - md = md.withTemplate(paramsTemplate.build(), getCursor(), md.getCoordinates().replaceParameters(), params.toArray()); + md = JavaTemplate.builder(paramsStr) + .contextSensitive() + .build() + .apply( + getCursor(), + md.getCoordinates().replaceParameters(), + params.toArray() + ); + updateCursor(md); - JavaTemplate.Builder statementTemplate = JavaTemplate.builder("this." + fieldName + " = " + fieldName + ";").context(getCursor()); //noinspection ConstantConditions - md = md.withTemplate(statementTemplate.build(), getCursor(), md.getBody().getCoordinates().lastStatement()); + md = JavaTemplate.builder("this." + fieldName + " = " + fieldName + ";") + .contextSensitive() + .build() + .apply( + getCursor(), + md.getBody().getCoordinates().lastStatement() + ); } return md; } diff --git a/src/main/java/org/openrewrite/java/spring/DeleteSpringProperty.java b/src/main/java/org/openrewrite/java/spring/DeleteSpringProperty.java index f02daa4eb..6bc1bfdfb 100644 --- a/src/main/java/org/openrewrite/java/spring/DeleteSpringProperty.java +++ b/src/main/java/org/openrewrite/java/spring/DeleteSpringProperty.java @@ -32,8 +32,8 @@ public class DeleteSpringProperty extends Recipe { @Option(displayName = "Property key", - description = "The property key to delete. Supports glob expressions", - example = "management.endpoint.configprops.*") + description = "The property key to delete. Supports glob expressions", + example = "management.endpoint.configprops.*") String propertyKey; @Override @@ -58,10 +58,10 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { public @Nullable Tree visit(@Nullable Tree t, ExecutionContext ctx) { if (t instanceof Yaml.Documents) { t = new org.openrewrite.yaml.DeleteProperty(propertyKey, false, true) - .getVisitor().visitNonNull(t, ctx); + .getVisitor().visitNonNull(t, ctx); } else if (t instanceof Properties.File) { t = new DeleteProperty(propertyKey, true) - .getVisitor().visitNonNull(t, ctx); + .getVisitor().visitNonNull(t, ctx); } return t; } diff --git a/src/main/java/org/openrewrite/java/spring/amqp/UseTlsAmqpConnectionString.java b/src/main/java/org/openrewrite/java/spring/amqp/UseTlsAmqpConnectionString.java index f7a875fc1..22e990e77 100644 --- a/src/main/java/org/openrewrite/java/spring/amqp/UseTlsAmqpConnectionString.java +++ b/src/main/java/org/openrewrite/java/spring/amqp/UseTlsAmqpConnectionString.java @@ -106,10 +106,10 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { public Tree visit(@Nullable Tree t, ExecutionContext ctx) { if (t instanceof Yaml.Documents && sourcePathMatches(((SourceFile) t).getSourcePath(), ctx)) { t = new UseTlsAmqpConnectionStringYaml(actualPropertyKey, oldPort, port, actualTlsPropertyKey, pathExpressions) - .getVisitor().visit(t, ctx); + .getVisitor().visit(t, ctx); } else if (t instanceof Properties.File && sourcePathMatches(((SourceFile) t).getSourcePath(), ctx)) { t = new UseTlsAmqpConnectionStringProperties(actualPropertyKey, oldPort, port, actualTlsPropertyKey, pathExpressions) - .getVisitor().visit(t, ctx); + .getVisitor().visit(t, ctx); } return t; } @@ -195,7 +195,8 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC if (updatedAmqpUrl != amqpUrl) { updated = true; connectionStrings[i] = updatedAmqpUrl.toString(); - doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", "false", null, null).getVisitor()); + doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", "false", null, null) + .getVisitor()); } } else { // hostname:port(/virtualhost) @@ -208,8 +209,10 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC if (!updatedConnectionString.equals(connectionString)) { updated = true; connectionStrings[i] = updatedConnectionString; - doAfterVisit(new AddSpringProperty(tlsPropertyKey, "true", null, pathExpressions).getVisitor()); - doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", null, null, null).getVisitor()); + doAfterVisit(new AddSpringProperty(tlsPropertyKey, "true", null, pathExpressions) + .getVisitor()); + doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", null, null, null) + .getVisitor()); } } } @@ -290,7 +293,8 @@ public Properties.Entry visitEntry(Properties.Entry entry, ExecutionContext ctx) if (updatedAmqpUrl != amqpUrl) { updated = true; connectionStrings[i] = updatedAmqpUrl.toString(); - doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", "false", null, null).getVisitor()); + doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", "false", null, null) + .getVisitor()); } } else { // hostname:port(/virtualhost) @@ -303,8 +307,10 @@ public Properties.Entry visitEntry(Properties.Entry entry, ExecutionContext ctx) if (!updatedConnectionString.equals(connectionString)) { updated = true; connectionStrings[i] = updatedConnectionString; - doAfterVisit(new AddSpringProperty(tlsPropertyKey, "true", null, pathExpressions).getVisitor()); - doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", null, null, null).getVisitor()); + doAfterVisit(new AddSpringProperty(tlsPropertyKey, "true", null, pathExpressions) + .getVisitor()); + doAfterVisit(new ChangeSpringPropertyValue(tlsPropertyKey, "true", null, null, null) + .getVisitor()); } } } diff --git a/src/main/java/org/openrewrite/java/spring/batch/MigrateItemWriterWrite.java b/src/main/java/org/openrewrite/java/spring/batch/MigrateItemWriterWrite.java index cc5e18a5a..ef86536e4 100644 --- a/src/main/java/org/openrewrite/java/spring/batch/MigrateItemWriterWrite.java +++ b/src/main/java/org/openrewrite/java/spring/batch/MigrateItemWriterWrite.java @@ -74,22 +74,23 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, Ex // updated automatically. Since parameters usages do not have their type updated, must replace the whole // method to ensure that type info is accurate / List import can potentially be removed // See: https://github.com/openrewrite/rewrite/issues/2819 - m = m.withTemplate( - JavaTemplate.builder("#{}\n #{} void write(#{} Chunk<#{}> #{}) throws Exception #{}") - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-batch-core-5.+", "spring-batch-infrastructure-5.+")) - .imports("org.springframework.batch.item.Chunk") - .build(), + + m = JavaTemplate.builder("#{}\n #{} void write(#{} Chunk<#{}> #{}) throws Exception #{}") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-batch-core-5.+", "spring-batch-infrastructure-5.+")) + .imports("org.springframework.batch.item.Chunk") + .build() + .apply( getCursor(), m.getCoordinates().replace(), annotationsWithOverride, m.getModifiers().stream() - .map(J.Modifier::toString) - .collect(Collectors.joining(" ")), + .map(J.Modifier::toString) + .collect(Collectors.joining(" ")), parameter.getModifiers().stream() - .map(J.Modifier::toString) - .collect(Collectors.joining(" ")), + .map(J.Modifier::toString) + .collect(Collectors.joining(" ")), chunkTypeParameter, paramName, m.getBody() == null ? "" : m.getBody().print(getCursor())); diff --git a/src/main/java/org/openrewrite/java/spring/batch/MigrateJobBuilderFactory.java b/src/main/java/org/openrewrite/java/spring/batch/MigrateJobBuilderFactory.java index 73a8e84c6..54d720a69 100644 --- a/src/main/java/org/openrewrite/java/spring/batch/MigrateJobBuilderFactory.java +++ b/src/main/java/org/openrewrite/java/spring/batch/MigrateJobBuilderFactory.java @@ -61,17 +61,18 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) doAfterVisit(new MigrateJobBuilderFactory.RemoveJobBuilderFactoryVisitor(clazz, enclosingMethod)); - return method.withTemplate(JavaTemplate - .builder("new JobBuilder(#{any(java.lang.String)}, jobRepository)") - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-batch-core-5.+")) - .imports("org.springframework.batch.core.repository.JobRepository", - "org.springframework.batch.core.job.builder.JobBuilder") - .build(), + return JavaTemplate + .builder("new JobBuilder(#{any(java.lang.String)}, jobRepository)") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-batch-core-5.+")) + .imports("org.springframework.batch.core.repository.JobRepository", + "org.springframework.batch.core.job.builder.JobBuilder") + .build().apply( getCursor(), method.getCoordinates().replace(), - method.getArguments().get(0)); + method.getArguments().get(0) + ); } return super.visitMethodInvocation(method, ctx); } @@ -132,7 +133,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl JavaTemplate paramsTemplate = JavaTemplate .builder(params.stream().map(p -> "#{}").collect(Collectors.joining(", "))) - .context(getCursor()) + .contextSensitive() .imports("org.springframework.batch.core.repository.JobRepository", "org.springframework.batch.core.job.builder.JobBuilder", "org.springframework.batch.core.Step") @@ -140,7 +141,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl .classpathFromResources(ctx, "spring-batch-core-5.+")) .build(); - md = md.withTemplate(paramsTemplate, getCursor(), md.getCoordinates().replaceParameters(), params.toArray()); + md = paramsTemplate.apply(getCursor(), md.getCoordinates().replaceParameters(), params.toArray()); maybeRemoveImport("org.springframework.batch.core.configuration.annotation.JobBuilderFactory"); maybeAddImport("org.springframework.batch.core.repository.JobRepository"); diff --git a/src/main/java/org/openrewrite/java/spring/batch/ReplaceSupportClassWithItsInterface.java b/src/main/java/org/openrewrite/java/spring/batch/ReplaceSupportClassWithItsInterface.java index b39ccf891..841bae17f 100644 --- a/src/main/java/org/openrewrite/java/spring/batch/ReplaceSupportClassWithItsInterface.java +++ b/src/main/java/org/openrewrite/java/spring/batch/ReplaceSupportClassWithItsInterface.java @@ -64,6 +64,7 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, if (cd.getExtends() != null && TypeUtils.isOfClassType(cd.getExtends().getType(), fullyQualifiedClassName)) { cd = cd.withExtends(null); + updateCursor(cd); // This is an interesting one... JobExecutionListenerSupport implements // JobExecutionListener // remove the super type from the class type to prevent a stack-overflow @@ -71,18 +72,19 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, JavaType.Class type = (JavaType.Class) cd.getType(); if (type != null) { cd = cd.withType(type.withSupertype(null)); + updateCursor(cd); } - cd = cd.withTemplate( - JavaTemplate - .builder(JavaType.ShallowClass.build(fullyQualifiedInterfaceName).getClassName()) - .imports(fullyQualifiedInterfaceName) - .javaParser(JavaParser.fromJavaVersion().classpath("spring-batch")) - .build(), + cd = JavaTemplate + .builder(JavaType.ShallowClass.build(fullyQualifiedInterfaceName).getClassName()) + .imports(fullyQualifiedInterfaceName) + .javaParser(JavaParser.fromJavaVersion().classpath("spring-batch")) + .build() + .apply( getCursor(), - cd.getCoordinates().addImplementsClause()); - cd = (J.ClassDeclaration) new RemoveSuperStatementVisitor().visitNonNull(cd, ctx, - getCursor()); + cd.getCoordinates().addImplementsClause() + ); + cd = (J.ClassDeclaration) new RemoveSuperStatementVisitor().visitNonNull(cd, ctx, getCursor()); maybeRemoveImport(fullyQualifiedClassName); maybeAddImport(fullyQualifiedInterfaceName); } diff --git a/src/main/java/org/openrewrite/java/spring/boot2/AddConfigurationAnnotationIfBeansPresent.java b/src/main/java/org/openrewrite/java/spring/boot2/AddConfigurationAnnotationIfBeansPresent.java index c4a4da196..cdcd76c12 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/AddConfigurationAnnotationIfBeansPresent.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/AddConfigurationAnnotationIfBeansPresent.java @@ -62,13 +62,14 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex private J.ClassDeclaration addConfigurationAnnotation(J.ClassDeclaration c) { maybeAddImport(FQN_CONFIGURATION); - JavaTemplate template = JavaTemplate.builder("@" + CONFIGURATION_SIMPLE_NAME) - .imports(FQN_CONFIGURATION) - .javaParser(JavaParser.fromJavaVersion().dependsOn("package " + CONFIGURATION_PACKAGE - + "; public @interface " + CONFIGURATION_SIMPLE_NAME + " {}")) - .build(); - return c.withTemplate(template, getCursor(), - c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + return JavaTemplate.builder("@" + CONFIGURATION_SIMPLE_NAME) + .imports(FQN_CONFIGURATION) + .javaParser(JavaParser.fromJavaVersion().dependsOn("package " + CONFIGURATION_PACKAGE + + "; public @interface " + CONFIGURATION_SIMPLE_NAME + " {}")) + .build().apply( + getCursor(), + c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName)) + ); } }); } diff --git a/src/main/java/org/openrewrite/java/spring/boot2/ConditionalOnBeanAnyNestedCondition.java b/src/main/java/org/openrewrite/java/spring/boot2/ConditionalOnBeanAnyNestedCondition.java index 280050b3f..ec9961114 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/ConditionalOnBeanAnyNestedCondition.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/ConditionalOnBeanAnyNestedCondition.java @@ -23,6 +23,7 @@ import org.openrewrite.java.search.UsesType; import org.openrewrite.java.tree.Expression; import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaCoordinates; import org.openrewrite.java.tree.Statement; import java.util.ArrayList; @@ -117,11 +118,15 @@ public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ct } if (anyConditionClassExists) { - a = a.withTemplate(JavaTemplate.builder("@Conditional(#{}.class)") - .imports("org.springframework.context.annotation.Conditional") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-context-5.*", "spring-boot-autoconfigure-2.*")) - .build(), getCursor(), a.getCoordinates().replace(), conditionalClassName); + a = JavaTemplate.builder("@Conditional(#{}.class)") + .imports("org.springframework.context.annotation.Conditional") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-context-5.*", "spring-boot-autoconfigure-2.*")) + .build() + .apply( + getCursor(), + a.getCoordinates().replace(), conditionalClassName + ); maybeAddImport("org.springframework.context.annotation.Conditional"); } else { // add the new conditional class template string to the parent ClassDeclaration Cursor @@ -145,12 +150,17 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex if (conditionalTemplates != null && !conditionalTemplates.isEmpty()) { for (String s : conditionalTemplates) { JavaTemplate t = JavaTemplate.builder(s) - .context(getCursor()) + .contextSensitive() .imports("org.springframework.boot.autoconfigure.condition.AnyNestedCondition") .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-context-5.*", "spring-boot-autoconfigure-2.*")) .build(); - c = maybeAutoFormat(c, c.withBody(c.getBody().withTemplate(t, getCursor(), c.getBody().getCoordinates().lastStatement())), ctx); + + c = maybeAutoFormat( + c, + t.apply(getCursor(), c.getBody().getCoordinates().lastStatement()), + ctx); + updateCursor(c); } // Schedule another visit to modify the associated annotations now that the new conditional classes have been added to the AST diff --git a/src/main/java/org/openrewrite/java/spring/boot2/DatabaseComponentAndBeanInitializationOrdering.java b/src/main/java/org/openrewrite/java/spring/boot2/DatabaseComponentAndBeanInitializationOrdering.java index 6dec53870..12c8e6119 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/DatabaseComponentAndBeanInitializationOrdering.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/DatabaseComponentAndBeanInitializationOrdering.java @@ -84,12 +84,15 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, Ex if (method.getMethodType() != null) { if (!isInitializationAnnoPresent(md.getLeadingAnnotations()) && isBean(md) && requiresInitializationAnnotation(method.getMethodType().getReturnType())) { - JavaTemplate template = JavaTemplate.builder("@DependsOnDatabaseInitialization") - .imports("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-boot-2.*")) - .build(); - md = md.withTemplate(template, getCursor(), md.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + md = JavaTemplate.builder("@DependsOnDatabaseInitialization") + .imports("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-boot-2.*")) + .build() + .apply( + getCursor(), + md.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName)) + ); maybeAddImport("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization"); } } @@ -101,12 +104,15 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex J.ClassDeclaration cd = super.visitClassDeclaration(classDecl, ctx); if (!isInitializationAnnoPresent(cd.getLeadingAnnotations()) && isComponent(cd) && requiresInitializationAnnotation(cd.getType())) { - JavaTemplate template = JavaTemplate.builder("@DependsOnDatabaseInitialization") - .imports("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-boot-2.*")) - .build(); - cd = cd.withTemplate(template, getCursor(), cd.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + cd = JavaTemplate.builder("@DependsOnDatabaseInitialization") + .imports("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-boot-2.*")) + .build() + .apply( + getCursor(), + cd.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName)) + ); maybeAddImport("org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitialization"); } return cd; diff --git a/src/main/java/org/openrewrite/java/spring/boot2/GetErrorAttributes.java b/src/main/java/org/openrewrite/java/spring/boot2/GetErrorAttributes.java index 2ec5ba13b..3cc154c0e 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/GetErrorAttributes.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/GetErrorAttributes.java @@ -70,36 +70,38 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu Expression includeStackTraceArgument = mi.getArguments().get(1); if (isLiteralTrue(includeStackTraceArgument)) { String template = "#{any(org.springframework.web.context.request.WebRequest)}, ErrorAttributeOptions.defaults().including(ErrorAttributeOptions.Include.STACK_TRACE)"; - mi = mi.withTemplate(JavaTemplate.builder(template) - .context(getCursor()) - .imports(parserImports) - .javaParser(JavaParser.fromJavaVersion() + mi = JavaTemplate.builder(template) + .contextSensitive() + .imports(parserImports) + .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-boot-2.*", "spring-boot-autoconfigure-2.*", "spring-web-5.*")) - .build(), + .build().apply( getCursor(), mi.getCoordinates().replaceArguments(), mi.getArguments().get(0) ); } else if (isLiteralFalse(includeStackTraceArgument)) { String template = "#{any(org.springframework.web.context.request.WebRequest)}, ErrorAttributeOptions.defaults()"; - mi = mi.withTemplate(JavaTemplate.builder(template) - .context(getCursor()) - .imports(parserImports) - .javaParser(JavaParser.fromJavaVersion() + mi = JavaTemplate.builder(template) + .contextSensitive() + .imports(parserImports) + .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-boot-2.*", "spring-boot-autoconfigure-2.*", "spring-web-5.*")) - .build(), + .build() + .apply( getCursor(), mi.getCoordinates().replaceArguments(), mi.getArguments().get(0) ); } else if (!(mi.getArguments().get(1) instanceof J.Ternary)) { String template = "#{any(org.springframework.web.context.request.WebRequest)}, #{any(boolean)} ? ErrorAttributeOptions.defaults().including(ErrorAttributeOptions.Include.STACK_TRACE) : ErrorAttributeOptions.defaults()"; - mi = mi.withTemplate(JavaTemplate.builder(template) - .context(getCursor()) - .imports(parserImports) - .javaParser(JavaParser.fromJavaVersion() + mi = JavaTemplate.builder(template) + .contextSensitive() + .imports(parserImports) + .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-boot-2.*", "spring-boot-autoconfigure-2.*", "spring-web-5.*")) - .build(), + .build() + .apply( getCursor(), mi.getCoordinates().replaceArguments(), mi.getArguments().toArray() diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MigrateActuatorMediaTypeToApiVersion.java b/src/main/java/org/openrewrite/java/spring/boot2/MigrateActuatorMediaTypeToApiVersion.java index 6cd280de5..c82d0f3be 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MigrateActuatorMediaTypeToApiVersion.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MigrateActuatorMediaTypeToApiVersion.java @@ -62,12 +62,13 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu maybeAddImport("org.springframework.boot.actuate.endpoint.ApiVersion"); maybeAddImport("org.springframework.http.MediaType"); maybeRemoveImport("org.springframework.boot.actuate.endpoint.http.ActuatorMediaType"); - mi = mi.withTemplate(JavaTemplate.builder("MediaType.asMediaType(ApiVersion.#{}.getProducedMimeType())") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-web-5.*", "spring-boot-actuator-2.5.*", "spring-core-5.*")) - .imports("org.springframework.http.MediaType", - "org.springframework.boot.actuate.endpoint.ApiVersion") - .build(), + mi = JavaTemplate.builder("MediaType.asMediaType(ApiVersion.#{}.getProducedMimeType())") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-web-5.*", "spring-boot-actuator-2.5.*", + "spring-core-5.*")) + .imports("org.springframework.http.MediaType", + "org.springframework.boot.actuate.endpoint.ApiVersion") + .build().apply( getCursor(), mi.getCoordinates().replace(), apiVersion); diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MigrateDiskSpaceHealthIndicatorConstructor.java b/src/main/java/org/openrewrite/java/spring/boot2/MigrateDiskSpaceHealthIndicatorConstructor.java index 062dc57ca..7129cd8b2 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MigrateDiskSpaceHealthIndicatorConstructor.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MigrateDiskSpaceHealthIndicatorConstructor.java @@ -52,12 +52,11 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { TypeUtils.isOfType(newClass.getConstructorType().getParameterTypes().get(1), JavaType.Primitive.Long)) { maybeAddImport("org.springframework.util.unit.DataSize"); - return newClass.withTemplate( - JavaTemplate.builder("new DiskSpaceHealthIndicator(#{any(java.io.File)}, DataSize.ofBytes(#{any(long)}))") - .imports("org.springframework.util.unit.DataSize") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-boot-actuator-2.*", "spring-core-5.*")) - .build(), + return JavaTemplate.builder("new DiskSpaceHealthIndicator(#{any(java.io.File)}, DataSize.ofBytes(#{any(long)}))") + .imports("org.springframework.util.unit.DataSize") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-boot-actuator-2.*", "spring-core-5.*")) + .build().apply( getCursor(), newClass.getCoordinates().replace(), newClass.getArguments().get(0), diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MigrateLocalServerPortAnnotation.java b/src/main/java/org/openrewrite/java/spring/boot2/MigrateLocalServerPortAnnotation.java index 4a7b13921..a21d84c12 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MigrateLocalServerPortAnnotation.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MigrateLocalServerPortAnnotation.java @@ -31,7 +31,7 @@ public class MigrateLocalServerPortAnnotation extends Recipe { private static final AnnotationMatcher LOCAL_SERVER_PORT_MATCHER = - new AnnotationMatcher("@org.springframework.boot.context.embedded.LocalServerPort"); + new AnnotationMatcher("@org.springframework.boot.context.embedded.LocalServerPort"); @Override public String getDisplayName() { @@ -46,30 +46,30 @@ public String getDescription() { @Override public TreeVisitor getVisitor() { return Preconditions.check(new UsesType<>("org.springframework.boot.context.embedded.LocalServerPort", false), - new JavaIsoVisitor() { - @Override - public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) { - J.Annotation a = super.visitAnnotation(annotation, ctx); - if (LOCAL_SERVER_PORT_MATCHER.matches(annotation)) { - a = a.withAnnotationType(a.getAnnotationType().withType(JavaType.buildType("org.springframework.boot.web.server.LocalServerPort"))); - maybeRemoveImport("org.springframework.boot.context.embedded.LocalServerPort"); - maybeAddImport("org.springframework.boot.web.server.LocalServerPort"); - } - return a; + new JavaIsoVisitor() { + @Override + public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) { + J.Annotation a = super.visitAnnotation(annotation, ctx); + if (LOCAL_SERVER_PORT_MATCHER.matches(annotation)) { + a = a.withAnnotationType(a.getAnnotationType().withType(JavaType.buildType("org.springframework.boot.web.server.LocalServerPort"))); + maybeRemoveImport("org.springframework.boot.context.embedded.LocalServerPort"); + maybeAddImport("org.springframework.boot.web.server.LocalServerPort"); } - }); + return a; + } + }); } @Override public List getRecipeList() { return Collections.singletonList(new AddDependency( - "org.springframework.boot", - "spring-boot-starter-web", - "2.0.x", - null, - "org.springframework.boot.web.server.LocalServerPort", - "org.springframework.boot.web.server.LocalServerPort", - null, - null, null, null, null, null, null, null)); + "org.springframework.boot", + "spring-boot-starter-web", + "2.0.x", + null, + "org.springframework.boot.web.server.LocalServerPort", + "org.springframework.boot.web.server.LocalServerPort", + null, + null, null, null, null, null, null, null)); } } diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MigrateMultipartConfigFactory.java b/src/main/java/org/openrewrite/java/spring/boot2/MigrateMultipartConfigFactory.java index ec1018a00..b4d505f45 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MigrateMultipartConfigFactory.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MigrateMultipartConfigFactory.java @@ -54,24 +54,21 @@ public TreeVisitor getVisitor() { public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { J.MethodInvocation m = super.visitMethodInvocation(method, ctx); if (setMaxFileSizeByLong.matches(m) || setMaxRequestSizeByLong.matches(m) || setFileSizeThresholdByInt.matches(m)) { - m = m.withTemplate( - JavaTemplate - .builder("DataSize.ofBytes(#{any()})") + m = JavaTemplate.builder("DataSize.ofBytes(#{any()})") .imports("org.springframework.util.unit.DataSize") .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-core-5.*", "spring-boot-2.*")) - .build(), + .build().apply( getCursor(), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); } else if (setMaxFileSizeByString.matches(m) || setMaxRequestSizeByString.matches(m) || setFileSizeThresholdByString.matches(m)) { - m = m.withTemplate( - JavaTemplate - .builder("DataSize.parse(#{any(java.lang.String)})") - .imports("org.springframework.util.unit.DataSize") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-core-5.*", "spring-boot-2.*")) - .build(), + m = JavaTemplate + .builder("DataSize.parse(#{any(java.lang.String)})") + .imports("org.springframework.util.unit.DataSize") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-core-5.*", "spring-boot-2.*")) + .build().apply( getCursor(), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MigrateRestTemplateBuilderTimeoutByInt.java b/src/main/java/org/openrewrite/java/spring/boot2/MigrateRestTemplateBuilderTimeoutByInt.java index 56422bd27..07f7d8620 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MigrateRestTemplateBuilderTimeoutByInt.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MigrateRestTemplateBuilderTimeoutByInt.java @@ -49,13 +49,13 @@ public TreeVisitor getVisitor() { public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { J.MethodInvocation m = super.visitMethodInvocation(method, ctx); if (connectionTimeout.matches(method) || readTimeout.matches(method)) { - m = m.withTemplate( - JavaTemplate - .builder("Duration.ofMillis(#{any(int)})") - .imports("java.time.Duration") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-boot-2.*")) - .build(), + m = JavaTemplate + .builder("Duration.ofMillis(#{any(int)})") + .imports("java.time.Duration") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-boot-2.*")) + .build() + .apply( getCursor(), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); diff --git a/src/main/java/org/openrewrite/java/spring/boot2/MoveAutoConfigurationToImportsFile.java b/src/main/java/org/openrewrite/java/spring/boot2/MoveAutoConfigurationToImportsFile.java index a0a4eb14f..a71e8c13b 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/MoveAutoConfigurationToImportsFile.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/MoveAutoConfigurationToImportsFile.java @@ -277,10 +277,8 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex .imports("org.springframework.boot.autoconfigure.AutoConfiguration") .build(); - doAfterVisit(new RemoveAnnotation("@org.springframework.context.annotation.Configuration") - .getVisitor()); - - c = c.withTemplate(addAnnotationTemplate, getCursor(), c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + doAfterVisit(new RemoveAnnotation("@org.springframework.context.annotation.Configuration").getVisitor()); + c = addAnnotationTemplate.apply(getCursor(), c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); maybeAddImport("org.springframework.boot.autoconfigure.AutoConfiguration"); } return c; diff --git a/src/main/java/org/openrewrite/java/spring/boot2/OutputCaptureExtension.java b/src/main/java/org/openrewrite/java/spring/boot2/OutputCaptureExtension.java index d7ea290db..29e99d699 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/OutputCaptureExtension.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/OutputCaptureExtension.java @@ -88,6 +88,7 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex } return s; }))); + updateCursor(c); if (classDecl.getBody().getStatements().size() != c.getBody().getStatements().size()) { JavaTemplate addOutputCaptureExtension = JavaTemplate.builder("@ExtendWith(OutputCaptureExtension.class)") @@ -97,10 +98,12 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex "org.springframework.boot.test.system.OutputCaptureExtension") .build(); - c = c.withTemplate(addOutputCaptureExtension, getCursor(), c.getCoordinates() + c = addOutputCaptureExtension.apply( + getCursor(), + c.getCoordinates() .addAnnotation(Comparator.comparing( - J.Annotation::getSimpleName, - new RuleBasedCollator("< ExtendWith") + J.Annotation::getSimpleName, + new RuleBasedCollator("< ExtendWith") )) ); @@ -135,11 +138,11 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu } JavaTemplate matchesTemplate = JavaTemplate.builder("#{any()}.matches(#{}.getAll())") - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-boot-test-2.*", "junit-jupiter-api-5.*")) .build(); - m = m.withTemplate(matchesTemplate, getCursor(), m.getCoordinates().replace(), m.getArguments().get(0), variableName); + m = matchesTemplate.apply(getCursor(), m.getCoordinates().replace(), m.getArguments().get(0), variableName); return m; } } @@ -158,7 +161,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, Ex if (!FindMethods.find(m, "org.springframework.boot.test.rule.OutputCapture *(..)").isEmpty() || !FindMethods.find(m, "org.springframework.boot.test.system.OutputCaptureRule *(..)").isEmpty()) { // FIXME need addParameter coordinate here... - // m = m.withTemplate(parameter.build(), m.getCoordinates().replaceParameters()); + // m = parameter.build().apply(m.getCoordinates().replaceParameters()); J.VariableDeclarations param = new J.VariableDeclarations(Tree.randomId(), Space.EMPTY, diff --git a/src/main/java/org/openrewrite/java/spring/boot2/ReplaceDeprecatedEnvironmentTestUtils.java b/src/main/java/org/openrewrite/java/spring/boot2/ReplaceDeprecatedEnvironmentTestUtils.java index 1809b11bf..522f4e9a3 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/ReplaceDeprecatedEnvironmentTestUtils.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/ReplaceDeprecatedEnvironmentTestUtils.java @@ -251,13 +251,12 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu Optional maybeMarker = m.getMarkers().findFirst(ReplaceEnvironmentUtilsMarker.class); if (maybeMarker.isPresent()) { ReplaceEnvironmentUtilsMarker marker = maybeMarker.get(); - m = m.withTemplate( - JavaTemplate.builder(marker.templateString) - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-boot-test-2.*")) - .imports("org.springframework.boot.test.util.TestPropertyValues") - .build(), + m = JavaTemplate.builder(marker.templateString) + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-boot-test-2.*")) + .imports("org.springframework.boot.test.util.TestPropertyValues") + .build().apply( getCursor(), m.getCoordinates().replace(), marker.parameters.toArray() diff --git a/src/main/java/org/openrewrite/java/spring/boot2/ReplaceExtendWithAndContextConfiguration.java b/src/main/java/org/openrewrite/java/spring/boot2/ReplaceExtendWithAndContextConfiguration.java index 9ccd3e998..57d28fd12 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/ReplaceExtendWithAndContextConfiguration.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/ReplaceExtendWithAndContextConfiguration.java @@ -118,12 +118,13 @@ private void replaceValueArgumentWithLocations(J.Annotation a, List } private J.Assignment createLocationsAssignment(J.Annotation annotation, Expression value) { - return (J.Assignment) ((J.Annotation) annotation.withTemplate( - JavaTemplate.builder("locations = #{any(String)}").context(getCursor()).build(), - getCursor(), - annotation.getCoordinates().replaceArguments(), - value - )).getArguments().get(0); + return (J.Assignment) ((J.Annotation) + JavaTemplate.builder("locations = #{any(String)}") + .contextSensitive().build().apply( + getCursor(), + annotation.getCoordinates().replaceArguments(), + value + )).getArguments().get(0); } }); } diff --git a/src/main/java/org/openrewrite/java/spring/boot2/RestTemplateBuilderRequestFactory.java b/src/main/java/org/openrewrite/java/spring/boot2/RestTemplateBuilderRequestFactory.java index 3520d66ce..34ccc490c 100644 --- a/src/main/java/org/openrewrite/java/spring/boot2/RestTemplateBuilderRequestFactory.java +++ b/src/main/java/org/openrewrite/java/spring/boot2/RestTemplateBuilderRequestFactory.java @@ -61,10 +61,10 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu if (REQUEST_FACTORY.matches(method) && isArgumentClientHttpRequestFactory) { JavaTemplate.Builder t = JavaTemplate.builder("() -> #{any(org.springframework.http.client.ClientHttpRequestFactory)}") - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-boot-2.*")); - m = m.withTemplate(t.build(), getCursor(), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); + m = t.build().apply(getCursor(), m.getCoordinates().replaceArguments(), m.getArguments().get(0)); } return m; } diff --git a/src/main/java/org/openrewrite/java/spring/boot3/AddSetUseTrailingSlashMatch.java b/src/main/java/org/openrewrite/java/spring/boot3/AddSetUseTrailingSlashMatch.java index 04aadc19a..78b974302 100644 --- a/src/main/java/org/openrewrite/java/spring/boot3/AddSetUseTrailingSlashMatch.java +++ b/src/main/java/org/openrewrite/java/spring/boot3/AddSetUseTrailingSlashMatch.java @@ -105,10 +105,10 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex return super.visitClassDeclaration(classDecl, ctx); } else { // add a `configurePathMatch` or `configurePathMatching` method to this class - JavaTemplate WebMvcConfigurePathMatchTemplate = JavaTemplate.builder( + JavaTemplate webMvcConfigurePathMatchTemplate = JavaTemplate.builder( "@Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer" + ".setUseTrailingSlashMatch(true); }") - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpath("spring-webmvc", "spring-context", "spring-web")) .imports(WEB_MVC_PATH_MATCH_CONFIGURER, @@ -120,7 +120,7 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex JavaTemplate.builder( "@Override public void configurePathMatching(PathMatchConfigurer configurer) { configurer" + ".setUseTrailingSlashMatch(true); }") - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpath("spring-webflux", "spring-context", "spring-web")) .imports(WEB_FLUX_PATH_MATCH_CONFIGURER, @@ -128,14 +128,8 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex "org.springframework.context.annotation.Configuration") .build(); - - JavaTemplate template = isWebMVC ? WebMvcConfigurePathMatchTemplate : webFluxConfigurePathMatchingTemplate; - classDecl = classDecl.withBody( - classDecl.getBody().withTemplate( - template, - getCursor(), - classDecl.getBody().getCoordinates().lastStatement() - )); + JavaTemplate template = isWebMVC ? webMvcConfigurePathMatchTemplate : webFluxConfigurePathMatchingTemplate; + classDecl = template.apply(getCursor(), classDecl.getBody().getCoordinates().lastStatement()); String importPathMatchConfigurer = isWebMVC ? WEB_MVC_PATH_MATCH_CONFIGURER : WEB_FLUX_PATH_MATCH_CONFIGURER; maybeAddImport(importPathMatchConfigurer, false); @@ -155,8 +149,8 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, } else { // add statement - JavaTemplate WebMvcTemplate = JavaTemplate.builder("#{any()}.setUseTrailingSlashMatch(true);") - .context(getCursor()) + JavaTemplate webMvcTemplate = JavaTemplate.builder("#{any()}.setUseTrailingSlashMatch(true);") + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpath("spring-webmvc", "spring-context", "spring-web")) .imports(WEB_MVC_PATH_MATCH_CONFIGURER, @@ -164,8 +158,8 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, "org.springframework.context.annotation.Configuration") .build(); - JavaTemplate WebFluxTemplate = JavaTemplate.builder("#{any()}.setUseTrailingSlashMatch(true);") - .context(getCursor()) + JavaTemplate webFluxTemplate = JavaTemplate.builder("#{any()}.setUseTrailingSlashMatch(true);") + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpath("spring-webflux", "spring-context", "spring-web")) .imports(WEB_MVC_PATH_MATCH_CONFIGURER, @@ -173,17 +167,12 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, "org.springframework.context.annotation.Configuration") .build(); - boolean isWebMVC = isWebMVCConfigurerMatchMethod(method); - - method = method.withBody( - method.getBody().withTemplate( - isWebMVC ? WebMvcTemplate : WebFluxTemplate, - getCursor(), - method.getBody().getCoordinates().lastStatement(), - ((J.VariableDeclarations) method.getParameters().get(0)).getVariables().get(0).getName() - )); - - return method; + JavaTemplate template = isWebMVCConfigurerMatchMethod(method) ? webMvcTemplate : webFluxTemplate; + return template.apply( + getCursor(), + method.getBody().getCoordinates().lastStatement(), + ((J.VariableDeclarations) method.getParameters().get(0)).getVariables().get(0).getName() + ); } } diff --git a/src/main/java/org/openrewrite/java/spring/boot3/ConfigurationOverEnableSecurity.java b/src/main/java/org/openrewrite/java/spring/boot3/ConfigurationOverEnableSecurity.java index b4e57d90d..fe07b34d3 100644 --- a/src/main/java/org/openrewrite/java/spring/boot3/ConfigurationOverEnableSecurity.java +++ b/src/main/java/org/openrewrite/java/spring/boot3/ConfigurationOverEnableSecurity.java @@ -115,14 +115,17 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex } } - JavaTemplate template = JavaTemplate.builder("@Configuration") - .imports(CONFIGURATION_FQN) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-context-5.3.+")) - .build(); maybeAddImport(CONFIGURATION_FQN); - return c.withTemplate(template, getCursor(), c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + return JavaTemplate.builder("@Configuration") + .imports(CONFIGURATION_FQN) + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-context-5.3.+")) + .build() + .apply( + getCursor(), + c.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName)) + ); } private boolean isExcluded(Set securityAnnotations) { diff --git a/src/main/java/org/openrewrite/java/spring/data/MigrateJpaSort.java b/src/main/java/org/openrewrite/java/spring/data/MigrateJpaSort.java index c096a8da4..bef3cbbf4 100644 --- a/src/main/java/org/openrewrite/java/spring/data/MigrateJpaSort.java +++ b/src/main/java/org/openrewrite/java/spring/data/MigrateJpaSort.java @@ -68,17 +68,18 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { .map(type -> "#{any(" + (type == null ? "" : type.getFullyQualifiedName()) + ")}") .collect(Collectors.joining(",", "JpaSort.of(", ")")); - return newClass.withTemplate( - JavaTemplate.builder(template) - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-data-commons-2.*", - "spring-data-jpa-2.3.*", "javax.persistence-api-2.*")) - .imports("org.springframework.data.jpa.domain.JpaSort") - .build(), + return JavaTemplate.builder(template) + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-data-commons-2.*", + "spring-data-jpa-2.3.*", "javax.persistence-api-2.*")) + .imports("org.springframework.data.jpa.domain.JpaSort") + .build() + .apply( getCursor(), newClass.getCoordinates().replace(), - newClass.getArguments().toArray()); + newClass.getArguments().toArray() + ); } return super.visitNewClass(newClass, ctx); diff --git a/src/main/java/org/openrewrite/java/spring/data/MigrateQuerydslJpaRepository.java b/src/main/java/org/openrewrite/java/spring/data/MigrateQuerydslJpaRepository.java index 9baf87375..87ddb1289 100644 --- a/src/main/java/org/openrewrite/java/spring/data/MigrateQuerydslJpaRepository.java +++ b/src/main/java/org/openrewrite/java/spring/data/MigrateQuerydslJpaRepository.java @@ -51,8 +51,7 @@ public TreeVisitor getVisitor() { @Override public J visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) { J.CompilationUnit c = (J.CompilationUnit) super.visitCompilationUnit(cu, ctx); - c = (J.CompilationUnit) new ChangeType(originalFqn, targetFqn, false) - .getVisitor().visitNonNull(c, ctx); + doAfterVisit(new ChangeType(originalFqn, targetFqn, false).getVisitor()); return c; } @@ -75,16 +74,15 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { "#{any(org.springframework.data.querydsl.EntityPathResolver)}, null)"; J.FieldAccess entityPathResolver = TypeTree.build("SimpleEntityPathResolver.INSTANCE"); - return newClass.withTemplate( - JavaTemplate.builder(template) - .imports(targetFqn) - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, - "javax.persistence-api-2.*", - "spring-data-commons-2.*", - "spring-data-jpa-2.*" - )) - .build(), + return JavaTemplate.builder(template) + .imports(targetFqn) + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, + "javax.persistence-api-2.*", + "spring-data-commons-2.*", + "spring-data-jpa-2.*" + )) + .build().apply( getCursor(), newClass.getCoordinates().replace(), newClass.getArguments().get(0), diff --git a/src/main/java/org/openrewrite/java/spring/data/UseTlsJdbcConnectionString.java b/src/main/java/org/openrewrite/java/spring/data/UseTlsJdbcConnectionString.java index 866bff72c..475eb61b9 100644 --- a/src/main/java/org/openrewrite/java/spring/data/UseTlsJdbcConnectionString.java +++ b/src/main/java/org/openrewrite/java/spring/data/UseTlsJdbcConnectionString.java @@ -96,17 +96,15 @@ public TreeVisitor getVisitor() { String actualPropertyKey = propertyKey == null ? "spring.datasource.url" : propertyKey; return new TreeVisitor() { - @Override - public @Nullable Tree visit(@Nullable Tree t, ExecutionContext ctx) { - if (t instanceof Yaml.Documents) { - t = new UseTlsJdbcConnectionStringYaml(actualPropertyKey, oldPort, port, validatedAttribute) - .getVisitor().visitNonNull(t, ctx); - } else if (t instanceof Properties.File) { - t = new UseTlsJdbcConnectionStringProperties(actualPropertyKey, oldPort, port, validatedAttribute) - .getVisitor().visitNonNull(t, ctx); + public Tree preVisit(Tree tree, ExecutionContext ctx) { + stopAfterPreVisit(); + if (tree instanceof Yaml.Documents) { + doAfterVisit(new UseTlsJdbcConnectionStringYaml(actualPropertyKey, oldPort, port, validatedAttribute).getVisitor()); + } else if (tree instanceof Properties.File) { + doAfterVisit(new UseTlsJdbcConnectionStringProperties(actualPropertyKey, oldPort, port, validatedAttribute).getVisitor()); } - return t; + return tree; } }; } diff --git a/src/main/java/org/openrewrite/java/spring/framework/EnvironmentAcceptsProfiles.java b/src/main/java/org/openrewrite/java/spring/framework/EnvironmentAcceptsProfiles.java index cd9d594a6..6a10f1818 100644 --- a/src/main/java/org/openrewrite/java/spring/framework/EnvironmentAcceptsProfiles.java +++ b/src/main/java/org/openrewrite/java/spring/framework/EnvironmentAcceptsProfiles.java @@ -52,15 +52,16 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu if (MATCHER.matches(method)) { maybeAddImport("org.springframework.core.env.Profiles"); String template = "Profiles.of(" + method.getArguments().stream().map(a -> "#{any(java.lang.String)}").collect(Collectors.joining(",")) + ")"; - method = method.withTemplate(JavaTemplate.builder(template) - .imports("org.springframework.core.env.Profiles", "org.springframework.core.env.Environment") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-core-5.*")) - .build(), + method = JavaTemplate.builder(template) + .imports("org.springframework.core.env.Profiles", "org.springframework.core.env.Environment") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-core-5.*")) + .build() + .apply( getCursor(), method.getCoordinates().replaceArguments(), method.getArguments().toArray() - ); + ); } return super.visitMethodInvocation(method, ctx); } diff --git a/src/main/java/org/openrewrite/java/spring/framework/MigrateInstantiationAwareBeanPostProcessorAdapter.java b/src/main/java/org/openrewrite/java/spring/framework/MigrateInstantiationAwareBeanPostProcessorAdapter.java index 073f49288..652051d77 100644 --- a/src/main/java/org/openrewrite/java/spring/framework/MigrateInstantiationAwareBeanPostProcessorAdapter.java +++ b/src/main/java/org/openrewrite/java/spring/framework/MigrateInstantiationAwareBeanPostProcessorAdapter.java @@ -15,13 +15,18 @@ */ package org.openrewrite.java.spring.framework; -import org.openrewrite.*; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; -import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.ChangeType; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.search.UsesType; -import org.openrewrite.java.tree.*; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.Space; +import org.openrewrite.java.tree.TypeUtils; import org.openrewrite.marker.Markers; import java.util.Collections; @@ -59,13 +64,10 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex } @Override - public @Nullable J visit(@Nullable Tree tree, ExecutionContext ctx) { - J j = super.visit(tree, ctx); - if (j instanceof JavaSourceFile) { - j = (J) new ChangeType(fromExtendingFqn, toImplementsFqn, false) - .getVisitor().visitNonNull(j, ctx); - } - return j; + public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) { + J.CompilationUnit compilationUnit = super.visitCompilationUnit(cu, ctx); + doAfterVisit(new ChangeType(fromExtendingFqn, toImplementsFqn, false).getVisitor()); + return compilationUnit; } }); } diff --git a/src/main/java/org/openrewrite/java/spring/framework/MigrateWebMvcConfigurerAdapter.java b/src/main/java/org/openrewrite/java/spring/framework/MigrateWebMvcConfigurerAdapter.java index 0f0125c7b..d2f28336f 100644 --- a/src/main/java/org/openrewrite/java/spring/framework/MigrateWebMvcConfigurerAdapter.java +++ b/src/main/java/org/openrewrite/java/spring/framework/MigrateWebMvcConfigurerAdapter.java @@ -15,11 +15,7 @@ */ package org.openrewrite.java.spring.framework; -import org.openrewrite.ExecutionContext; -import org.openrewrite.Preconditions; -import org.openrewrite.Recipe; -import org.openrewrite.SourceFile; -import org.openrewrite.TreeVisitor; +import org.openrewrite.*; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; import org.openrewrite.java.JavaTemplate; @@ -49,20 +45,21 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex J.ClassDeclaration cd = super.visitClassDeclaration(classDecl, ctx); if (cd.getExtends() != null && TypeUtils.isOfClassType(cd.getExtends().getType(), "org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter")) { cd = cd.withExtends(null); + updateCursor(cd); // This is an interesting one... WebMvcConfigurerAdapter implements WebMvcConfigurer // remove the super type from the class type to prevent a stack-overflow exception when the JavaTemplate visits class type. JavaType.Class type = (JavaType.Class) cd.getType(); if (type != null) { cd = cd.withType(type.withSupertype(null)); + updateCursor(cd); } - cd = cd.withTemplate(JavaTemplate.builder("WebMvcConfigurer") - .context(getCursor().dropParentUntil(p -> p instanceof J.ClassDeclaration || p instanceof SourceFile)) + cd = JavaTemplate.builder("WebMvcConfigurer") + .contextSensitive() .imports("org.springframework.web.servlet.config.annotation.WebMvcConfigurer") .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-webmvc-5.*")) - .build(), - getCursor(), - cd.getCoordinates().addImplementsClause()); + .build().apply(getCursor(), cd.getCoordinates().addImplementsClause()); + updateCursor(cd); cd = (J.ClassDeclaration) new RemoveSuperStatementVisitor().visitNonNull(cd, ctx, getCursor()); maybeRemoveImport("org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter"); maybeAddImport("org.springframework.web.servlet.config.annotation.WebMvcConfigurer"); diff --git a/src/main/java/org/openrewrite/java/spring/security5/ReplaceGlobalMethodSecurityWithMethodSecurity.java b/src/main/java/org/openrewrite/java/spring/security5/ReplaceGlobalMethodSecurityWithMethodSecurity.java index 4ba3d2dd6..41563f303 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/ReplaceGlobalMethodSecurityWithMethodSecurity.java +++ b/src/main/java/org/openrewrite/java/spring/security5/ReplaceGlobalMethodSecurityWithMethodSecurity.java @@ -68,15 +68,17 @@ public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ct newArgs.add(buildPrePostEnabledAssignedToFalse()); } - JavaTemplate enableMethodSecurityTemplate = JavaTemplate.builder("@EnableMethodSecurity") - .javaParser(JavaParser.fromJavaVersion() - .classpathFromResources(ctx, "spring-security-config-5.8.+")) - .imports(EnableMethodSecurityFqn) - .build(); - maybeAddImport(EnableMethodSecurityFqn); maybeRemoveImport(EnableGlobalMethodSecurityFqn); - annotation = annotation.withTemplate(enableMethodSecurityTemplate, getCursor(), annotation.getCoordinates().replace()); + annotation = JavaTemplate.builder("@EnableMethodSecurity") + .javaParser(JavaParser.fromJavaVersion() + .classpathFromResources(ctx, "spring-security-config-5.8.+")) + .imports(EnableMethodSecurityFqn) + .build() + .apply( + getCursor(), + annotation.getCoordinates().replace() + ); return autoFormat(annotation.withArguments(newArgs), ctx); } return annotation; diff --git a/src/main/java/org/openrewrite/java/spring/security5/UpdateArgon2PasswordEncoder.java b/src/main/java/org/openrewrite/java/spring/security5/UpdateArgon2PasswordEncoder.java index ce41fda6c..ab96ba51a 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/UpdateArgon2PasswordEncoder.java +++ b/src/main/java/org/openrewrite/java/spring/security5/UpdateArgon2PasswordEncoder.java @@ -78,7 +78,8 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { newClass = (J.NewClass) j; if (DEFAULT_CONSTRUCTOR_MATCHER.matches(newClass)) { maybeAddImport(ARGON2_PASSWORD_ENCODER_CLASS); - return newClass.withTemplate(newV52FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + + return newV52FactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { List arguments = newClass.getArguments(); if (FULL_CONSTRUCTOR_MATCHER.matches(newClass)) { @@ -93,13 +94,13 @@ && resolvedValueMatchesLiteral(hashLength, DEFAULT_HASH_LENGTH) && resolvedValueMatchesLiteral(parallelism, DEFAULT_PARALLELISM) && resolvedValueMatchesLiteral(memory, DEFAULT_MEMORY) && resolvedValueMatchesLiteral(iterations, DEFAULT_ITERATIONS)) { - return newClass.withTemplate(newV58FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newV58FactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else if (resolvedValueMatchesLiteral(saltLength, DEFAULT_V52_SALT_LENGTH) && resolvedValueMatchesLiteral(hashLength, DEFAULT_V52_HASH_LENGTH) && resolvedValueMatchesLiteral(parallelism, DEFAULT_V52_PARALLELISM) && resolvedValueMatchesLiteral(memory, DEFAULT_V52_MEMORY) && resolvedValueMatchesLiteral(iterations, DEFAULT_V52_ITERATIONS)) { - return newClass.withTemplate(newV52FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newV52FactoryMethodTemplate(ctx).apply(getCursor(),newClass.getCoordinates().replace()); } } } diff --git a/src/main/java/org/openrewrite/java/spring/security5/UpdatePbkdf2PasswordEncoder.java b/src/main/java/org/openrewrite/java/spring/security5/UpdatePbkdf2PasswordEncoder.java index a124edee8..5c0eccdc4 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/UpdatePbkdf2PasswordEncoder.java +++ b/src/main/java/org/openrewrite/java/spring/security5/UpdatePbkdf2PasswordEncoder.java @@ -83,18 +83,18 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { newClass = (J.NewClass) j; if (DEFAULT_CONSTRUCTOR_MATCHER.matches(newClass)) { maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS); - return newClass.withTemplate(newFactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newFactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { List arguments = newClass.getArguments(); if (ONE_ARG_CONSTRUCTOR_MATCHER.matches(newClass)) { Expression secret = arguments.get(0); maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS); if (resolvedValueMatchesLiteral(secret, DEFAULT_SECRET)) { - return newClass.withTemplate(newFactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newFactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { String algorithm = HASH_WIDTH_TO_ALGORITHM_MAP.get(DEFAULT_HASH_WIDTH); maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS + ".SecretKeyFactoryAlgorithm", algorithm); - return newClass.withTemplate(newConstructorTemplate(ctx, algorithm), getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), newIntLiteral(DEFAULT_ITERATIONS)); + return newConstructorTemplate(ctx, algorithm).apply(getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), newIntLiteral(DEFAULT_ITERATIONS)); } } else if (TWO_ARG_CONSTRUCTOR_MATCHER.matches(newClass)) { Expression secret = arguments.get(0); @@ -102,11 +102,11 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS); if (resolvedValueMatchesLiteral(secret, DEFAULT_SECRET) && resolvedValueMatchesLiteral(saltLength, DEFAULT_SALT_LENGTH)) { - return newClass.withTemplate(newFactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newFactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { String algorithm = HASH_WIDTH_TO_ALGORITHM_MAP.get(DEFAULT_HASH_WIDTH); maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS + ".SecretKeyFactoryAlgorithm", algorithm); - return newClass.withTemplate(newConstructorTemplate(ctx, algorithm), getCursor(), newClass.getCoordinates().replace(), secret, saltLength, newIntLiteral(DEFAULT_ITERATIONS)); + return newConstructorTemplate(ctx, algorithm).apply(getCursor(), newClass.getCoordinates().replace(), secret, saltLength, newIntLiteral(DEFAULT_ITERATIONS)); } } else if (THREE_ARG_CONSTRUCTOR_MATCHER.matches(newClass)) { Expression secret = arguments.get(0); @@ -117,14 +117,14 @@ && resolvedValueMatchesLiteral(saltLength, DEFAULT_SALT_LENGTH)) { if (resolvedValueMatchesLiteral(secret, DEFAULT_SECRET) && resolvedValueMatchesLiteral(iterations, DEFAULT_ITERATIONS) && DEFAULT_HASH_WIDTH.equals(knownHashWidth)) { - return newClass.withTemplate(newFactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newFactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { String algorithm = HASH_WIDTH_TO_ALGORITHM_MAP.get(knownHashWidth); if (algorithm != null) { maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS + ".SecretKeyFactoryAlgorithm", algorithm); - return newClass.withTemplate(newConstructorTemplate(ctx, algorithm), getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), iterations); + return newConstructorTemplate(ctx, algorithm).apply(getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), iterations); } else { - return newClass.withTemplate(newDeprecatedConstructorTemplate(ctx), getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), iterations, hashWidth); + return newDeprecatedConstructorTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace(), secret, newIntLiteral(DEFAULT_SALT_LENGTH), iterations, hashWidth); } } } @@ -139,7 +139,7 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) if (j instanceof J.MethodInvocation && VERSION5_5_FACTORY_MATCHER.matches(((J.MethodInvocation) j))) { maybeAddImport(PBKDF2_PASSWORD_ENCODER_CLASS); method = (J.MethodInvocation) j; - return method.withTemplate(newFactoryMethodTemplate(ctx), getCursor(), method.getCoordinates().replace()); + return newFactoryMethodTemplate(ctx).apply(getCursor(), method.getCoordinates().replace()); } return j; } diff --git a/src/main/java/org/openrewrite/java/spring/security5/UpdateSCryptPasswordEncoder.java b/src/main/java/org/openrewrite/java/spring/security5/UpdateSCryptPasswordEncoder.java index 88f03531c..db59721f6 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/UpdateSCryptPasswordEncoder.java +++ b/src/main/java/org/openrewrite/java/spring/security5/UpdateSCryptPasswordEncoder.java @@ -78,7 +78,7 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) { newClass = (J.NewClass) j; if (DEFAULT_CONSTRUCTOR_MATCHER.matches(newClass)) { maybeAddImport(SCRYPT_PASSWORD_ENCODER_CLASS); - return newClass.withTemplate(newV41FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newV41FactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else { List arguments = newClass.getArguments(); if (FULL_CONSTRUCTOR_MATCHER.matches(newClass)) { @@ -93,13 +93,13 @@ && resolvedValueMatchesLiteral(memoryCost, DEFAULT_MEMORY_COST) && resolvedValueMatchesLiteral(parallelization, DEFAULT_PARALLELIZATION) && resolvedValueMatchesLiteral(keyLength, DEFAULT_KEY_LENGTH) && resolvedValueMatchesLiteral(saltLength, DEFAULT_SALT_LENGTH)) { - return newClass.withTemplate(newV58FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newV58FactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } else if (resolvedValueMatchesLiteral(cpuCost, DEFAULT_V41_CPU_COST) && resolvedValueMatchesLiteral(memoryCost, DEFAULT_V41_MEMORY_COST) && resolvedValueMatchesLiteral(parallelization, DEFAULT_V41_PARALLELIZATION) && resolvedValueMatchesLiteral(keyLength, DEFAULT_V41_KEY_LENGTH) && resolvedValueMatchesLiteral(saltLength, DEFAULT_V41_SALT_LENGTH)) { - return newClass.withTemplate(newV41FactoryMethodTemplate(ctx), getCursor(), newClass.getCoordinates().replace()); + return newV41FactoryMethodTemplate(ctx).apply(getCursor(), newClass.getCoordinates().replace()); } } } diff --git a/src/main/java/org/openrewrite/java/spring/security5/UseNewSecurityMatchers.java b/src/main/java/org/openrewrite/java/spring/security5/UseNewSecurityMatchers.java index f88c93639..9ca324b69 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/UseNewSecurityMatchers.java +++ b/src/main/java/org/openrewrite/java/spring/security5/UseNewSecurityMatchers.java @@ -56,14 +56,14 @@ public TreeVisitor getVisitor() { public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { J.MethodInvocation mi = super.visitMethodInvocation(method, ctx); if (HTTP_SECURITY_MATCHER.matches(mi) && mi.getMethodType() != null) { - return mi.withTemplate(securityMatcherTemplate(ctx), getCursor(), mi.getCoordinates().replaceMethod(), mi.getArguments().get(0)); + return securityMatcherTemplate(ctx).apply(getCursor(), mi.getCoordinates().replaceMethod(), mi.getArguments().get(0)); } return mi; } private JavaTemplate securityMatcherTemplate(ExecutionContext ctx) { return JavaTemplate.builder("securityMatcher(#{any(String)})") - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .classpathFromResources(ctx, "spring-security-web-5.8.+", "spring-security-config-5.8.+")) .build(); diff --git a/src/main/java/org/openrewrite/java/spring/security5/WebSecurityConfigurerAdapter.java b/src/main/java/org/openrewrite/java/spring/security5/WebSecurityConfigurerAdapter.java index c39c40d73..c79ae5207 100644 --- a/src/main/java/org/openrewrite/java/spring/security5/WebSecurityConfigurerAdapter.java +++ b/src/main/java/org/openrewrite/java/spring/security5/WebSecurityConfigurerAdapter.java @@ -314,12 +314,15 @@ private J.MethodDeclaration changeToBeanMethod(J.MethodDeclaration m, J.ClassDec } maybeAddImport(inmemoryAuthConfigType); - return addBeanAnnotation(m, getCursor()); + // not calling `updateCursor()` here because `visitBlock()` currently requires + // the original to be stored in the cursor + return addBeanAnnotation(m, new Cursor(getCursor().getParentOrThrow(), m)); } @Override public J.Block visitBlock(J.Block block, ExecutionContext ctx) { J.Block b = super.visitBlock(block, ctx); + updateCursor(b); if (getCursor().getParent() != null && getCursor().getParent().getValue() instanceof J.MethodDeclaration) { J.MethodDeclaration parentMethod = getCursor().getParent().getValue(); Cursor classDeclCursor = getCursor().dropParentUntil(it -> it instanceof J.ClassDeclaration || it == Cursor.ROOT_VALUE); @@ -352,21 +355,32 @@ public J.Block visitBlock(J.Block block, ExecutionContext ctx) { } private J.Block handleHttpSecurity(J.Block b, J.MethodDeclaration parentMethod) { - JavaTemplate template = JavaTemplate.builder("return #{any(org.springframework.security.config.annotation.SecurityBuilder)}.build();") - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .dependsOn("package org.springframework.security.config.annotation;" + - "public interface SecurityBuilder {\n" + - " O build() throws Exception;" + - "}")).imports("org.springframework.security.config.annotation.SecurityBuilder").build(); - return b.withTemplate(template, getCursor(), b.getCoordinates().lastStatement(), - ((J.VariableDeclarations) parentMethod.getParameters().get(0)).getVariables().get(0).getName()); + return JavaTemplate.builder("return #{any(org.springframework.security.config.annotation.SecurityBuilder)}.build();") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .dependsOn("package org.springframework.security.config.annotation;" + + "public interface SecurityBuilder {\n" + + " O build() throws Exception;" + + "}")) + .imports("org.springframework.security.config.annotation.SecurityBuilder") + .build() + .apply( + getCursor(), + b.getCoordinates().lastStatement(), + ((J.VariableDeclarations) parentMethod.getParameters().get(0)).getVariables().get(0).getName() + ); } private J.Block handleWebSecurity(J.Block b, J.MethodDeclaration parentMethod) { String t = "return (" + ((J.VariableDeclarations) parentMethod.getParameters().get(0)).getVariables().get(0).getName().getSimpleName() + ") -> #{any()};"; - JavaTemplate template = JavaTemplate.builder(t).context(getCursor()).javaParser(JavaParser.fromJavaVersion()).build(); - b = b.withTemplate(template, getCursor(), b.getCoordinates().firstStatement(), b); + b = JavaTemplate.builder(t) + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion()) + .build() + .apply( + getCursor(), + b.getCoordinates().firstStatement(), b + ); return b.withStatements(ListUtils.map(b.getStatements(), (index, stmt) -> { if (index == 0) { return stmt; @@ -407,10 +421,9 @@ private J.Block handleAuthInMemory(J.Block b, J.MethodDeclaration parentMethod) b = SearchResult.found(b, "Unrecognized type of user expression " + userExpr + "\n.Please correct manually"); } JavaTemplate template = JavaTemplate.builder(t) - .context(getCursor()) + .contextSensitive() .javaParser(JavaParser.fromJavaVersion() .dependsOn( - "package org.springframework.security.core.userdetails;\n" + "public interface UserDetails {}\n", @@ -432,9 +445,8 @@ private J.Block handleAuthInMemory(J.Block b, J.MethodDeclaration parentMethod) .build(); List allExceptLastStatements = b.getStatements(); allExceptLastStatements.remove(b.getStatements().size() - 1); - b = b - .withStatements(allExceptLastStatements) - .withTemplate(template, getCursor(), b.getCoordinates().lastStatement(), templateParams); + b = b.withStatements(allExceptLastStatements); + b = template.apply(updateCursor(b), b.getCoordinates().lastStatement(), templateParams); maybeAddImport(FQN_INMEMORY_AUTH_MANAGER); maybeRemoveImport(FQN_AUTH_MANAGER_BUILDER); return b; @@ -442,12 +454,16 @@ private J.Block handleAuthInMemory(J.Block b, J.MethodDeclaration parentMethod) private J.MethodDeclaration addBeanAnnotation(J.MethodDeclaration m, Cursor c) { maybeAddImport(FQN_BEAN); - JavaTemplate template = JavaTemplate.builder(BEAN_ANNOTATION).imports(FQN_BEAN).javaParser(JavaParser.fromJavaVersion() - .dependsOn("package " + BEAN_PKG + "; public @interface " + BEAN_SIMPLE_NAME + " {}")).build(); - return m.withTemplate(template, c, m.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName))); + return JavaTemplate.builder(BEAN_ANNOTATION) + .imports(FQN_BEAN) + .javaParser(JavaParser.fromJavaVersion() + .dependsOn("package " + BEAN_PKG + "; public @interface " + BEAN_SIMPLE_NAME + " {}")) + .build() + .apply( + c, + m.getCoordinates().addAnnotation(Comparator.comparing(J.Annotation::getSimpleName)) + ); } - - }); } diff --git a/src/main/java/org/openrewrite/java/spring/security6/UpdateRequestCache.java b/src/main/java/org/openrewrite/java/spring/security6/UpdateRequestCache.java index 88b9dbfc2..87d8d3e88 100644 --- a/src/main/java/org/openrewrite/java/spring/security6/UpdateRequestCache.java +++ b/src/main/java/org/openrewrite/java/spring/security6/UpdateRequestCache.java @@ -15,10 +15,7 @@ */ package org.openrewrite.java.spring.security6; -import org.openrewrite.ExecutionContext; -import org.openrewrite.Preconditions; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; +import org.openrewrite.*; import org.openrewrite.internal.ListUtils; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; @@ -75,15 +72,18 @@ public J.Block visitBlock(J.Block block, ExecutionContext executionContext) { for (int i = 0; i < statements.size(); i++) { Statement statement = statements.get(i); if (isNewHttpSessionRequestCacheStatement(statement)) { - JavaTemplate template = JavaTemplate.builder("#{any()}.setMatchingRequestParameterName(\"continue\");") - .context(getCursor()) - .javaParser(JavaParser.fromJavaVersion() - .classpath("spring-security-web")) - .imports( - "org.springframework.security.web.savedrequest.HttpSessionRequestCache") - .build(); - - statement = statement.withTemplate(template, getCursor(), statement.getCoordinates().replace(), getSelect(statement)); + statement = JavaTemplate.builder("#{any()}.setMatchingRequestParameterName(\"continue\");") + .contextSensitive() + .javaParser(JavaParser.fromJavaVersion() + .classpath("spring-security-web")) + .imports( + "org.springframework.security.web.savedrequest.HttpSessionRequestCache") + .build() + .apply( + new Cursor(getCursor(), statement), + statement.getCoordinates().replace(), + getSelect(statement) + ); statements = ListUtils.insert(statements, statement, i + 1); return block.withStatements(statements); @@ -104,10 +104,11 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, .imports( "org.springframework.security.web.savedrequest.NullRequestCache") .build(); - maybeAddImport("org.springframework.security.web.savedrequest.NullRequestCache"); maybeRemoveImport("org.springframework.security.web.savedrequest.HttpSessionRequestCache"); - arg = arg.withTemplate(template, getCursor(), arg.getCoordinates().replace()); + arg = template.apply( + new Cursor(getCursor(), arg), + arg.getCoordinates().replace()); return method.withArguments(Collections.singletonList(arg)); } diff --git a/src/main/java/org/openrewrite/maven/spring/UpgradeExplicitSpringBootDependencies.java b/src/main/java/org/openrewrite/maven/spring/UpgradeExplicitSpringBootDependencies.java index abf12cd37..4ac75d7f7 100644 --- a/src/main/java/org/openrewrite/maven/spring/UpgradeExplicitSpringBootDependencies.java +++ b/src/main/java/org/openrewrite/maven/spring/UpgradeExplicitSpringBootDependencies.java @@ -178,6 +178,8 @@ private void mayBeUpdateVersion(String groupId, String artifactId, Xml.Tag tag) if (!version.isPresent() || !version.get().getValue().isPresent()) { return; } + // TODO: we could use the org.openrewrite.java.dependencies.UpgradeDependencyVersion if we implement there a getVisitor with a similar logic than here, + // but right now it's just a list of recipes, and the getVisitor is the default from Recipe and does nothing SourceFile sourceFile = getCursor().firstEnclosing(SourceFile.class); if (sourceFile instanceof Xml.Document) { doAfterVisit(new org.openrewrite.maven.UpgradeDependencyVersion(groupId, artifactId, dependencyVersion, null, null, null).getVisitor()); diff --git a/src/testWithSpringBoot_2_3/java/org/openrewrite/java/spring/boot2/SpringBoot2JUnit4to5MigrationTest.java b/src/testWithSpringBoot_2_3/java/org/openrewrite/java/spring/boot2/SpringBoot2JUnit4to5MigrationTest.java index d8b61b459..c3884ee39 100644 --- a/src/testWithSpringBoot_2_3/java/org/openrewrite/java/spring/boot2/SpringBoot2JUnit4to5MigrationTest.java +++ b/src/testWithSpringBoot_2_3/java/org/openrewrite/java/spring/boot2/SpringBoot2JUnit4to5MigrationTest.java @@ -15,6 +15,7 @@ */ package org.openrewrite.java.spring.boot2; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openrewrite.Issue; import org.openrewrite.config.Environment; @@ -40,6 +41,7 @@ public void defaults(RecipeSpec spec) { @Issue("https://github.com/openrewrite/rewrite-spring/issues/43") @Test + @Disabled // TODO: dependency on rewrite-testing-frameworks void springBootRunWithRemovedNoExtension() { //language=java rewriteRun( @@ -81,6 +83,7 @@ void testFindAll() { @Issue("https://github.com/openrewrite/rewrite-spring/issues/296") @Test + @Disabled // TODO: dependency on rewrite-testing-frameworks void springBootRunWithContextConfigurationReplacedWithSpringJUnitConfig() { //language=java rewriteRun(