You mentioned that I could open a ticket for a kind-of rewrite I am struggling with. Beside the ValidatedNel typealias rewrite, there is one more kind of recipes that I am struggling with. If both are resolved I think I can provide rewrites for all important rewrites needed for Arrow, which would be huge ๐ฅณ
It's kind-of related to to #25, since that would also solve my problem but I think applying ReplaceWith through recipes is even more complex. I am not sure if the Kotlin compiler/parser somewhere exposes ReplaceWith rewrites (this could be possible). It should occurs somewhere in the Kotlin Plugin / analyser. (I request some pointers from @raulraja if he could provide more insights).
What I am struggling with is how this rewrite can be achieved in a recipe. The biggest problem I think is that the lambda can also appear in the shape of a method reference: listOf(1, 2, 3).traverse(::validated) or be a multi-line lambda. So it seems that the only shaped approach is to capture the result of the lambda in a val and then call bind in the following line.
funvalidate(int:Int): Either<String, Int> =TODO()
listOf(1, 2, 3).mapOrAccumulate {
val res = validate(it)
res.bind()
}
That requires to know for sure the chosen name for res doesn't overlap with any other variables defined in a potentially multi-line lambda.
resulted in an incorrect change of formatting. The "static" import, is excluded from the regular import list, and follows a similar pattern of styling as Java imports. Which is unnatural for Kotlin, since there is no concept of "static" they also don't appear separately in the import list.
Strangely, it also resulted in the import getting collapsed into * imports when 3 of these "static" imports appeared. This was also an unexpected side-effect but could potentially be solved within the same issue.
When I didn't use "static" imports for these imports, I encountered an other issue. Since it was fixed by using "static" imports for these top-level imports I am assuming I was using a hack before by using maybeAddImport("arrow.core.raise.ensure", false) and this somehow caused a bug.
When parsing and printing the source code back to text without modifications, the printed source didn't match the original source code. This means there is a bug in the parser implementation itself. Please open an issue to report this, providing a sample of the code that generated this error!
vararg will only parse successfully if it is the only argument in the method declaration: asList(vararg ts: T)
@TestvoidvarArgs() {
rewriteRun(
kotlin(
""" fun <T> asList(s: String, vararg ts: T): List<T> { val result = ArrayList<T>() for (t in ts) // ts is an Array result.add(t) return result } val list = asList ("", 1 , 2 , 3 ) """
)
);
}
We use the ResolvedReferences from the FIR to preserve bound generics.
In some cases, the Symbols#getResolvedReturnTypeRef will throw a CastClassException, because we should be calling Symbol#getFir#getReturnTypeRef.
I am using ChangeType to rewrite Validated to Either, and it's not working for following case. (It's perhaps a bit far-fetched and wasn't expecting this to work, but implementing a custom ChangeType seems tricky so hoping we can perhaps find an intermediate solution).
I currently have following typealiases:
typealiasValidatedNel<E, A> =Validated<NonEmptyList<A>, E>typealiasEitherNel<E, A> =Either<NonEmptyList<A>, E>
Ideally would be a way to rewrite from ValidatedNel<E, A> to EitherNel<E, A> but it's not at all blocking.
I also tried following, but naturally it didn't do anything ๐
Parentheses may surround any expression but are not preserved in the FIR. The PARENTHESIZED element only exists in the PSI but requires mapping the PSI to the FIR. The FIR may be constructed from multiple PSIs and is not easily mapped.
Note: The FIR is necessary for the correct type attribution because the PSI DOES NOT contain the correct types, and the common case of binary expressions to enforce order of execution has been handled.
The KotlinParser adds all the Input as sources to the Kotlin compiler before calling convertAnalyzedFirToIr.` An exception may occur during the conversion; the error is currently not associated with a specific input.
It may be possible to execute convertAnalyzedFirToIr per SourceFile now that the Disposable is not disposed of until all sources have generated CUs because the FirSession will still be available.
This PR attempts to search for the ensure method invocation, but visitMethodInvocation is never called.
The resulting assertion message is also quite confusing, see below. Inspecting the code it seems that after in Assertions.kotlin on line 49 is never used, and discarded.
org.opentest4j.AssertionFailedError: [When parsing and printing the source code back to text without modifications, the printed source didn't match the original source code. This means there is a bug in the parser implementation itself. Please open an issue to report this, providing a sample of the code that generated this error!]
expected:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
but was:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false,) { "failure")
return 1
}"
but actually expected:
org.opentest4j.AssertionFailedError: [When parsing and printing the source code back to text without modifications, the printed source didn't match the original source code. This means there is a bug in the parser implementation itself. Please open an issue to report this, providing a sample of the code that generated this error!]
expected:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
but was:
"package com.yourorg
import arrow.core.raise.Raise
import arrow.core.raise.ensure
fun Raise<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
* What went wrong:
Execution failed for task ':rewriteRun'.
> java.lang.RuntimeException: java.lang.IllegalArgumentException: 'other' is different type of Path
import org.example.Message// Message is accessible
import org.test.MessageasTestMessage// TestMessage stands for 'org.test.Message'
This is a common enough situation in many languages that it may make sense to change J.Import to add a new field. The Java printer would ignore this field, but other language printers would not.
The class path is detected, the jar is set in KotlinParser through addJvmClasspathRoot(compilerConfiguration, file);, and the class exists in the jar, but the Kotlin compiler does not resolve the type.
I tried to keep the changes in this PR to a minimal, but some additional information:
Same issue occurs when using KotlinIsoVisitor
Same issue occurs if using JavaTemplate.builder(this::getCursor, "public fun hello(): String { return \"Hello from #{}!\" }")
As the stacktrace below indicates the line triggering this exception in the user code is J.withTemplate on line 74 in SayHelloRecipe.java.
Failing with following output:
java.lang.AssertionError: Failed to parse sources or run recipe
at org.openrewrite.test.RewriteTest.lambda$defaultExecutionContext$11(RewriteTest.java:511)
at org.openrewrite.RecipeScheduler.lambda$scheduleVisit$4(RecipeScheduler.java:274)
at org.openrewrite.RecipeScheduler.lambda$mapAsync$0(RecipeScheduler.java:56)
at org.openrewrite.scheduling.DirectScheduler.schedule(DirectScheduler.java:35)
at org.openrewrite.RecipeScheduler.mapAsync(RecipeScheduler.java:57)
at org.openrewrite.RecipeScheduler.scheduleVisit(RecipeScheduler.java:236)
at org.openrewrite.test.RecipeSchedulerCheckingExpectedCycles.scheduleVisit(RecipeSchedulerCheckingExpectedCycles.java:50)
at org.openrewrite.RecipeScheduler.scheduleRun(RecipeScheduler.java:101)
at org.openrewrite.Recipe.run(Recipe.java:330)
at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:319)
at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:128)
at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:123)
at arrow.SayHelloRecipeTest.addsHelloToFooBar(SayHelloRecipeTest.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.openrewrite.internal.RecipeRunException: Exception while visiting project file 'null (in FooBar)', caused by: java.lang.NullPointerException: Cannot invoke "org.openrewrite.java.tree.J$Block.getMarkers()" because the return value of "org.openrewrite.java.tree.J$ClassDeclaration.getBody()" is null, at org.openrewrite.kotlin.internal.KotlinPrinter$KotlinJavaPrinter.visitClassDeclaration(KotlinPrinter.java:303)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:324)
at app//org.openrewrite.kotlin.internal.KotlinPrinter$KotlinJavaPrinter.visit(KotlinPrinter.java:198)
at app//org.openrewrite.kotlin.internal.KotlinPrinter.visit(KotlinPrinter.java:45)
at app//org.openrewrite.kotlin.internal.KotlinPrinter.visit(KotlinPrinter.java:38)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:172)
at app//org.openrewrite.Tree.print(Tree.java:93)
at app//org.openrewrite.Tree.print(Tree.java:89)
at app//org.openrewrite.Tree.printTrimmed(Tree.java:108)
at app//org.openrewrite.java.internal.template.BlockStatementTemplateGenerator.classDeclaration(BlockStatementTemplateGenerator.java:538)
at app//org.openrewrite.java.internal.template.BlockStatementTemplateGenerator.template(BlockStatementTemplateGenerator.java:189)
at app//org.openrewrite.java.internal.template.BlockStatementTemplateGenerator.lambda$template$0(BlockStatementTemplateGenerator.java:84)
at app//io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:65)
at app//org.openrewrite.java.internal.template.BlockStatementTemplateGenerator.template(BlockStatementTemplateGenerator.java:71)
at app//org.openrewrite.java.internal.template.JavaTemplateParser.parseBlockStatements(JavaTemplateParser.java:158)
at app//org.openrewrite.java.internal.template.JavaTemplateJavaExtension$1.visitBlock(JavaTemplateJavaExtension.java:80)
at app//org.openrewrite.java.internal.template.JavaTemplateJavaExtension$1.visitBlock(JavaTemplateJavaExtension.java:59)
at app//org.openrewrite.java.tree.J$Block.acceptJava(J.java:761)
at app//org.openrewrite.java.tree.J.accept(J.java:64)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:276)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:172)
at app//org.openrewrite.java.JavaTemplate.withTemplate(JavaTemplate.java:107)
at app//org.openrewrite.java.JavaTemplate.withTemplate(JavaTemplate.java:39)
at app//org.openrewrite.java.tree.J.withTemplate(J.java:91)
at app//arrow.SayHelloRecipe$SayHelloVisitor.visitClassDeclaration(SayHelloRecipe.java:76)
at app//arrow.SayHelloRecipe$SayHelloVisitor.visitClassDeclaration(SayHelloRecipe.java:45)
at app//org.openrewrite.java.tree.J$ClassDeclaration.acceptJava(J.java:1211)
at app//org.openrewrite.java.tree.J.accept(J.java:64)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:276)
at app//org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:356)
at app//org.openrewrite.kotlin.KotlinVisitor.lambda$visitCompilationUnit$2(KotlinVisitor.java:54)
at app//org.openrewrite.internal.ListUtils.lambda$map$0(ListUtils.java:145)
at app//org.openrewrite.internal.ListUtils.map(ListUtils.java:126)
at app//org.openrewrite.internal.ListUtils.map(ListUtils.java:145)
at app//org.openrewrite.kotlin.KotlinVisitor.visitCompilationUnit(KotlinVisitor.java:54)
at app//org.openrewrite.kotlin.KotlinVisitor.visitJavaSourceFile(KotlinVisitor.java:42)
at app//org.openrewrite.kotlin.tree.K$CompilationUnit.acceptKotlin(K.java:177)
at app//org.openrewrite.kotlin.tree.K.accept(K.java:48)
at app//org.openrewrite.TreeVisitor.visit(TreeVisitor.java:276)
at app//org.openrewrite.RecipeScheduler.lambda$scheduleVisit$4(RecipeScheduler.java:270)
... 94 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.openrewrite.java.tree.J$Block.getMarkers()" because the return value of "org.openrewrite.java.tree.J$ClassDeclaration.getBody()" is null
at org.openrewrite.kotlin.internal.KotlinPrinter$KotlinJavaPrinter.visitClassDeclaration(KotlinPrinter.java:303)
at org.openrewrite.kotlin.internal.KotlinPrinter$KotlinJavaPrinter.visitClassDeclaration(KotlinPrinter.java:191)
at org.openrewrite.java.tree.J$ClassDeclaration.acceptJava(J.java:1211)
at org.openrewrite.java.tree.J.accept(J.java:64)
at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:276)
... 132 more
Parsing failure on FirLambdaArgumentExpression.
Cause: building the function call arguments assumes the arguments are comma delimited.
Kotlin allows trailing lambda to be a part of the method invocation per docs.
The assertion message is incorrect, see below. Inspecting the code it seems that after in Assertions.kotlin on line 49 is never used, and discarded.
org.opentest4j.AssertionFailedError: [When parsing and printing the source code back to text without modifications, the printed source didn't match the original source code. This means there is a bug in the parser implementation itself. Please open an issue to report this, providing a sample of the code that generated this error!]
expected:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
but was:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false,) { "failure")
return 1
}"
but actually expected:
org.opentest4j.AssertionFailedError: [When parsing and printing the source code back to text without modifications, the printed source didn't match the original source code. This means there is a bug in the parser implementation itself. Please open an issue to report this, providing a sample of the code that generated this error!]
expected:
"package com.yourorg
import arrow.core.continuations.EffectScope
fun EffectScope<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
but was:
"package com.yourorg
import arrow.core.raise.Raise
import arrow.core.raise.ensure
fun Raise<String>.test(): Int {
ensure(false) { "failure" }
return 1
}"
If present, specifies a code fragment which should be used as a replacement for the deprecated API usage.
This can speed up recipe development, as simple replacements are specified directly on the deprecated methods. A few different samples taken from Arrow's deprecation of Validated:
arrow/core/Either.kt
@Deprecated(
"orNone is being renamed to getOrNone to be more consistent with the Kotlin Standard Library naming",
ReplaceWith("getOrNone()")
)
publicfunorNone(): Option<B> = getOrNone()
arrow/core/Validated.kt
@Deprecated(
DeprMsg+"Use isLeft on Either after refactoring",
ReplaceWith("toEither().isLeft()")
)
publicval isInvalid:Boolean=
fold({ true }, { false })
@Deprecated(
DeprMsg+"Use left instead to construct the equivalent Either value",
ReplaceWith("this.left()", "arrow.core.left")
)
publicinlinefun <E> E.invalid(): Validated<E, Nothing> =Invalid(this)
Goal
Ideally these replacements can be done just by looking at the runtime classpath for any deprecated methods used in the current code, and replacing those instances directly. As an intermediate we can look at generating replacement recipes for some simple cases only, and/or write those recipe stubs out to yaml files to be applied separately. There may be more options, but figured start a discussion here with this initial outline.