Moderne Recipes
This doc includes every recipe that is exclusive to users of Moderne. For a full list of all recipes, check out our recipe catalog. For more information about how to use Moderne for automating code refactoring and analysis at scale, contact us.
io.moderne.recipe
recipes-kotlin
- org.openrewrite.kotlin.android.Android$KtRecipe
- Find Android smells
- Search-only Android recipe family covering the deprecated-API surface (Activity / Fragment / Handler / kotlinx.android.synthetic / parcel / Vibrator / registerReceiver), storage-layer footguns (
SharedPreferences.commit, Room@Queryshape,ContentResolver.query), lifecycle smells (LiveData.observe(this, ...), publicMutableLiveData), permissions/security (requestPermissions,MODE_WORLD_*), Android-specific performance (findViewByIdinonDraw, rawBitmapFactory,Handler.postDelayed,runOnUiThread), WebView smells (loadUrl,setJavaScriptEnabled), logging smells (Log.*,System.out), and modernization candidates (manualParcelable/Serializable, RxJava, raw Dagger, manualViewModelProvider,ObjectAnimator,Runtime.exec).
- org.openrewrite.kotlin.android.FindAlertDialogBuilderConstructor$KtRecipe
- Find
AlertDialog.Builder(this)constructions android.app.AlertDialog.Builderdoes not pick up app-bar themes or Material styles. For consistent theming on AppCompat surfaces, useandroidx.appcompat.app.AlertDialog.Builder(orMaterialAlertDialogBuilderfor Material apps). Each match is worth a quick accessibility/theming review.
- Find
- org.openrewrite.kotlin.android.FindAndroidLifecycleSmells$KtRecipe
- Find Android lifecycle / LiveData smells
- Lifecycle and observable-state patterns that leak across configuration changes or expose internal mutability:
LiveData.observe(this, ...)inside fragments,MutableLiveData.postValuefrom main-thread contexts, publicMutableLiveDataproperties, and rawMutableLiveDataallocations.
- org.openrewrite.kotlin.android.FindAndroidLogUsage$KtRecipe
- Find
android.util.Log.v/d/i/w/e(...)calls android.util.Logis a flat global logger with no routing, no structured fields, and no off-by-default for release builds. Migrate to Timber (per-tree fan-out, automatic tag detection) or AndroidXandroidx.tracingfor performance-trace integration. Each match is a candidate for the migration.
- Find
- org.openrewrite.kotlin.android.FindAndroidLoggingSmells$KtRecipe
- Find Android logging smells
- Logging shapes that don't compose with structured logging:
android.util.Log.v/d/i/w/ecalls (flat global logger; prefer Timber orandroidx.tracing) andSystem.out.printlnon Android (untagged logcat output).
- org.openrewrite.kotlin.android.FindAndroidModernizationCandidates$KtRecipe
- Find Android modernization candidates
- Patterns that work but predate the modern Android toolchain: manual
Parcelable(@Parcelize),java.io.Serializableon Android transports, RxJava imports (coroutines + Flow),Dagger*Component.builder()(Hilt), directViewModelProviderconstruction (by viewModels()),ObjectAnimator(Compose animation APIs), andRuntime.exec(audit for app-sandbox fit).
- org.openrewrite.kotlin.android.FindAndroidPerformanceSmells$KtRecipe
- Find Android-specific performance smells
- Patterns that drop UI-thread frames or allocate at draw time:
findViewByIdinsideonDraw/onMeasure/onLayout, unboundedBitmapFactory.decode*(noinSampleSize), hand-rolledThread.start()from UI components,Handler.postDelayed(no lifecycle), and pre-coroutinerunOnUiThread/View.postdispatch.
- org.openrewrite.kotlin.android.FindAndroidPermissionsSmells$KtRecipe
- Find Android permissions / security smells
- Permission-handling patterns the platform has deprecated: direct
requestPermissions(...)calls andonRequestPermissionsResultoverrides (useActivityResultContracts.RequestPermission), andMODE_WORLD_READABLE/WORLD_WRITEABLE(useFileProvider).
- org.openrewrite.kotlin.android.FindAndroidStorageSmells$KtRecipe
- Find Android storage / data-layer smells
- Storage-tier patterns that block the main thread or sit on deprecated APIs:
SharedPreferences.Editor.commit(), bareprefs.edit()calls, Room@Querymethods returning synchronous results,ContentResolver.query, and Realm usage.
- org.openrewrite.kotlin.android.FindAndroidViewModelInjection$KtRecipe
- Find
ViewModelProvider(...)direct constructions ViewModelProvider(this).get(MyViewModel::class.java)predates theby viewModels()/by activityViewModels()Kotlin property delegates. With Hilt, those delegates pick up the@HiltViewModelannotation — no factory plumbing needed at the call site.
- Find
- org.openrewrite.kotlin.android.FindAndroidWebViewSmells$KtRecipe
- Find Android WebView smells
- WebView call sites that need a security review:
WebView.loadUrl(...)(URL trust boundary) andWebSettings.setJavaScriptEnabled(true)(script-execution trust boundary). For untrusted content, Chrome Custom Tabs (CustomTabsIntent) is the safer alternative.
- org.openrewrite.kotlin.android.FindAsyncTask$KtRecipe
- Find
AsyncTaskinstantiations AsyncTaskwas deprecated in API 30. The Kotlin replacement isviewModelScope.launch \{ withContext(Dispatchers.IO) \{ … \} \}or another coroutine-aware framework. Each match is a candidate for migration.
- Find
- org.openrewrite.kotlin.android.FindAsyncTaskExecute$KtRecipe
- Find
AsyncTask.execute/executeOnExecutorcalls - Beyond
AsyncTaskinstantiation, theexecute/executeOnExecutorcall sites are the place the background work actually starts. Migration toviewModelScope.launch \{ withContext(Dispatchers.IO) \{ … \} \}happens at the call site, not the declaration — flag both.
- Find
- org.openrewrite.kotlin.android.FindBareHandlerConstructor$KtRecipe
- Find
Handler()constructor calls without an explicitLooper - The zero-arg
Handlerconstructor was deprecated in API 30 because it implicitly captures the current thread's looper — a footgun when called from a background thread. Always pass an explicitLooper, e.g.Handler(Looper.getMainLooper()).
- Find
- org.openrewrite.kotlin.android.FindBitmapFactoryDecode$KtRecipe
- Find
BitmapFactory.decode*calls BitmapFactory.decode*without an explicitBitmapFactory.Options.inSampleSizeallocates the bitmap at full source resolution. For UI use, downsample viainSampleSize(or move the entire concern to Coil/Glide, which handle pooling, lifecycle, and downsampling for you).
- Find
- org.openrewrite.kotlin.android.FindContentResolverQuery$KtRecipe
- Find
ContentResolver.query(...)calls ContentResolver.query(...)blocks the calling thread for the full lifetime of the underlying IPC and cursor walk. Wrap the call inwithContext(Dispatchers.IO) \{ … \}, expose it as aFlow(contentResolver.observe(uri)-style), or move to a Room@Queryif the data is backed by SQLite.
- Find
- org.openrewrite.kotlin.android.FindContextRegisterReceiver$KtRecipe
- Find
Context.registerReceiver(...)calls - On API 33+
registerReceiver(...)requires an explicitRECEIVER_EXPORTED/RECEIVER_NOT_EXPORTEDflag — calls without it throwSecurityException. Migrate toContextCompat.registerReceiver(...), which forwards the flag and is backwards-compatible.
- Find
- org.openrewrite.kotlin.android.FindDeprecatedAndroidApis$KtRecipe
- Find deprecated Android APIs
- Search-only bundle that flags Android APIs the platform has deprecated or removed:
findViewById,AsyncTask, the single-arggetColor/getDrawable/getColorStateListresource getters, the zero-argHandler()constructor,kotlinx.android.syntheticimports, the movedkotlinx.android.parcel.Parcelizeimport,startActivityForResult/onActivityResult/requestPermissions,LocalBroadcastManager, deprecatedFragmentlifecycle methods,Resources.getDrawable/getColor,startService,PreferenceManager,Vibrator.vibrate(long),Context.registerReceiverwithout flags, andMutableLiveDataallocations.
- org.openrewrite.kotlin.android.FindDeprecatedParcelizeImport$KtRecipe
- Find
kotlinx.android.parcelimports - The
kotlinx.android.parcelpackage was moved tokotlinx.parcelizein 2020 when the standalone Parcelize plugin shipped. Replace the import and the Gradle plugin coordinate.
- Find
- org.openrewrite.kotlin.android.FindDeprecatedResourceGetters$KtRecipe
- Find deprecated
Context.getColor/getDrawable/getColorStateListcalls - The single-argument forms on
Context/Resourcesare deprecated — they don't take a theme and behave inconsistently across API levels. UseContextCompat.getColor(context, id)/ContextCompat.getDrawable(context, id)/AppCompatResources.getColorStateList(context, id)instead.
- Find deprecated
- org.openrewrite.kotlin.android.FindFindViewById$KtRecipe
- Find
findViewByIdcall sites findViewByIdis the legacy view-lookup API. Modern Android uses ViewBinding (auto-generatedBindingclasses per layout) which is type-safe, null-safe, and avoids the per-call HashMap walk. Each match is a candidate for migration.
- Find
- org.openrewrite.kotlin.android.FindFindViewByIdInHotPath$KtRecipe
- Find
findViewByIdinsideonDraw/onMeasure/onLayout - View tree-walking inside the draw/measure/layout pass costs frame budget on every pass. Cache the lookup once (in
onFinishInflateor alateinitinitialized when the view attaches), or — better — migrate to ViewBinding so the cache is generated.
- Find
- org.openrewrite.kotlin.android.FindFragmentManagerExecutePendingTransactions$KtRecipe
- Find
FragmentManager.executePendingTransactions()calls executePendingTransactions()forces synchronous fragment-transaction execution on the calling thread — usually a workaround for code that races a not-yet-attached fragment. PrefercommitNow()/commitNowAllowingStateLoss()at the call site that scheduled the transaction, or restructure the call to read state from the resulting fragment'sonViewCreated.
- Find
- org.openrewrite.kotlin.android.FindFragmentOnActivityCreated$KtRecipe
- Find
Fragment.onActivityCreatedoverrides Fragment.onActivityCreated(Bundle)was deprecated in Fragment 1.3 because the host-activity lifecycle is no longer a reliable signal for fragment readiness. Move the work toonViewCreated(view-state setup) or to aLifecycleObserveronviewLifecycleOwner(cross-component coordination).
- Find
- org.openrewrite.kotlin.android.FindFragmentOnAttachActivity$KtRecipe
- Find
Fragment.onAttach(Activity)overrides - The
onAttach(Activity)overload was deprecated in API 23 — useonAttach(Context)instead. TheContextparameter is the activity for activity-hosted fragments and the application context for headless cases, and works on devices where the parent is not an activity.
- Find
- org.openrewrite.kotlin.android.FindFragmentSetRetainInstance$KtRecipe
- Find
Fragment.setRetainInstance(true)calls Fragment.setRetainInstance(true)was deprecated in Fragment 1.3 because retained fragments break process-death restoration and tangle the lifecycle owner with the host activity. Move retained state to aViewModelscoped to the navigation host.
- Find
- org.openrewrite.kotlin.android.FindHandlerPostDelayed$KtRecipe
- Find
Handler.postDelayed(...)calls Handler.postDelayed(runnable, ms)schedules main-thread work without a story for cancellation — the canonical bug is the activity dying while the runnable is still scheduled, then running with a stale view reference. UselifecycleScope.launch \{ delay(ms); … \}instead: cancellation is automatic on lifecycle teardown.
- Find
- org.openrewrite.kotlin.android.FindIntentActionGetContent$KtRecipe
- Find legacy
Intent.ACTION_PICK/ACTION_GET_CONTENTreferences ACTION_PICK/ACTION_GET_CONTENTpredate the Photo Picker (ACTION_PICK_IMAGES, API 33+ with backport) and the Storage Access Framework (ACTION_OPEN_DOCUMENT). For media, preferActivityResultContracts.PickVisualMedia; for documents,OpenDocument.
- Find legacy
- org.openrewrite.kotlin.android.FindKotlinAndroidSyntheticImports$KtRecipe
- Find
kotlinx.android.synthetic.*imports - The Kotlin Android Extensions synthetic-view plugin was deprecated in 1.4.20 and removed entirely in later AGP versions. Migrate the call sites to ViewBinding. Each reference here corresponds to a usage that won't compile without the (removed) plugin.
- Find
- org.openrewrite.kotlin.android.FindLifecycleObserveLiveData$KtRecipe
- Find
LiveData.observe(this, observer)calls insideFragment - Inside a
Fragment,liveData.observe(this, observer)ties the subscription to the fragment's lifecycle — which outlives the view acrossonDestroyView/onCreateViewrecreation and produces dangling references to a destroyed view. UseviewLifecycleOwnerinstead.
- Find
- org.openrewrite.kotlin.android.FindLiveDataPostValueFromMain$KtRecipe
- Find
MutableLiveData.postValue(...)calls inside coroutine main-thread contexts postValueexists for background-thread updaters — it marshals through the main looper and coalesces consecutive updates. When called from a place that already runs on the main thread (UI callbacks, view-model initialization,Dispatchers.Mainblocks), the coalescing is a footgun: intermediate values silently drop. UsesetValue/.value =on the main thread,postValueonly from background threads.
- Find
- org.openrewrite.kotlin.android.FindLocalBroadcastManager$KtRecipe
- Find
LocalBroadcastManager.getInstance(...)usage LocalBroadcastManagerwas deprecated in AndroidX 1.1 — the project effectively documents it as a global event bus, with all the ordering and lifetime trouble that implies. Migrate toLiveData,StateFlow, orSharedFlowfor in-process pub/sub.
- Find
- org.openrewrite.kotlin.android.FindManualDaggerProvision$KtRecipe
- Find
Dagger*Component.builder().build()patterns - Calls of the form
DaggerXComponent.builder().build()indicate the application is composing its dependency graph by hand. Hilt (@HiltAndroidApp/@AndroidEntryPoint) generates the same graph automatically and integrates with Compose, ViewModel, and WorkManager out of the box.
- Find
- org.openrewrite.kotlin.android.FindManualThreadingInActivity$KtRecipe
- Find
Thread \{ \}.start()calls insideActivity/Fragment - Hand-rolled
Thread \{ … \}.start()inside a UI component leaks across configuration changes (the thread outlives the activity) and has no story for cancellation. Migrate tolifecycleScope.launch(Dispatchers.IO) \{ … \}orviewModelScope.launch \{ … \}— both cancel when the lifecycle ends.
- Find
- org.openrewrite.kotlin.android.FindModeWorldReadable$KtRecipe
- Find
MODE_WORLD_READABLE/MODE_WORLD_WRITEABLEreferences - Both constants were deprecated in API 17 — they grant any app on the device read or write access to the file. Use a
FileProviderto share content URIs, or scope the file viaContext.getFilesDir()and expose it through your own content provider with explicit permissions.
- Find
- org.openrewrite.kotlin.android.FindMutableLiveDataAllocation$KtRecipe
- Find
MutableLiveDataallocations - In Kotlin Android code,
MutableStateFlow<T>is the modern equivalent. It integrates with structured concurrency, exposes the current value synchronously, and composes cleanly with Compose'scollectAsState/collectAsStateWithLifecycle. EachMutableLiveData()here is a candidate for migration.
- Find
- org.openrewrite.kotlin.android.FindObjectAnimator$KtRecipe
- Find
ObjectAnimator.ofInt/ofFloat(...)calls - Direct
ObjectAnimatoruse is a candidate for review — for Compose UIs the idiomatic replacement isanimate*AsState/Animatable, which integrate with recomposition and cancellation. For view-system code,SpringAnimation/PhysicsAnimationcover more interaction shapes than the time-basedObjectAnimator.
- Find
- org.openrewrite.kotlin.android.FindOnActivityResultOverride$KtRecipe
- Find
onActivityResultoverrides - Every override of
Activity.onActivityResult/Fragment.onActivityResultis half of the deprecatedstartActivityForResultpair. The new Activity Result APIs (registerForActivityResult(ActivityResultContracts.X) \{ … \}) deliver results to a lambda colocated with the launcher — the override goes away.
- Find
- org.openrewrite.kotlin.android.FindOnRequestPermissionsResultOverride$KtRecipe
- Find
onRequestPermissionsResultoverrides - Override of
Activity.onRequestPermissionsResult/Fragment.onRequestPermissionsResult— the result-callback half of the deprecatedrequestPermissions(...)pair. Replace with aregisterForActivityResult(ActivityResultContracts.RequestPermission)lambda.
- Find
- org.openrewrite.kotlin.android.FindParcelableJavaImpl$KtRecipe
- Find Kotlin classes implementing
Parcelablewithout@Parcelize - Manual
writeToParcel/CREATORimplementations are pure boilerplate that thekotlin-parcelizeplugin generates for any class annotated@Parcelize. Each manual implementation is a candidate for migration to the annotation.
- Find Kotlin classes implementing
- org.openrewrite.kotlin.android.FindPreferenceManagerGetDefaultSharedPreferences$KtRecipe
- Find
PreferenceManager.getDefaultSharedPreferences(...)calls android.preference.*(framework) was deprecated in API 29. AndroidXandroidx.preference.*is the supported path, and even there the modern shape for KV state is Jetpack DataStore (Preferences DataStorefor key/value,Proto DataStorefor typed records) — which works insuspendcontexts and survives process death without main-thread blocking.
- Find
- org.openrewrite.kotlin.android.FindPreferenceManagerImport$KtRecipe
- Find
android.preference.PreferenceManagerimports - The framework
android.preference.*package was deprecated in API 29. Move toandroidx.preference.*(drop-in replacement) or, for KV state, Jetpack DataStore — which composes with coroutines andFlowinstead of running on the main thread.
- Find
- org.openrewrite.kotlin.android.FindPublicMutableLiveDataProperty$KtRecipe
- Find public
MutableLiveDataproperties - Exposing
MutableLiveData<T>(orMutableStateFlow<T>) to observers lets them mutate the model from the consumer side. The convention is to keep the mutable handleprivateand expose a read-onlyLiveData<T>/StateFlow<T>getter, so the owner is the only one that can publish updates.
- Find public
- org.openrewrite.kotlin.android.FindRealmUsage$KtRecipe
- Find
Realm.getDefaultInstance()calls - Realm Java/Kotlin is in maintenance and was effectively superseded by Realm Kotlin (
io.realm.kotlin) and ultimately by MongoDB Atlas Device SDKs. EachRealm.getDefaultInstance()is a candidate for migration to Room + DataStore, or to the modern Realm Kotlin SDK.
- Find
- org.openrewrite.kotlin.android.FindRequestPermissions$KtRecipe
- Find direct
requestPermissions(...)calls - Calling
requestPermissions(...)directly couples the request to a screen and a request code that has to be matched inonRequestPermissionsResult. The modern shape isregisterForActivityResult(ActivityResultContracts.RequestPermission()) \{ granted -> … \}— the result lands in a lambda next to the launcher.
- Find direct
- org.openrewrite.kotlin.android.FindResourcesGetColor$KtRecipe
- Find
resources.getColor(...)(one-arg) calls Resources.getColor(int)was deprecated in API 23 — it doesn't take a theme. Replace withContextCompat.getColor(context, id), which threads the theme through and respects?attrreferences.
- Find
- org.openrewrite.kotlin.android.FindResourcesGetDrawable$KtRecipe
- Find
resources.getDrawable(...)(one-arg) calls Resources.getDrawable(int)was deprecated in API 22 — it doesn't take a theme. Replace withResourcesCompat.getDrawable(resources, id, theme)to render themed drawables consistently across API levels.
- Find
- org.openrewrite.kotlin.android.FindRoomQueryWithoutLiveDataOrFlow$KtRecipe
- Find
@QueryDAO methods returning a synchronous result - A non-suspend
@QueryreturningList<X>,X?, or a scalar runs the DB query on the calling thread — by default Room throwsIllegalStateExceptionif that's the main thread. Mark the functionsuspend(single-shot) or returnFlow<...>/LiveData<...>(observable) so Room can dispatch the query off the main thread.
- Find
- org.openrewrite.kotlin.android.FindRunOnUiThread$KtRecipe
- Find
Activity.runOnUiThread \{ \}/View.post \{ \}calls - Hand-rolled main-thread dispatch (
runOnUiThread,view.post) was the pre-coroutine pattern for crossing thread boundaries from a background worker. In Kotlin, preferwithContext(Dispatchers.Main) \{ … \}— it composes with structured cancellation and surfaces in the call site's coroutine context.
- Find
- org.openrewrite.kotlin.android.FindRuntimeExecInAndroid$KtRecipe
- Find
Runtime.exec(...)/ProcessBuilder.start()calls - Forking a process from an Android app is almost never the right shape — the system imposes strict app-sandbox limits (no
su, no arbitrary binaries) and process lifetime is unrelated to the activity that spawned it. Audit each call site againstWorkManager, foreground services, or — if you genuinely need shell tools —java.lang.ProcessBuilderwith explicit lifecycle management.
- Find
- org.openrewrite.kotlin.android.FindRxJavaImports$KtRecipe
- Find
io.reactivex.*imports - RxJava is in maintenance and Kotlin's idiomatic story is coroutines +
Flow. Each import is a candidate for migration tokotlinx.coroutines.flow.*(or, at the boundary,kotlinx-coroutines-rx3/kotlinx-coroutines-rx2adapters during incremental migration).
- Find
- org.openrewrite.kotlin.android.FindSerializableUsage$KtRecipe
- Find Kotlin classes implementing
java.io.Serializable java.io.Serializableis reflection-based and slow on Android — it allocates substantially more thanParcelableand pulls in field-by-field reflection at deserialize time. For inter-component transport, prefer@Parcelize(kotlin-parcelize) orkotlinx.serialization.
- Find Kotlin classes implementing
- org.openrewrite.kotlin.android.FindSharedPreferencesCommit$KtRecipe
- Find
SharedPreferences.Editor.commit()calls commit()writes to disk on the calling thread (often the main thread, where it can drop a frame).apply()writes asynchronously and atomically, returning immediately — use it unless you specifically need the boolean result on the spot.
- Find
- org.openrewrite.kotlin.android.FindSharedPreferencesEdit$KtRecipe
- Find
sharedPrefs.edit()calls - Raw
edit()calls predate AndroidXSharedPreferences.edit \{ … \}, the Kotlin extension that handlesapply/commitfor the caller. Replace eachprefs.edit().put*(...).apply()chain withprefs.edit \{ put*(...) \}— same disk write, less ceremony, and harder to drop the apply by accident.
- Find
- org.openrewrite.kotlin.android.FindStartActivityForResult$KtRecipe
- Find
startActivityForResultcalls startActivityForResultwas deprecated in AndroidX Activity 1.2 / Fragment 1.3 in favor of the Activity Result APIs (registerForActivityResult(ActivityResultContracts.X) \{ result -> … \}). The new API survives process death, decouples the launcher from the lifecycle owner, and removes the per-screenonActivityResultswitch.
- Find
- org.openrewrite.kotlin.android.FindStartService$KtRecipe
- Find
startService(...)calls - On API 26+ background apps cannot call
startService(...)— the system throwsIllegalStateException. For services that must run while the app is backgrounded, callContextCompat.startForegroundService(context, intent)and post a notification within five seconds. For one-shot work, useWorkManagerinstead.
- Find
- org.openrewrite.kotlin.android.FindSystemOutInAndroid$KtRecipe
- Find
System.out.println(...)calls System.outon Android writes to logcat under a default tag that's easy to lose. UseLog.d/Log.ifor tagged output (or, better, Timber) — both route through Android's logging pipeline with filterable tags.
- Find
- org.openrewrite.kotlin.android.FindVibratorVibrateLong$KtRecipe
- Find
Vibrator.vibrate(long)(one-arg) calls - The single-
longVibrator.vibrate(ms)was deprecated in API 26. UseVibrator.vibrate(VibrationEffect.createOneShot(...))(orVibratorManageron API 31+) — both let the platform pick the appropriate amplitude.
- Find
- org.openrewrite.kotlin.android.FindWebViewJavaScriptEnabled$KtRecipe
- Find
WebSettings.setJavaScriptEnabled(true)calls - Enabling JavaScript in a WebView lets the loaded page run arbitrary script in your app's context. For first-party content this is often fine; for any third-party content it's a critical security boundary. Each match is worth reviewing alongside the trust model of the loaded URLs.
- Find
- org.openrewrite.kotlin.android.FindWebViewLoadUrl$KtRecipe
- Find
WebView.loadUrl(...)calls - Each
WebView.loadUrl(...)is worth a security review: arbitrary http://-scheme URLs bypass the system browser and inherit the WebView's privileges (cookies, JS bridges). For untrusted content preferCustomTabsIntent(Chrome Custom Tabs) — better security, better UX, no JS bridge.
- Find
- org.openrewrite.kotlin.bestpractices.BestPractices$KtRecipe
- Apply Kotlin best-practice idioms
- Opinionated bundle of every best-practice recipe in this module: collection / string round-trip collapses, stdlib accessor swaps, and a broad set of search-only flags covering class structure, function declarations, string construction, Boolean conditionals, lambdas, and exception handling. For diff-only output, use
ImproveKotlinBestPracticesinstead.
- org.openrewrite.kotlin.bestpractices.CollapseRedundantConversions$KtRecipe
- Collapse redundant collection / string conversions
- Drops needless
toList()/toMutableList()/toSet()/toTypedArray()round-trips andtrimStart().trimEnd()-style chains that allocate one or more intermediate copies. The replacement performs the same conversion in one pass.
- org.openrewrite.kotlin.bestpractices.FindAbstractClassWithoutMembers$KtRecipe
- Find
abstract classdeclarations without abstract members - An
abstract classwith no abstract members and no state offers nothing overinterface— andinterfacecomposes better (multiple inheritance, no constructor coupling). If the class is being used as a marker, considersealed interfacefor stronger exhaustiveness checks.
- Find
- org.openrewrite.kotlin.bestpractices.FindAlsoPrintln$KtRecipe
- Find
.also \{ println(it) \}debug patterns .also \{ println(it) \}is a side-channel print left over from debugging. It survives compilation, runs in production, and is invisible at the call site — remove it or route the value through a logger.
- Find
- org.openrewrite.kotlin.bestpractices.FindAlsoWithEmptyBody$KtRecipe
- Find
x.also \{ \}calls with an empty body x.also \{ \}with an empty block is a no-op that returnsx. Drop the call — it adds an allocation for the captured lambda and obscures the value flow.
- Find
- org.openrewrite.kotlin.bestpractices.FindAnonymousObjectSingleMethod$KtRecipe
- Find anonymous
object : Interface \{ override fun … \}with a single override - An anonymous object that implements one interface with a single function override is the canonical SAM-conversion target. If the interface is declared
fun interface I \{ … \}, the call site collapses to a lambda.
- Find anonymous
- org.openrewrite.kotlin.bestpractices.FindBareExceptionThrow$KtRecipe
- Find
throw Exception("…")calls - Throwing bare
Exception(orRuntimeException) loses information that a more specific type would carry. PreferIllegalArgumentException(bad input),IllegalStateException(object in wrong state), or a domain-specific subclass.
- Find
- org.openrewrite.kotlin.bestpractices.FindBareRuntimeExceptionThrow$KtRecipe
- Find
throw RuntimeException("…")calls - Same family as
throw Exception("...")— flag for replacement withIllegalArgumentException/IllegalStateException/domain-specific subclass.
- Find
- org.openrewrite.kotlin.bestpractices.FindBestPracticeCandidates$KtRecipe
- Find best-practice candidates
- Search-only bundle: flags places where a more idiomatic Kotlin spelling is available. Each match shows up as a
SearchResultfor review; nothing is rewritten automatically because the migration is a judgment call.
- org.openrewrite.kotlin.bestpractices.FindBooleanConditionalSmells$KtRecipe
- Find Boolean-conditional smells
if (x) true else false, its inverse,!x.isEmpty()/!x.isBlank()family negations,if (x == null) null else x.foo(),if (x != null) x.foo()patterns, andif (return …) else …early-return ladders — each is the long form of a single Kotlin operator or method.
- org.openrewrite.kotlin.bestpractices.FindBooleanLiteralReturnType$KtRecipe
- Find
fun f(): Boolean = true|falseliteral-returning functions - A function whose body is literally
trueorfalseis rarely the right shape — either the predicate was a stub left in by mistake, or the value is genuinely constant and should be aconst val. Either way, surface the call site for human review.
- Find
- org.openrewrite.kotlin.bestpractices.FindCatchReturningNull$KtRecipe
- Find
try \{ … \} catch (e: Exception) \{ null \}patterns - Swallowing every exception into
nulldiscards diagnostic information and conflates 'no value' with 'I lost the cause'.runCatching \{ \}returns aResult<T>whosegetOrNull()matches this shape, andonFailure \{ \}keeps a hook for diagnostics.
- Find
- org.openrewrite.kotlin.bestpractices.FindClassExtendsAny$KtRecipe
- Find
class Foo : Any()declarations - Every class implicitly extends
Any— writing it explicitly only adds noise and a redundant supertype clause.
- Find
- org.openrewrite.kotlin.bestpractices.FindClassStructureSmells$KtRecipe
- Find class-declaration smells
- Search-only bundle: flags class-level structural smells (empty companion, empty class body, redundant
: Any(), manualtoString/equals/hashCodetrio, named companion of constants, multiple secondary constructors, sealed-class-without-state, marker-object-without-data, empty init, all-val classes that could bedata class, mutabledata class/object state, abstract classes without abstract members, andopenclasses with no overridable members).
- org.openrewrite.kotlin.bestpractices.FindClassWithoutDataAnnotation$KtRecipe
- Find classes that could be
data class - A class whose only members are
valconstructor parameters — no methods, no init, no extra properties — is the canonical shapedata classexists for. AddingdatasynthesizestoString/equals/hashCode/copy/componentNwithout changing any other semantics.
- Find classes that could be
- org.openrewrite.kotlin.bestpractices.FindCompareToInsteadOfOperator$KtRecipe
- Find
x.compareTo(y) <op> 0patterns x.compareTo(y) > 0is the long form ofx > yfor anyComparable<T>— and>/</>=/<=are defined onComparableto use exactly that call. The operator form reads as the comparison it is, and the bytecode emitted is identical.
- Find
- org.openrewrite.kotlin.bestpractices.FindDataClassWithMutableProperty$KtRecipe
- Find
data classdeclarations withvarproperties data classgeneratesequalsandhashCodeover the primary-constructor properties. Mutating avarproperty after the instance is stored in a hash-based collection breaks the invariant — the entry can no longer be found by lookup. Preferval; if mutation is needed, model it throughcopy(...).
- Find
- org.openrewrite.kotlin.bestpractices.FindDataObjectCandidates$KtRecipe
- Find marker
objectdeclarations that could bedata object - A bare
object Foodeclaration with no body inheritsAny.toString(), which prints asFoo$Companion@<hash>-style identity strings.data object Foo(Kotlin 1.9+) generates a readabletoString("Foo"),equals(identity), andhashCode— preferred for marker singletons used inwhenexhaustiveness checks and serialization.
- Find marker
- org.openrewrite.kotlin.bestpractices.FindDoubleBangChain$KtRecipe
- Find chained
!!assertions in a single expression x!!.y!!.zchains multiple!!assertions in one expression. Each one is a separate NPE risk with no diagnostic. Either the intermediate values are non-null (and the assertions can be dropped) or the chain should be modeled with?.let \{ \}to surface the absent case explicitly.
- Find chained
- org.openrewrite.kotlin.bestpractices.FindElseAfterReturn$KtRecipe
- Find
if (x) \{ return … \} else \{ … \}patterns - When the
ifbranch returns, theelseis unreachable as a fall-through guard — the body after theelsecan be moved out of theelseblock, which makes the early-return shape obvious to readers.
- Find
- org.openrewrite.kotlin.bestpractices.FindEmptyClassBody$KtRecipe
- Find
class Foo \{\}declarations with an empty body - An empty class body
\{\}adds no information. Kotlin allows the body to be omitted entirely:class Foois the same declaration without the redundant braces.
- Find
- org.openrewrite.kotlin.bestpractices.FindEmptyCompanionObject$KtRecipe
- Find empty
companion objectdeclarations - A
companion object \{\}with no members generates a syntheticCompanionholder class that's never used. Remove it — Kotlin doesn't require an empty companion object for any feature.
- Find empty
- org.openrewrite.kotlin.bestpractices.FindEmptyInitBlock$KtRecipe
- Find empty
init \{ \}blocks - An empty
init \{\}block is a no-op. Remove it — every empty initializer is a place a future reader pauses before noticing it does nothing.
- Find empty
- org.openrewrite.kotlin.bestpractices.FindEqualitySmells$KtRecipe
- Find equality / comparison smells
===/!==referential checks (usually==is meant),x == true|falselonghand for Boolean, andx.compareTo(y) > 0calls that should use the comparison operator directly.
- org.openrewrite.kotlin.bestpractices.FindEqualsToBooleanLiteral$KtRecipe
- Find
b == true/b == falsecomparisons - When
bisBoolean,b == trueis justbandb == falseis!b. The longhand only obscures intent. ForBoolean?the longhand is meaningful — it returnsfalsefornullrather than failing on!!— so leave those alone; flag only the comparison and let the reviewer decide.
- Find
- org.openrewrite.kotlin.bestpractices.FindExceptionHandlingSmells$KtRecipe
- Find exception-handling smells
Throwable.printStackTrace()(bypasses the logger), barethrow Exception("…")/throw RuntimeException("…")allocations (lose type information), andtry \{ \} catch (e: Exception) \{ null \}patterns (collapsible torunCatching \{ \}.getOrNull()).
- org.openrewrite.kotlin.bestpractices.FindExplicitUnitReturnType$KtRecipe
- Find functions with explicit
: Unitreturn type - Kotlin functions that don't declare a return type return
Unitby convention. Writing: Unitexplicitly adds noise — drop it unless the explicit form aids a generated API surface (e.g.@JvmOverloads).
- Find functions with explicit
- org.openrewrite.kotlin.bestpractices.FindForEachAddCandidate$KtRecipe
- Find
xs.forEach \{ ys.add(it) \}patterns xs.forEach \{ ys.add(it) \}is the loop-form ofys.addAll(xs). The bulk operation is a single method call and uses the most efficient copy strategy the receiver supports.
- Find
- org.openrewrite.kotlin.bestpractices.FindForEachPrintln$KtRecipe
- Find
forEach \{ println(it) \}patterns forEach \{ println(it) \}is the loop-formfor (x in xs) println(x)— verify whether the print is debug-only. If it is intended output, considerjoinToString("\n").let(::println)to write the whole thing in one syscall.
- Find
- org.openrewrite.kotlin.bestpractices.FindForceUnwrapInLet$KtRecipe
- Find
!!inside a?.let \{ \}body x?.let \{ it!! \}(orit.foo()!!) is internally inconsistent: the safe-call entry already guards null, so the!!onitcan never trigger. Drop the!!— the lambda body has a non-null receiver by construction.
- Find
- org.openrewrite.kotlin.bestpractices.FindFunctionDeclarationSmells$KtRecipe
- Find function-declaration smells
- Search-only bundle: explicit
: Unit/: Nothingreturn type, block bodies that are a singlereturn expr, literal-Boolean-returning functions,Pair/Triplereturns that could be data classes, default-before-required parameters,suspend fundeclarations returningJob/Deferred, and explicitreturn Unitstatements.
- org.openrewrite.kotlin.bestpractices.FindFunctionReturningPair$KtRecipe
- Find functions returning
Pair<A, B> - A function returning
Pair<A, B>forces every caller to remember which side is which. A smalldata class Result(val a: A, val b: B)documents the role of each component and gainscomponentN()/copy()for free.
- Find functions returning
- org.openrewrite.kotlin.bestpractices.FindFunctionReturningTriple$KtRecipe
- Find functions returning
Triple<A, B, C> - Same shape as the
Paircase but the readability cost compounds — three positional components is the limit where most readers stop guessing which is which. Replace with adata class.
- Find functions returning
- org.openrewrite.kotlin.bestpractices.FindIfNullElseExpression$KtRecipe
- Find
if (x == null) null else x.foo()patterns - An
if (x == null) null else x.foo()collapses to the safe-callx?.foo(). The safe-call is structurally null-aware — the longhand re-checks for null without surfacing the absent case in the type system.
- Find
- org.openrewrite.kotlin.bestpractices.FindIfReturnFalseElseTrue$KtRecipe
- Find
if (x) false else truepatterns if (x) false else trueis just!x. Replace the inverted Boolean conditional with the negation it already expresses.
- Find
- org.openrewrite.kotlin.bestpractices.FindIfReturnTrueElseFalse$KtRecipe
- Find
if (x) true else falsepatterns if (x) true else falseis justxafter Boolean simplification. The longhand only hides intent.
- Find
- org.openrewrite.kotlin.bestpractices.FindIsNotEmptyOnString$KtRecipe
- Find
x.isNotEmpty()onStringwhereisNotBlank()might be wanted String.isNotEmpty()returns true for whitespace-only strings. When the check exists to guard against missing user input,isNotBlank()is usually closer to the intent.
- Find
- org.openrewrite.kotlin.bestpractices.FindLambdaSmells$KtRecipe
- Find lambda / functional smells
- Redundant
map \{ it.toString() \}/forEach \{ it.toString() \}, debug-leftover.also \{ println(it) \}/forEach \{ println(it) \},xs.toList().forEach \{ \}over already-iterable receivers,.also \{ it.add(...) \}-built mutable collections, andforEach \{ ys.add(it) \}(useaddAll).
- org.openrewrite.kotlin.bestpractices.FindLazyWithoutMode$KtRecipe
- Find
lazy \{ \}calls without an explicitLazyThreadSafetyMode lazy \{ \}defaults toLazyThreadSafetyMode.SYNCHRONIZED— every read passes a synchronized check. For thread-confined state (UI, single-threaded actors),lazy(LazyThreadSafetyMode.NONE) \{ \}avoids the synchronization entirely.
- Find
- org.openrewrite.kotlin.bestpractices.FindLetForNotNullCheck$KtRecipe
- Find
if (x != null) x.foo()patterns if (x != null) \{ x.foo() \}is the long form ofx?.let \{ it.foo() \}— or, when only one call is needed andxis a local,x?.foo(). The safe-call form makes the null-aware path part of the type system rather than a separate Boolean check.
- Find
- org.openrewrite.kotlin.bestpractices.FindManualToStringEqualsHashCode$KtRecipe
- Find classes with manual
toString/equals/hashCodeoverrides - A class that overrides all three of
toString,equals, andhashCodeover its own fields is the canonical shapedata classexists for. Migrate todata class C(val a: A, …)to delete the boilerplate and gaincopy()pluscomponentN()for free.
- Find classes with manual
- org.openrewrite.kotlin.bestpractices.FindMultipleSecondaryConstructors$KtRecipe
- Find classes with multiple overloaded secondary constructors
- Two or more secondary constructors with different arities almost always collapse into a single primary constructor with default arguments. The default-arg form composes with named arguments and
@JvmOverloadsfor cross-language interop.
- org.openrewrite.kotlin.bestpractices.FindMutableListAlsoAdd$KtRecipe
- Find
mutableListOf<T>().also \{ it.add(x) \}patterns - Building a list through
mutableListOf<T>().also \{ it.add(...) \}is the side-channel form ofbuildList \{ add(...) \}(or justmutableListOf(x)if every element is known up front). The builder form makes intent explicit.
- Find
- org.openrewrite.kotlin.bestpractices.FindMutableMapAlsoPut$KtRecipe
- Find
mutableMapOf<K,V>().also \{ it.put(...) \}patterns - Same shape as
mutableListOf().also \{ it.add(...) \}for maps. The builder form (buildMap \{ put(...) \}) makes the entries visible without the side-channelit.put.
- Find
- org.openrewrite.kotlin.bestpractices.FindMutableSetAlsoAdd$KtRecipe
- Find
mutableSetOf<T>().also \{ it.add(x) \}patterns - Same shape as the
mutableListOfvariant — usebuildSet \{ add(...) \}for the same readability gain.
- Find
- org.openrewrite.kotlin.bestpractices.FindNamedCompanionObjectOfConstants$KtRecipe
- Find named
companion object Constantspatterns - A
companion object Constants \{ const val X = ... \}adds a named singleton to hold what are essentially file-level constants. Promote the constants to top-levelconst vals — they read the same and avoid the synthetic holder class.
- Find named
- org.openrewrite.kotlin.bestpractices.FindNegatedIsBlank$KtRecipe
- Find
!x.isBlank()calls - Kotlin's
String.isNotBlank()is the direct positive form. The negated-blank check reads the same value without the leading!.
- Find
- org.openrewrite.kotlin.bestpractices.FindNegatedIsEmpty$KtRecipe
- Find
!x.isEmpty()calls - Kotlin ships
isNotEmpty()directly onString,Collection, andMap. The negation reads top-down without re-parsing the!.
- Find
- org.openrewrite.kotlin.bestpractices.FindNegatedIsNotBlank$KtRecipe
- Find
!x.isNotBlank()calls !x.isNotBlank()is the long form ofx.isBlank().
- Find
- org.openrewrite.kotlin.bestpractices.FindNegatedIsNotEmpty$KtRecipe
- Find
!x.isNotEmpty()calls !x.isNotEmpty()is the long form ofx.isEmpty(). Use the direct positive call.
- Find
- org.openrewrite.kotlin.bestpractices.FindObjectWithMutableState$KtRecipe
- Find
objectdeclarations withvarproperties - An
objectis a singleton — itsvarproperties are shared global mutable state. Concurrent reads/writes race without synchronization, and the value can change in surprising ways across modules.
- Find
- org.openrewrite.kotlin.bestpractices.FindOpenClassWithoutOverrides$KtRecipe
- Find
open classdeclarations without overridable members - The
openmodifier on a class only matters if subclasses override something. A bareopen class Foo(or one whose members are allfinal) signals an intent — "this class is meant to be extended" — that the type system can't actually enforce. Either declare specific membersopen(and drop the class-levelopen) or remove the modifier entirely.
- Find
- org.openrewrite.kotlin.bestpractices.FindRedundantReturnUnit$KtRecipe
- Find
return Unit/return kotlin.Unitstatements - Functions that return
Unitdon't need an explicit return at all —return(no expression) or simply falling off the end is the conventional shape. Writingreturn Unitrepeats the implicit value.
- Find
- org.openrewrite.kotlin.bestpractices.FindRedundantToStringInForEach$KtRecipe
- Find
forEach \{ it.toString() \}patterns it.toString()inside aforEachevaluates the call but discards the result — equivalent toforEach \{\}. Either the side effect ontoString()is the goal (very unusual) or the call is dead code.
- Find
- org.openrewrite.kotlin.bestpractices.FindRedundantToStringInMap$KtRecipe
- Find
map \{ it.toString() \}/map \{ x -> x.toString() \}patterns - If the producer already returns a type whose
toString()is the desired representation, themapis a no-op. If the goal is to materialize theStrings up-front,joinToString()/toString()on the collection is usually a better fit.
- Find
- org.openrewrite.kotlin.bestpractices.FindReferentialEquality$KtRecipe
- Find
===/!==referential-equality comparisons - Kotlin's
===checks reference identity, ignoringequals. Fordata classand other value-like types this almost always wants==instead. Flag every referential check for review — true reference comparisons (e.g. sentinelAnyobjects) are legitimate but rare.
- Find
- org.openrewrite.kotlin.bestpractices.FindReturnTypeNothing$KtRecipe
- Find functions declared with
: Nothingreturn type Nothingmeans 'this function never returns normally' — the body mustthrow, loop forever, or call anotherNothing-returning function. Flag for review: if the body actually does return, the type is wrong; if it always throws, the call sites can rely on Kotlin's exhaustiveness checks.
- Find functions declared with
- org.openrewrite.kotlin.bestpractices.FindRunWithEmptyBody$KtRecipe
- Find
run \{ \}calls with an empty body run \{ \}is a scope function for evaluating a block as an expression with an implicitthisreceiver. If the block is empty, the call evaluates toUnitand does nothing — drop it.
- Find
- org.openrewrite.kotlin.bestpractices.FindScopeFunctionSmells$KtRecipe
- Find scope-function smells
run \{ \}with empty or no-thisbodies,also \{ \}with empty bodies, and?.let \{ … !! \}patterns where the null-guard and force-unwrap contradict each other.
- org.openrewrite.kotlin.bestpractices.FindSealedClassWithoutStateCandidates$KtRecipe
- Find
sealed classdeclarations that could besealed interface - A
sealed classwith no constructor parameters and no fields adds no expressive power oversealed interface. The interface form composes better (allows multiple inheritance, supportsdata objectdirect implementation, makes the no-state contract explicit).
- Find
- org.openrewrite.kotlin.bestpractices.FindSingleExpressionBodyCandidate$KtRecipe
- Find
fun foo(): T \{ return x \}block bodies - A function whose entire body is a single
return expris the canonical shape for Kotlin's single-expression-body syntax (fun foo(): T = expr). The expression form makes type inference more useful and removes one level of brace nesting.
- Find
- org.openrewrite.kotlin.bestpractices.FindStandaloneRunWithoutThis$KtRecipe
- Find top-level
run \{ … \}whose body never usesthis - Top-level
run \{ … \}(no receiver) is meaningful only when the block uses the implicitthisor executes multiple statements as an expression. If the body neither referencesthisnor depends on the scoping it provides, the wrapper just adds an unnecessary lambda allocation.
- Find top-level
- org.openrewrite.kotlin.bestpractices.FindStringConcatWithEmptyLeft$KtRecipe
- Find
"" + xpatterns - Prepending an empty
""is a Java idiom for forcing atoString()conversion. In Kotlin writex.toString()or the template"$x"for the same effect with explicit intent.
- Find
- org.openrewrite.kotlin.bestpractices.FindStringConcatWithEmptyRight$KtRecipe
- Find
x + ""patterns - Appending an empty
""is the inverse of the Java"" + xidiom. Usex.toString()or"$x"instead.
- Find
- org.openrewrite.kotlin.bestpractices.FindStringConstructionSmells$KtRecipe
- Find string-construction smells
- Trivial
String.format("%s", x)calls and"" + x/x + ""concatenations that read more clearly as Kotlin string templates.
- org.openrewrite.kotlin.bestpractices.FindStringFormatTrivial$KtRecipe
- Find trivial
String.format("%s", x)calls String.format("%s", x)is the long-hand for the Kotlin string template"$x". The template avoids the per-call format-string parse and reads as the thing it produces.
- Find trivial
- org.openrewrite.kotlin.bestpractices.FindSuspendFunctionReturningJob$KtRecipe
- Find
suspend fundeclarations returningJob/Deferred - A
suspend fun foo(): Jobis almost always a confusion of two patterns — either the function should suspend and return a value (drop theJob/Deferred), or it should launch and return the handle (dropsuspend, and callcoroutineScope \{ launch \{ … \} \}internally).
- Find
- org.openrewrite.kotlin.bestpractices.FindThrowablePrintStackTrace$KtRecipe
- Find
Throwable.printStackTrace()calls printStackTrace()writes the throwable straight toSystem.err, bypassing whatever structured logger the application uses. Route the throwable through a logger so log levels, MDCs, and sinks apply.
- Find
- org.openrewrite.kotlin.bestpractices.FindToListBeforeForEach$KtRecipe
- Find
xs.toList().forEach \{ … \}patterns Iterable.forEachalready iterates without materializing a list. The intermediatetoList()allocates a copy that's read once and discarded.
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenAsStatement$KtRecipe
- Find
when (x) \{ … \}used as a statement - A
whenused as a statement (its result is discarded) often obscures intent — either the writer expected an expression value or each branch is a side-effecting block that would read more clearly asif/else if. Flag for review.
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenSmells$KtRecipe
- Find
when-statement smells whenexpressions that read awkwardly: missingelse, single-branch, used as statement, with duplicate branch bodies that should collapse to comma-separated labels, or with a Boolean selector that should beif.
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenWithBooleanSubject$KtRecipe
- Find
when (b: Boolean)selectors when (b) \{ true -> … false -> … \}is the long form ofif (b) …— and thewhenreads as if it might gain a third branch, which Boolean cannot. Replace withif.
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenWithIdenticalBranches$KtRecipe
- Find
whenwith two or more branches having identical bodies when (x) \{ A -> f(); B -> f() \}repeats the same body for distinct labels — collapse to a single branch with comma-separated labels:A, B -> f().
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenWithSingleBranch$KtRecipe
- Find
when (x) \{ A -> … \}with a single branch - A single-branch
when (x) \{ A -> … \}is the long form ofif (x == A) …. Theifreads more directly and doesn't suggest the branch list will grow.
- Find
- org.openrewrite.kotlin.bestpractices.FindWhenWithoutElse$KtRecipe
- Find
when (x)expressions without anelsebranch - A
when (x)used as an expression requires exhaustiveness — without anelse, the compiler can only prove it for sealed/enumselectors. Used as a statement, the missingelseis a tripwire: any new variant silently falls through. Flag for review.
- Find
- org.openrewrite.kotlin.bestpractices.FindWildcardImport$KtRecipe
- Find wildcard
import a.b.*statements - Wildcard imports pull every public symbol from a package — they hide the dependency surface and make incremental compilation more conservative. Prefer explicit per-symbol imports.
- Find wildcard
- org.openrewrite.kotlin.bestpractices.ImproveKotlinBestPractices$KtRecipe
- Apply Kotlin best-practice rewrites
- Autofix-only best-practice bundle: collection / string round-trip collapses and stdlib accessor swaps. Excludes the search-only
Find*recipes so the run output is just diffs, not a flood of search results.
- org.openrewrite.kotlin.bestpractices.UseFirstForGetZero$KtRecipe
- Use
first()instead ofget(0) first()reads more naturally thanget(0)and gives the same compile-time bounds guarantees — both throwNoSuchElementException/IndexOutOfBoundsExceptionon an empty list.
- Use
- org.openrewrite.kotlin.bestpractices.UseLengthForCountNoPredicate$KtRecipe
- Use
lengthinstead ofString.count() String.count()walks every character and increments a counter.lengthreads the precomputed size off theStringheader.
- Use
- org.openrewrite.kotlin.bestpractices.UseSizeForCountNoPredicate$KtRecipe
- Use
sizeinstead ofCollection.count() Collection.count()without a predicate walks the iterable.sizereads the precomputed property onCollection.
- Use
- org.openrewrite.kotlin.bestpractices.UseStdlibAccessors$KtRecipe
- Use stdlib accessors for size / first
- Replaces walk-based accessors with their O(1) property/method equivalents —
count()/length/sizeandget(0)/first().
- org.openrewrite.kotlin.bestpractices.UseToListForToMutableListThenToList$KtRecipe
- Use
toList()instead oftoMutableList().toList() toMutableList()allocates a mutable copy, thentoList()copies it again to an immutable list.toList()directly does what's needed in one pass.
- Use
- org.openrewrite.kotlin.bestpractices.UseToListForToSetThenToList$KtRecipe
- Use
distinct()instead oftoSet().toList() distinct()returns aListwith duplicates removed in one pass.toSet().toList()allocates a set and then copies its contents into a list — two allocations to do the same job, and the order semantics differ subtly because hash-based sets don't preserve insertion order across all platforms.
- Use
- org.openrewrite.kotlin.bestpractices.UseToSetForDistinctThenToSet$KtRecipe
- Use
toSet()instead ofdistinct().toSet() toSet()deduplicates while building the set.distinct().toSet()allocates aListof distinct elements first, then copies into the set.
- Use
- org.openrewrite.kotlin.bestpractices.UseToSetForToListThenToSet$KtRecipe
- Use
toSet()instead oftoList().toSet() toSet()works on anyIterable. The intermediatetoList()just allocates a list that's immediately discarded.
- Use
- org.openrewrite.kotlin.bestpractices.UseToStringForStringToString$KtRecipe
- Drop redundant
String.toString() - Calling
toString()on a value that is already aStringis a no-op that compiles to a method call returning the same reference.
- Drop redundant
- org.openrewrite.kotlin.bestpractices.UseToTypedArrayForToListThenToTypedArray$KtRecipe
- Use
toTypedArray()instead oftoList().toTypedArray() toTypedArray()accepts anyCollection; the intermediatetoList()just allocates a list that's immediately discarded.
- Use
- org.openrewrite.kotlin.bestpractices.UseTrimForTrimEndThenTrimStart$KtRecipe
- Use
trim()instead oftrimEnd().trimStart() - Same as the inverse —
trim()strips both ends in one pass without the intermediateStringallocation.
- Use
- org.openrewrite.kotlin.bestpractices.UseTrimForTrimStartThenTrimEnd$KtRecipe
- Use
trim()instead oftrimStart().trimEnd() trim()strips whitespace from both ends in a single pass with no intermediate allocation.trimStart().trimEnd()builds a temporaryStringfor the left-trimmed value before the second pass.
- Use
- org.openrewrite.kotlin.compose.Compose$KtRecipe
- Find Compose stability and recomposition issues
- Search-only recipes that surface Jetpack Compose anti-patterns the Android docs and Compose stability guide call out: unstable parameter types, mutable classes annotated
@Stable/@Immutable, inlineModifierallocations, missingrememberkeys, effect-handler misuse, navigation inside composable bodies, single-child layout wrappers, lazy-list items without keys, and API-shape violations. Each match is aSearchResultfor human review — Compose remedies are judgement calls (hoist? wrap? annotate? split?) that depend on context outside any one expression. For diff-only output on the small autofix set, useImproveKotlinCompose.
- org.openrewrite.kotlin.compose.FindArrayParameterOnComposable$KtRecipe
- Find
Array<T>parameters on@Composablefunctions - JVM arrays are mutable references — Compose's stability inferrer marks an
Array<T>parameter unstable, forcing the composable to recompose every time the parent recomposes. PreferImmutableList<T>or a@Stablewrapper.
- Find
- org.openrewrite.kotlin.compose.FindBoxWithSingleChild$KtRecipe
- Find
Box \{ … \}with a single child - A
Box \{ OneChild() \}adds a layout node and a measurement pass for no compositional benefit — the child could be invoked directly with the sameModifier. Either pull the modifier onto the child or use the explicitBoxplacement APIs if alignment is doing real work.
- Find
- org.openrewrite.kotlin.compose.FindByRememberWithoutMutableState$KtRecipe
- Find
by remember \{ … \}delegations whose body isn't amutableStateOf by remember \{ … \}pairs with aMutableState<T>so the property delegates its read/write through the snapshot system. If theremember \{ \}body returns a plainT, thebydoes nothing useful — and is a strong hint the author forgot to wrap the value inmutableStateOf(...)orderivedStateOf \{ … \}.
- Find
- org.openrewrite.kotlin.compose.FindCanvasInComposable$KtRecipe
- Find
Canvas \{ … \}blocks inside a@Composable Canvas \{ drawXxx(...) \}re-runs the draw lambda on every recomposition; allocatingPaint,Path, orBrushinstances inside the lambda creates GC pressure that shows up as jank. Review for hoistable allocations (remember \{ Paint().apply \{ … \} \}) and fordrawWithCache \{ … \}opportunities.
- Find
- org.openrewrite.kotlin.compose.FindCardWithSingleChild$KtRecipe
- Find
Card \{ OneChild() \}patterns - A
Card \{ OneChild() \}allocates a layout node and an elevation surface for exactly one composable. If the child already styles itself (Modifier.background/Modifier.shadow), theCardis decorative duplication — pull the styling into the child'sModifierchain.
- Find
- org.openrewrite.kotlin.compose.FindColumnWithSingleChild$KtRecipe
- Find
Column \{ … \}with a single child - A
Column \{ OneChild() \}allocates a layout node and runs the column measurement to position exactly one child. Either remove the column or replace withBox(modifier = m)if the column'sverticalArrangementactually does work the parent isn't.
- Find
- org.openrewrite.kotlin.compose.FindComposableCallInNonComposableLambda$KtRecipe
- Find
@Composablecalls inside non-@Composablelambda parameters - A
@Composablefunction called from inside a non-Composable lambda (e.g., aforEach \{ \}) won't enter the composition tree correctly — the function executes but its emitted nodes don't get tracked for invalidation. Either move the call out of the lambda, or use a Compose-aware iterator (items(list) \{ … \}).
- Find
- org.openrewrite.kotlin.compose.FindComposableConventionSmells$KtRecipe
- Find Compose function-naming conventions
- Function-naming patterns the Compose API guide calls out: non-
@Composablefunctions that use composable APIs (remember/LaunchedEffect/rememberCoroutineScope) without the annotation.
- org.openrewrite.kotlin.compose.FindComposableLambdaParamMissingDefault$KtRecipe
- Find
@Composablefunctions with a content lambda parameter not defaulted to\{\} - By Material/Compose convention, content slot lambdas (
content: @Composable () -> Unit) default to\{\}so callers can compose the function without supplying a body when they only want the surrounding chrome. Flag content slots without defaults so the API gets the convention-conforming overload.
- Find
- org.openrewrite.kotlin.compose.FindComposableMissingModifierParam$KtRecipe
- Find
@Composablefunctions without aModifierparameter - The Compose API guideline says every composable that emits UI should accept a
Modifierparameter (namedmodifier, defaulted toModifier) so callers can size, layout, and decorate without subclassing. Flag composables that emit content but expose noModifierslot.
- Find
- org.openrewrite.kotlin.compose.FindComposableWithReturnValue$KtRecipe
- Find
@Composable fun … (): Xfunctions returning a non-Unitvalue - A
@Composablefunction that returns a value either emits UI as a side-effect (anti-pattern: invocation order is now load-bearing) or computes a derived value that should be a@ReadOnlyComposable. Mark explicit value-returning composables@ReadOnlyComposableso callers know they don't emit, or split into emitting-vs-returning pairs.
- Find
- org.openrewrite.kotlin.compose.FindComposeApiDesignIssues$KtRecipe
- Find Compose API design issues
- Composable functions that don't follow the Compose API guidelines: lowercase name (UI emitters should be
PascalCase), non-Unitreturn without@ReadOnlyComposable, content slot without a default\{\}, missingModifierparameter, and@Composableinvocations from non-Composable lambdas.
- org.openrewrite.kotlin.compose.FindComposeEffectIssues$KtRecipe
- Find Compose effect handler issues
- Effect handlers misused:
LaunchedEffect(Unit)/LaunchedEffect(true)placeholder keys,DisposableEffectlambdas missingonDispose \{ \},rememberCoroutineScope()mis-placed inside a lambda,LaunchedEffectinside loops, and side-effecting calls (logging,File) inside the composable body rather than an effect block.
- org.openrewrite.kotlin.compose.FindComposeLayoutIssues$KtRecipe
- Find Compose layout hierarchy smells
- Layout containers that exist for no compositional benefit:
Box/Column/Rowwrapping a single child, andLazyColumn/LazyRowitems missing a stablekey(which churns composition state on reorder).
- org.openrewrite.kotlin.compose.FindComposeModifierIssues$KtRecipe
- Find Compose
Modifiersmells - Modifier-chain shapes that allocate per recomposition (
Modifier.padding(...)inline), branch with structurally distinct chains (if (x) Modifier.foo() else Modifier), or stackfillMax/paddingin a layout-changing order. Each match needs the author's intent to fix correctly.
- Find Compose
- org.openrewrite.kotlin.compose.FindComposeNavigationIssues$KtRecipe
- Find Compose navigation / coroutine misuse
- Calls that need to be wrapped in an effect handler or event handler:
navController.navigate(...)from a composable body,scope.launch \{ … \}outsideLaunchedEffect, lifecycle-naivecollectAsStateinstead ofcollectAsStateWithLifecycle.
- org.openrewrite.kotlin.compose.FindComposeRememberIssues$KtRecipe
- Find Compose
rememberkey issues remember \{ … \}calls where the keys do not align with the values the block reads — keylessrememberthat captures changing variables, andremember \{ mutableStateOf(call()) \}candidates forderivedStateOf.
- Find Compose
- org.openrewrite.kotlin.compose.FindComposeStabilityIssues$KtRecipe
- Find Compose stability issues
- Surface declarations where Compose's stability inferrer will refuse to mark a parameter, property, or class as stable:
MutableList/MutableMap/MutableSetparameters, read-onlyListparameters,@Stable/@Immutableannotations applied to classes withvarfields, anddata classdeclarations holdingList<T>properties.
- org.openrewrite.kotlin.compose.FindComposeStateReadIssues$KtRecipe
- Find Compose state read/write issues
- Patterns where a
MutableState/Stateis read or constructed in a way that loses the snapshot value: explicit.valuereads, baremutableStateOfwithoutremember, class-field state ownership, missingderivedStateOf, transient collection allocations.
- org.openrewrite.kotlin.compose.FindComposeViewModelIssues$KtRecipe
- Find Compose ViewModel wiring issues
- ViewModel acquisition inside composables —
hiltViewModel<X>()andviewModel<X>()— and StateFlow exposure:MutableStateFlowwithout anasStateFlow()read-only view.
- org.openrewrite.kotlin.compose.FindConditionalModifier$KtRecipe
- Find
if (x) Modifier.foo() else Modifierpatterns if (cond) Modifier.foo() else Modifierreturns two structurally differentModifierchains, breaking memoization on the consumer. UseModifier.then(if (cond) Modifier.foo() else Modifier)orModifier.composed \{ if (cond) padding(8.dp) else this \}so the consumer sees a single stable reference.
- Find
- org.openrewrite.kotlin.compose.FindContextParameterOnComposable$KtRecipe
- Find
android.content.Contextparameters on@Composablefunctions - Passing a
Contextinto a composable couples it to the activity instance and makes the function harder to preview/test. UseLocalContext.currentinside the composable instead — it works through the composition tree and is preview-safe.
- Find
- org.openrewrite.kotlin.compose.FindCoroutineLaunchInComposableBody$KtRecipe
- Find
scope.launch \{ … \}calls inside a@Composablebody scope.launch \{ … \}in a@Composablebody starts a new coroutine on every recomposition — none of them get cancelled until the scope dies. UseLaunchedEffect(key) \{ … \}, which is automatically cancelled and restarted by the composition's lifecycle.
- Find
- org.openrewrite.kotlin.compose.FindCoroutineLaunchInsideLaunchedEffectInLoop$KtRecipe
- Find
for (...) \{ LaunchedEffect(...) \{ … \} \}patterns - A
LaunchedEffectinside a loop creates a separate coroutine per iteration. That is rarely the intended structure — it is usually a mis-placement of effect logic. Prefer a singleLaunchedEffect(keys = arrayOf(...)) \{ for (...) \{ … \} \}or restructure the loop to live inside the effect.
- Find
- org.openrewrite.kotlin.compose.FindDataClassWithListProperty$KtRecipe
- Find
data classdeclarations withList<T>properties - When a
data classis passed to a@Composableand one of its properties is akotlin.collections.List<T>, Compose marks the entire class unstable. Wrap the list inImmutableList<T>fromkotlinx.collections.immutable(or split the list out and remember it separately) so stability inference can prove the holder is@Stable.
- Find
- org.openrewrite.kotlin.compose.FindDerivedStateOfCandidate$KtRecipe
- Find
remember \{ mutableStateOf(expensiveCall()) \}patterns remember \{ mutableStateOf(expensiveCall()) \}evaluates the expression once and stores it — but if the expression depends on snapshot state, you want it to recompute when that state changes.derivedStateOf \{ expensiveCall() \}(inside aremember \{ \}) recomputes lazily only when its tracked reads invalidate, instead of either staling out or recomputing on every recomposition.
- Find
- org.openrewrite.kotlin.compose.FindDisposableEffectMissingOnDispose$KtRecipe
- Find
DisposableEffect \{ … \}blocks missing anonDispose \{ \} DisposableEffect's contract is to return aDisposableEffectResultfromonDispose \{ … \}— without it, the compiler should reject the block, but easy mistakes (earlyreturn, wrong receiver) silently bypass cleanup. Confirm the final statement of everyDisposableEffectlambda is anonDispose \{ \}call so resources are released on leave-the-composition.
- Find
- org.openrewrite.kotlin.compose.FindDpAllocationInComposableBody$KtRecipe
- Find
n.dpallocations inside a@Composablebody Dpis an inline value class — most.dpaccesses compile to a primitive. But certain platforms (older Kotlin, KMP non-JVM targets) box the value. In hot composables, prefer hoistingprivate val padding = 8.dpto file scope so the conversion runs once.
- Find
- org.openrewrite.kotlin.compose.FindFlowCollectAsState$KtRecipe
- Find
Flow.collectAsState()calls — prefercollectAsStateWithLifecycle() collectAsState()keeps collecting whenever the composition is alive, including while the host activity is stopped.collectAsStateWithLifecycle()(fromandroidx.lifecycle:lifecycle-runtime-compose) ties collection to the lifecycle owner, dropping subscription while in the background and freeing the upstreamFlowfrom doing work nothing will display.
- Find
- org.openrewrite.kotlin.compose.FindFlowParameterOnComposable$KtRecipe
- Find
Flow<T>/StateFlow<T>parameters on@Composablefunctions - Passing a
Flow<T>into a@Composableshifts collection from aLaunchedEffectto the consumer — but if the caller re-creates theFlowper recomposition, collection restarts every time. Prefer collecting at the call site and passing the resultingState<T>(orTdirectly).
- Find
- org.openrewrite.kotlin.compose.FindHardcodedColor$KtRecipe
- Find
Color(0xFF…)/Color.Xliterals inside@Composable - Hardcoded
Colorliterals inside a composable bypassMaterialTheme.colorScheme.X, breaking light/dark theme adaptation and theming overrides. Move the literal into the theme (aColorSchemeextension or a top-level theme val) and read it viaMaterialTheme.colorSchemeat the call site.
- Find
- org.openrewrite.kotlin.compose.FindHardcodedDesignTokens$KtRecipe
- Find hardcoded color literals inside
@Composable Color(0xFF…)literals inside composables break theming and accessibility (light/dark). Hoist intoMaterialTheme.colorScheme.*.
- Find hardcoded color literals inside
- org.openrewrite.kotlin.compose.FindHiltViewModelInComposable$KtRecipe
- Find
hiltViewModel<X>()calls inside@Composable hiltViewModel<MyViewModel>()inside a@Composablecouples the screen-level dependency injection to that composable. That is the recommended pattern at navigation entry points, but flagged for review when the same ViewModel is injected from multiple composables (you'll get distinct instances per nav graph entry).
- Find
- org.openrewrite.kotlin.compose.FindImmutableAnnotationOnMutableClass$KtRecipe
- Find
@Immutableon classes withvarproperties @Immutableis the stronger sibling of@Stable: it promises that all public properties are observably unchangeable after construction. Avarfield is by definition observably changeable — Compose will assume it can skip recompositions safely and miss updates. Drop the annotation or convert the property toval(and a private backing var if needed).
- Find
- org.openrewrite.kotlin.compose.FindInlineModifierConstruction$KtRecipe
- Find
Modifier.xxx()allocations inside a@Composablebody - Each
Modifier.padding(...)-style chain allocates a freshModifierinstance, and a freshModifierdefeats Compose's structural-equality skip — every recomposition allocates again and forces re-layout. Hoist the modifier into aremember \{ Modifier… \}, accept aModifierparameter from the caller, or build static modifiers as top-level vals.
- Find
- org.openrewrite.kotlin.compose.FindLambdaAsComposableParamWithoutNoinline$KtRecipe
- Find lambda parameters on
@Composablefunctions - Function-typed parameters are unstable from Compose's stability inferrer perspective unless the lambda reference is stable (e.g., function reference or
rememberd). For frequently-recomposed composables, accept a(T) -> Unitand document caller responsibility, or fold the callback into a stable holder. Flag for review when the API is performance-sensitive.
- Find lambda parameters on
- org.openrewrite.kotlin.compose.FindLambdaCapturingMutableStateInItems$KtRecipe
- Find lazy-list
items(...) \{ … \}content lambdas that read aMutableStatefrom the enclosing scope - When a
LazyColumn/LazyRowcontent lambda reads aMutableState/Statefrom the enclosing scope, every change to that state invalidates the entire item composition. Hoist the state into a per-itemremember, or read it inside a child composable so only the affected item recomposes.
- Find lazy-list
- org.openrewrite.kotlin.compose.FindLaunchedEffectMultipleSuspendCalls$KtRecipe
- Find
LaunchedEffectbodies with several distinct suspend calls - A
LaunchedEffectlambda that issues several distinct top-level suspend calls is usually doing two things: a long-running collector plus an unrelated kickoff. Split them into separateLaunchedEffects keyed independently so canceling one doesn't cancel the other on key changes.
- Find
- org.openrewrite.kotlin.compose.FindLaunchedEffectWithTrueKey$KtRecipe
- Find
LaunchedEffect(true) \{ … \}blocks LaunchedEffect(true)(or any literaltrue/falsekey) is a one-shot effect dressed up to look like it has a key. It is structurally identical toLaunchedEffect(Unit)but reads as if the author meant to pass a variable. Switch toUnitfor clarity or pass the real dependency.
- Find
- org.openrewrite.kotlin.compose.FindLaunchedEffectWithUnitKey$KtRecipe
- Find
LaunchedEffect(Unit) \{ … \}blocks LaunchedEffect(Unit) \{ … \}runs exactly once per composition lifetime — that's intentional for one-shot startup work, but it is also the easiest spelling when the author wanted lifecycle-aware re-launch on a real key. ConfirmUnitwas intentional and not a placeholder for the actual dependencies the effect reads.
- Find
- org.openrewrite.kotlin.compose.FindLaunchedEffectWithoutKey$KtRecipe
- Find
LaunchedEffect \{ … \}calls with no key argument LaunchedEffectalways takes at least one key — without one the call is a compile error (or silently rebound to a(suspend () -> Unit)overload in stubbed builds). Confirm a key is supplied;LaunchedEffect(Unit) \{ … \}is the canonical one-shot spelling.
- Find
- org.openrewrite.kotlin.compose.FindLazyColumnDirectCall$KtRecipe
- Find
LazyColumn \{ … \}calls — verify items use stable keys - A
LazyColumn \{ items(...) \{ … \} \}whose inneritemscall has nokey = \{ … \}recomposes every visible row on every reorder/insertion. Audit the call to add a stable key.
- Find
- org.openrewrite.kotlin.compose.FindLazyListItemMissingKey$KtRecipe
- Find
LazyColumn/LazyRowitems(...)calls missing akey = \{ … \}argument - Without a stable
key,LazyColumn/LazyRowindexes items by position. Inserting an item shifts every following index and Compose has to recompose every visible child, recreating their state. A stablekey(typically an id) lets Compose preserve composition state across reorderings and animations.
- Find
- org.openrewrite.kotlin.compose.FindLazyRowDirectCall$KtRecipe
- Find
LazyRow \{ … \}calls — verify items use stable keys - A
LazyRow \{ items(...) \{ … \} \}whose inneritemscall has nokey = \{ … \}recomposes every visible cell on every reorder. Audit the call to add a stable key.
- Find
- org.openrewrite.kotlin.compose.FindLazyVerticalGridDirectCall$KtRecipe
- Find
LazyVerticalGrid \{ … \}calls — verify items use stable keys - A
LazyVerticalGrid \{ items(...) \{ … \} \}whose inneritemscall has nokey = \{ … \}recomposes every visible cell on every reorder. Audit the call to add a stable key.
- Find
- org.openrewrite.kotlin.compose.FindLifecycleAwareFlowSmells$KtRecipe
- Find lifecycle-naive flow / LiveData collection in Composables
- Collectors and observers that keep running while the host activity is stopped:
LiveData.observeAsState(),viewModel.uiState.collectAsState()(vscollectAsStateWithLifecycle()), andLiveData.observe(...)called directly from a@Composable.
- org.openrewrite.kotlin.compose.FindListAsComposableParam$KtRecipe
- Find
@Composablefunctions withList/Map/Setparameters kotlin.collections.List(and friends) are read-only views, not immutable types — aList<T>can be aMutableList<T>upcast, so Compose's stability inferrer marks the parameter unstable and re-invokes the composable on every parent recomposition. UseImmutableList<T>fromkotlinx.collections.immutableor wrap in a@Immutabledata holder.
- Find
- org.openrewrite.kotlin.compose.FindListOfInComposableBody$KtRecipe
- Find
listOf(...)/mapOf(...)/setOf(...)calls inside a@Composable listOf(a, b)allocates a freshListon every recomposition. If the composable downstream is@Stableand compares its inputs by reference, the new list defeats memoization. Hoist into aremember \{ listOf(a, b) \}or convert to anImmutableListdeclared at file scope.
- Find
- org.openrewrite.kotlin.compose.FindLiveDataObserveInComposable$KtRecipe
- Find
LiveData.observe(...)calls inside@Composable LiveData.observe(lifecycleOwner, observer)is forActivity/Fragmentcode; inside a@Composableit registers a brand-new observer on every recomposition and never removes it. UseobserveAsState()(or migrate toStateFlowandcollectAsStateWithLifecycle()).
- Find
- org.openrewrite.kotlin.compose.FindLongModifierChain$KtRecipe
- Find
Modifier.xxx().yyy()...chains longer than five operations - A
Modifierchain with more than five operations is hard to read, hard to memoize, and often hides a hoist-into-a-named-Modifier opportunity. Extract the chain into aval styled = Modifier…declaration (ideallyremembered at the call site) so the composable body reads as intent rather than plumbing.
- Find
- org.openrewrite.kotlin.compose.FindLowercaseComposableFunction$KtRecipe
- Find
@Composablefunctions whose name starts with a lowercase letter - Compose convention: composables that emit UI use
PascalCaseto set them apart from regular Kotlin functions in IDE auto-complete and stack traces. Lowercase-named composables either should be renamed or, if they return a value rather than emit UI, marked@ReadOnlyComposableto signal they don't compose.
- Find
- org.openrewrite.kotlin.compose.FindModifierClickableBeforeBackground$KtRecipe
- Find
Modifier.clickable \{ \}.background(...)chains - When
clickableprecedesbackgroundin aModifierchain, the background paints on top of the touch target — the visible color is the background, but the ripple/feedback originates from the layer underneath, which usually isn't the look the author wanted. Placebackground(...)first andclickable \{ … \}last so the touch surface sits above the visual fill.
- Find
- org.openrewrite.kotlin.compose.FindModifierFillMaxAndPaddingOrderSmell$KtRecipe
- Find
Modifier.fillMaxXxx().padding(...)chains - Modifier order matters:
Modifier.fillMaxSize().padding(8.dp)fills the parent first and then insets — the visible content is smaller than the parent.Modifier.padding(8.dp).fillMaxSize()insets the available space and then fills it, producing a layout that hugs the padded box. The right order is intent-specific; flag chains for review.
- Find
- org.openrewrite.kotlin.compose.FindModifierFillMaxWidthAfterFillMaxSize$KtRecipe
- Find
Modifier.fillMaxSize().fillMaxWidth()chains fillMaxSize()already constrains both width and height — appendingfillMaxWidth()is redundant and signals the author wasn't sure which size operator they wanted. Drop the second call or swap to the single operator that captures the intent.
- Find
- org.openrewrite.kotlin.compose.FindModifierOrderingSmells$KtRecipe
- Find Compose
Modifierordering smells - Modifier chains whose order produces a subtly wrong visual or interactive shape:
clickablepainted over by a laterbackground,fillMaxWidthfollowed bypadding(inset after the fill), andfillMaxSizeimmediately followed by a redundantfillMaxWidth/fillMaxHeight. Also surfacesModifier.weight(...)calls outside aRow/Columnscope, and overly long chains that could be hoisted into a named modifier.
- Find Compose
- org.openrewrite.kotlin.compose.FindModifierPaddingAfterFillMaxWidth$KtRecipe
- Find
Modifier.fillMaxWidth().padding(...)chains fillMaxWidth()followed bypadding(...)reserves the full width and then insets — the visible content is narrower than the parent. Most authors who write that chain meantpadding(...).fillMaxWidth()so the inset comes first and the fill happens inside the inset region. The right order is intent-specific; flag for review.
- Find
- org.openrewrite.kotlin.compose.FindModifierPaddingAllEqual$KtRecipe
- Find
padding(start = x, end = x, top = x, bottom = x)shorthand opportunities - When every named
padding(...)argument carries the same value,padding(all = x)(or justpadding(x)) communicates the uniform inset in a single token. Mixed-valuepadding(...)is fine; equal-on-all-sides is a shorthand candidate.
- Find
- org.openrewrite.kotlin.compose.FindModifierPaddingHorizontalEqualToVertical$KtRecipe
- Find
padding(start = x, end = x, top = y, bottom = y)shorthand opportunities Modifier.padding(start = 8.dp, end = 8.dp, top = 16.dp, bottom = 16.dp)reads as four independent insets but really means "8 horizontal, 16 vertical". The shorterpadding(horizontal = 8.dp, vertical = 16.dp)says that intent up front and survives a future change to one axis without re-pairing the values.
- Find
- org.openrewrite.kotlin.compose.FindModifierPaddingZero$KtRecipe
- Find zero-valued
Modifier.padding(...)calls Modifier.padding(0.dp)allocates aPaddingValuesand a layout pass to inset by zero — the call is a no-op in terms of layout but not at runtime. Drop the call (or split out the surrounding chain so the zero edge isn't expressed at all).
- Find zero-valued
- org.openrewrite.kotlin.compose.FindModifierShorthands$KtRecipe
- Find
Modifier.padding(...)shorthand opportunities - Named-argument
padding(...)calls whose values reduce to a shorter spelling: equal start/end + equal top/bottom collapses topadding(horizontal = x, vertical = y); all-equal collapses topadding(all = x); all-zero is a removable no-op.
- Find
- org.openrewrite.kotlin.compose.FindModifierWeightOutsideRowColumn$KtRecipe
- Find
Modifier.weight(...)calls outside aRow/Columnscope Modifier.weight(weight)is an extension onRowScope/ColumnScope— calling it elsewhere is a compile error in well-typed code, but stub builds and intrinsic-measurement hacks let mis-scoped calls slip through. Flag anyweight(...)on aModifierchain whose nearest enclosing scoped builder isn't aRoworColumn.
- Find
- org.openrewrite.kotlin.compose.FindMutableCollectionAsComposableParam$KtRecipe
- Find
@Composablefunctions withMutableList/MutableMap/MutableSetparameters - Compose's stability inferrer treats
MutableList/MutableMap/MutableSetparameters as unstable — every recomposition compares by identity and re-invokes the composable even if no element changed. Usekotlinx.collections.immutable.ImmutableList(or wrap in a@Stableclass) so equality checks short-circuit and recomposition is skipped.
- Find
- org.openrewrite.kotlin.compose.FindMutableStateInClassField$KtRecipe
- Find
mutableStateOf(...)stored in a class field private val x = mutableStateOf(...)at class scope ties the state to the lifetime of the enclosing class — ViewModel scope is fine, but UI-layer classes shouldn't be holding state for the composable. Hoist into a ViewModel or accept the state from the caller via parameters so recomposition and lifecycle agree on ownership.
- Find
- org.openrewrite.kotlin.compose.FindMutableStateInComposableWithoutRemember$KtRecipe
- Find bare
mutableStateOf(...)inside@Composablewithoutremember \{ \} - A bare
mutableStateOf(...)call inside a@Composableallocates a freshMutableStateon every recomposition, throwing away the previous value. Wrap inremember \{ mutableStateOf(...) \}so the snapshot survives recomposition (or hoist into a ViewModel if it needs to survive process death).
- Find bare
- org.openrewrite.kotlin.compose.FindNavigateInComposableBody$KtRecipe
- Find
NavController.navigate(...)calls in a@Composablebody navController.navigate(...)called directly in the body fires on every recomposition, leading to navigation loops or back-stack corruption. Wrap in aLaunchedEffect(key) \{ … \}keyed by the condition that should trigger the navigation, or move the call into an event handler (onClick = \{ … \}).
- Find
- org.openrewrite.kotlin.compose.FindNonComposableUsingComposableApis$KtRecipe
- Find non-
@Composablefunctions calling@Composable-only APIs - A function that calls
LaunchedEffect/remember/rememberCoroutineScopebut isn't annotated@Composableitself is a compile error in well-typed code, but suppressors and hand-rolled annotations let it slip through. Add@Composableto the function declaration so the contract is explicit.
- Find non-
- org.openrewrite.kotlin.compose.FindObserveAsState$KtRecipe
- Find
LiveData.observeAsState()calls — prefercollectAsStateWithLifecycle() observeAsState()ties subscription to the composition, not to the lifecycle owner — collection keeps running while the host activity isSTOPPED. Migrate toStateFlowandcollectAsStateWithLifecycle()(or stay on LiveData and useandroidx.lifecycle.compose.observeAsState, which is lifecycle-aware in newer versions).
- Find
- org.openrewrite.kotlin.compose.FindPublicMutableStateFlowProperty$KtRecipe
- Find non-
privateMutableStateFlowproperties - Convention pattern:
private val _state = MutableStateFlow(...); val state: StateFlow<T> = _state.asStateFlow(). A non-privateMutableStateFlowproperty exposes the writable handle to consumers — anyone who can read it can also call.value = …ortryEmit(...), breaking the unidirectional-data-flow contract the ViewModel is supposed to enforce. Make the fieldprivateand expose a read-onlyStateFlowview.
- Find non-
- org.openrewrite.kotlin.compose.FindRecompositionSmells$KtRecipe
- Find Compose recomposition smells
- Recomposition-related patterns whose default behavior surprises authors:
LazyColumn/LazyRow/LazyVerticalGridwhose inneritems(...)calls have nokey(composition state churns on reorder), and lazy-list content lambdas that read snapshot state from the enclosing scope (every state change invalidates the entire list).
- org.openrewrite.kotlin.compose.FindRememberCoroutineScopeInLambda$KtRecipe
- Find
rememberCoroutineScope()calls inside a lambda rememberCoroutineScope()must be called from a composition-aware position — inside a lambda (like anonClick) it's a compile error. The recipe surfaces such mis-positioned calls so they migrate to the composable body proper.
- Find
- org.openrewrite.kotlin.compose.FindRememberMutableListOfWithoutMutableState$KtRecipe
- Find
remember \{ mutableListOf<T>() \}patterns remember \{ mutableListOf<T>() \}survives recomposition but mutations to the list are invisible to Compose — adding an item won't trigger a re-render of any consumer that reads the list. Useremember \{ mutableStateListOf<T>() \}(or hoist tomutableStateListOf<T>()at file scope) so writes register as snapshot writes.
- Find
- org.openrewrite.kotlin.compose.FindRememberNoKeys$KtRecipe
- Find
remember \{ … \}calls with no keys remember \{ … \}with no key arguments caches once per call site forever. If the block references variables that vary between recompositions, the cache holds a stale value. Either pass the referenced variables as keys (remember(input) \{ … \}) or — if the value really is invariant — leave a comment justifying it.
- Find
- org.openrewrite.kotlin.compose.FindRememberWithUnstableKey$KtRecipe
- Find
remember(mutableListOf(...), …)and similar unstable-key calls - A
remember(key, calc)whose key is a fresh allocation —mutableListOf(...),arrayOf(...),listOf(...)— is structurally a new key on every recomposition. The cache resets every time, defeating the entire purpose ofremember. Pass the underlying values that do survive recomposition (or stable references) as the keys.
- Find
- org.openrewrite.kotlin.compose.FindRowWithSingleChild$KtRecipe
- Find
Row \{ … \}with a single child - A
Row \{ OneChild() \}allocates a layout node and runs the row measurement to position exactly one child. Either remove the row or replace withBox(modifier = m)if the row'shorizontalArrangementactually does work the parent isn't.
- Find
- org.openrewrite.kotlin.compose.FindSideEffectAllocationsInBody$KtRecipe
- Find
java.io.File(...)allocations inside a@Composablebody - Filesystem objects allocated inside a
@Composablebody get rebuilt on every recomposition. Even if the constructor is cheap, the I/O performed by callers (File.exists(),File.length()) often is not. Move the allocation into aremember \{ File(...) \}block or out of the composable entirely.
- Find
- org.openrewrite.kotlin.compose.FindSideEffectInComposableBody$KtRecipe
- Find logging calls in
@Composablebodies android.util.Log/printlninside a@Composablebody runs on every recomposition — often dozens of times during a single user interaction — producing log spam and disguising real telemetry. Move the call into aSideEffect \{ \}(or aLaunchedEffect(key) \{ \}) so it fires once per successful composition, or out of the composable entirely.
- Find logging calls in
- org.openrewrite.kotlin.compose.FindSideEffectSmells$KtRecipe
- Find Compose effect-handler misuse
- Effect calls whose shape mismatches the effect's contract:
SideEffect(key) \{ \}(SideEffecttakes no keys);LaunchedEffect \{ \}with no key (useLaunchedEffect(Unit));LaunchedEffectlambdas with several distinct suspend calls that probably want splitting.
- org.openrewrite.kotlin.compose.FindSideEffectWithKey$KtRecipe
- Find
SideEffect(key) \{ … \}calls SideEffect \{ \}takes no keys — it runs after every successful composition. Passing an argument suggests the author meantLaunchedEffect(key) \{ \}(lifecycle-tied) orDisposableEffect(key) \{ … \}(cleanup-tied). Either drop the argument or switch to the keyed effect type.
- Find
- org.openrewrite.kotlin.compose.FindStableAnnotationOnClassWithMutableCollection$KtRecipe
- Find
@Stableclasses holding mutable-collection properties - An
@Stableclass with aMutableList/MutableMap/MutableSetproperty cannot uphold the contract: the collection can mutate withoutequals/hashCodereflecting the change, so Compose's skip-when-equal heuristic produces stale UI. Replace withImmutableList/PersistentListor drop the@Stableannotation.
- Find
- org.openrewrite.kotlin.compose.FindStableAnnotationOnMutableClass$KtRecipe
- Find
@Stableon classes withvarproperties @Stableis a contract: callers may skip recomposition when input references compare equal, and the class promises thatequals/hashCodereflect all observable state. Avarproperty breaks both halves — the value can mutate without anyone updating the snapshot system, so the annotation lies and downstream@Composables silently skip required recompositions.
- Find
- org.openrewrite.kotlin.compose.FindStateAndRememberSmells$KtRecipe
- Find Compose state + remember misuse
- State that does not survive recomposition the way the author intended:
remember(unstableKey, …)whose key is itself a fresh allocation;by remember \{ … \}whose body isn't aMutableState(the delegate is a no-op);remember \{ mutableListOf(...) \}where the mutations bypass the snapshot system.
- org.openrewrite.kotlin.compose.FindStateFlowDirectCollect$KtRecipe
- Find
viewModel.uiState.collectAsState()calls — confirm lifecycle-aware collection viewModel.uiState.collectAsState()keeps the collector active while the host is in the background —collectAsStateWithLifecycle()is the lifecycle-aware analogue. Both work; the recipe surfaces the call so each ViewModel-collection site is verified rather than defaulted.
- Find
- org.openrewrite.kotlin.compose.FindStateValueRead$KtRecipe
- Find
state.valuereads inside a@Composable - Reading
state.valueworks but loses thebydelegate ergonomics — and worse, withremember \{ mutableStateOf(...) \}plus.value, it is easy to forget therememberand create a freshMutableStateper recomposition. Preferval state by remember \{ mutableStateOf(...) \}so the type checker keeps the snapshot read implicit.
- Find
- org.openrewrite.kotlin.compose.FindSurfaceWithSingleChild$KtRecipe
- Find
Surface \{ OneChild() \}patterns - A
Surface \{ OneChild() \}wrapper that only sets a tonal elevation or color is rarely the right place to live — the same effect is achievable by passingModifier.background(...)orModifier.shadow(...)directly to the child. Audit single-child surfaces for redundancy.
- Find
- org.openrewrite.kotlin.compose.FindUnnecessaryComposeWrappers$KtRecipe
- Find single-child wrapper composables (Material 3)
- Material 3 wrapper composables that add a layout node and a styling pass for exactly one child:
Surface \{ OneChild() \}andCard \{ OneChild() \}. Audit for redundancy — the same styling can usually be expressed by passingModifier.background/Modifier.shadowto the child.
- org.openrewrite.kotlin.compose.FindViewModelInComposable$KtRecipe
- Find
viewModel<X>()calls inside@Composable viewModel<X>()retrieves aViewModelscoped to the nearestViewModelStoreOwner. Inside a generic composable this couples the composable to the host'sViewModelStoreOwnerprovision — fine at screen entry points, surprising deep in a component tree. Flag to confirm intent.
- Find
- org.openrewrite.kotlin.compose.ImproveKotlinCompose$KtRecipe
- Apply Compose autofix rewrites
- Autofix-only Compose bundle: promotes
remember \{ mutableStateOf(emptyList/Map()) \}to the snapshot-awaremutableStateListOf/mutableStateMapOfcontainers. The bulk of Compose remediation is judgement-call work flagged byCompose— for diff-only output, use this recipe instead.
- org.openrewrite.kotlin.compose.UseMutableStateListOf$KtRecipe
- Find
remember \{ mutableStateOf(emptyList<T>()) \}candidates formutableStateListOf remember \{ mutableStateOf(emptyList()) \}boxes the list in aMutableState, so writes requirestate.value = state.value + item.mutableStateListOf<T>()is a snapshot-aware list:add/removeregister as snapshot writes and trigger recomposition for readers.
- Find
- org.openrewrite.kotlin.compose.UseMutableStateMapOf$KtRecipe
- Find
remember \{ mutableStateOf(emptyMap<K, V>()) \}candidates formutableStateMapOf remember \{ mutableStateOf(emptyMap()) \}boxes the map in aMutableState, so writes requirestate.value = state.value + …(or a clone).mutableStateMapOf<K, V>()is a snapshot-aware map: directput/removecalls register as snapshot writes and trigger recomposition for readers.
- Find
- org.openrewrite.kotlin.compose.UseSpecializedComposeStateContainers$KtRecipe
- Find
remember \{ mutableStateOf(emptyList/Map()) \}candidates for snapshot-aware containers - Patterns like
remember \{ mutableStateOf(emptyList()) \}box the collection in aMutableState— directadd/putcalls bypass the snapshot system.mutableStateListOf<T>()/mutableStateMapOf<K, V>()are snapshot-aware containers whose mutations register as snapshot writes and notify readers.
- Find
- org.openrewrite.kotlin.coroutines.Coroutines$KtRecipe
- Modernize Kotlin coroutines code
- Search-only recipes that surface coroutine-related issues IntelliJ IDEA 2026.1's coroutine inspections flag: structured-concurrency leaks, blocking on suspend contexts, Flow operator misorder, and hand-rolled sequencing where a canonical operator exists. Each match is a
SearchResultfor review — nothing is rewritten automatically.
- org.openrewrite.kotlin.coroutines.FindAsyncImmediatelyAwait$KtRecipe
- Find
async \{ ... \}.await()patterns async \{ … \}.await()on its own is structurally identical towithContext \{ … \}plus an extraDeferredallocation. UsewithContext(ctx) \{ … \}(or just inline the body) —asyncis for concurrency, not sequencing.
- Find
- org.openrewrite.kotlin.coroutines.FindBareCoroutineScopeCtor$KtRecipe
- Find raw
CoroutineScope(...)constructions - A
CoroutineScope(...)constructed inline must be cancelled explicitly when its owner is torn down; nothing automatic ties it to a lifecycle. Prefer one of the framework scopes (viewModelScope,lifecycleScope) or own the cancellation explicitly in aCloseable.
- Find raw
- org.openrewrite.kotlin.coroutines.FindBlockingOnSuspend$KtRecipe
- Find blocking calls inside coroutine contexts
- Java-monitor and
runBlockingprimitives that pin the dispatcher thread when invoked from a suspend function or coroutine builder. Each match needs to migrate to a coroutine-aware signaling primitive (delay,Channel,Mutex,CompletableDeferred).
- org.openrewrite.kotlin.coroutines.FindCallbackFlowWithoutAwaitClose$KtRecipe
- Find
callbackFlow \{ \}blocks without anawaitClose \{ \}terminator callbackFlow \{ \}must end withawaitClose \{ \}to suspend until the consumer cancels. Without it, the producer either completes immediately (silent drop) or throws — the same flow needs to register its cleanup hook inawaitClose \{ \}.
- Find
- org.openrewrite.kotlin.coroutines.FindCoroutineScopeBuilderWithSingleLaunch$KtRecipe
- Find
coroutineScope \{ launch \{ ... \} \}with a single child - A
coroutineScope \{ launch \{ … \} \}containing a singlelaunchis equivalent to just running the launch body inline — the surrounding scope adds an allocation and a synchronization point with nothing to coordinate.
- Find
- org.openrewrite.kotlin.coroutines.FindCoroutineSequencingSmells$KtRecipe
- Find coroutine sequencing smells
- Hand-rolled sequencing that would be cleaner with the canonical operators:
map \{ it.await() \}(useawaitAll),forEach \{ it.join() \}(usejoinAll),async \{ \}.await()(usewithContextor inline), nestedwithContext,coroutineScope \{ launch \{ \} \}with a single child.
- org.openrewrite.kotlin.coroutines.FindDebounceBeforeDistinctUntilChanged$KtRecipe
- Find
debounce(...).distinctUntilChanged()patterns debouncealready drops intermediate values within the window; addingdistinctUntilChangedafter it is redundant if the upstream is already deduped. Verify whetherdistinctUntilChangedbelongs beforedebounce, where it can prevent re-firing the debounce window for repeated values.
- Find
- org.openrewrite.kotlin.coroutines.FindFlowAntiPatterns$KtRecipe
- Find Flow operator antipatterns
- Flow chains where operator order, sharing configuration, or terminal placement undermines the intended behavior — collapsible
map.map/filter.filter,flowOnpast a terminal,stateIn/shareInwithout an explicit timeout,Flow.collectinside@Composable, etc.
- org.openrewrite.kotlin.coroutines.FindFlowCollectInsideCompose$KtRecipe
- Find
Flow.collectcalls inside a@Composable Flow.collectinside a@Composableties collection to recomposition rather than the composable's lifecycle, leaking work on re-entry. UsecollectAsStateWithLifecycle(Compose) or wrap withLaunchedEffect \{ flow.collect \{ … \} \}.
- Find
- org.openrewrite.kotlin.coroutines.FindFlowFilterFilterChain$KtRecipe
- Find
Flow.filter \{ \} .filter \{ \}chains - Adjacent
Flow.filter \{ \}calls do twice the work a combined predicate would do. Fold them into onefilter \{ p1(it) && p2(it) \}.
- Find
- org.openrewrite.kotlin.coroutines.FindFlowMapMapChain$KtRecipe
- Find
Flow.map \{ \} .map \{ \}chains - Two adjacent
Flow.map \{ \}operators emit through twotransformstages where one would do. Fold them into a singlemap, or usemap \{ (a, b) -> … \}destructuring.
- Find
- org.openrewrite.kotlin.coroutines.FindFlowOfWithVararg$KtRecipe
- Find
flowOf(...)calls — verify size flowOf(items)materializes each item upfront — for hot data or large fanout, preferflow \{ items.forEach \{ emit(it) \} \}or aChannel-backed flow to avoid the upfront vararg array.
- Find
- org.openrewrite.kotlin.coroutines.FindFlowOnAfterTerminal$KtRecipe
- Find
Flow.flowOnplaced after a terminal operator flowOn(...)applies to upstream operators only. Placing it after a terminal likecollect,first, ortoListis a no-op — the producer dispatcher is whatever the collector inherits.
- Find
- org.openrewrite.kotlin.coroutines.FindForEachJoin$KtRecipe
- Find
forEach \{ it.join() \}overList<Job> - Sequential
.forEach \{ it.join() \}waits for eachJobto complete before starting the next wait.joinAll()waits for all jobs concurrently with a single suspension point.
- Find
- org.openrewrite.kotlin.coroutines.FindGlobalScopeActor$KtRecipe
- Find
GlobalScope.actorcalls GlobalScope.actor \{ \}is structurally identical toGlobalScope.launch: the actor coroutine has no parent and cannot be cancelled cooperatively. Use a lifecycle-scopedactorinstead.
- Find
- org.openrewrite.kotlin.coroutines.FindGlobalScopeAsync$KtRecipe
- Find
GlobalScope.asynccalls GlobalScope.async \{ \}produces an orphanDeferredthat has no parent in the structured-concurrency tree. Exceptions thrown from this coroutine are dropped until somethingawait()s the result — and if nothing does, they vanish silently.
- Find
- org.openrewrite.kotlin.coroutines.FindGlobalScopeLaunch$KtRecipe
- Find
GlobalScope.launchcalls GlobalScope.launch \{ \}is a fire-and-forget coroutine builder with no parent — it cannot be cancelled with the lifecycle that started it and leaks if the work outlives the screen/process. Prefer a scopedCoroutineScopetied to the lifecycle (viewModelScope,lifecycleScope, or an explicit scope cancelled inonCleared).
- Find
- org.openrewrite.kotlin.coroutines.FindGlobalScopeProduce$KtRecipe
- Find
GlobalScope.producecalls GlobalScope.produce \{ \}returns an unscopedReceiveChannelthat keeps running until its producer block returns. Anchor the channel to a scope owned by the surrounding lifecycle.
- Find
- org.openrewrite.kotlin.coroutines.FindJobAsContext$KtRecipe
- Find raw
Job()allocations - Raw
Job()calls usually feed aCoroutineScope(...)context, where they signal an intent to manage coroutine lifecycle manually. That manual lifecycle is easy to forget to cancel; preferSupervisorJob()paired with a scope tied to the surrounding lifecycle (e.g.viewModelScope).
- Find raw
- org.openrewrite.kotlin.coroutines.FindMapAwait$KtRecipe
- Find
map \{ it.await() \}overList<Deferred<T>> - Sequential
.map \{ it.await() \}waits for eachDeferredin turn and rethrows the first exception only after every earlier element completes.awaitAll()waits concurrently and rethrows immediately on the first failure.
- Find
- org.openrewrite.kotlin.coroutines.FindMutableStateFlowNullable$KtRecipe
- Find
MutableStateFlow<T?>(null)declarations - Nullable
MutableStateFlow<T?>is a common pattern for 'no value yet', but collapses the empty state and the value-is-null state into one. ASharedFlow<T>withreplay = 0and explicittryEmit(or a sealed wrapperUiState.Empty | Loaded(T)) usually expresses intent more precisely.
- Find
- org.openrewrite.kotlin.coroutines.FindObjectNotifyInSuspend$KtRecipe
- Find
Object.notify/notifyAllcalls insidesuspendfunctions - Monitor-based signaling (
notify/notifyAll) doesn't compose with coroutine cancellation or structured concurrency. Replace with aChannel,MutableSharedFlow, orCompletableDeferredto wake suspended coroutines.
- Find
- org.openrewrite.kotlin.coroutines.FindObjectWaitInSuspend$KtRecipe
- Find
Object.waitcalls insidesuspendfunctions Object.wait()blocks the dispatcher thread on a monitor and cannot be interrupted by coroutine cancellation. Migrate toChannel/Flow/Mutexor aCompletableDeferredfor cross-coroutine signaling.
- Find
- org.openrewrite.kotlin.coroutines.FindRunBlockingInLaunch$KtRecipe
- Find
runBlockingcalls inside alaunch/asynclambda runBlockinginside an outer coroutine builder pins the dispatcher thread until the inner block returns, defeating the cooperative scheduling the outer builder set up. Inline the suspending body — you're already in a suspend context.
- Find
- org.openrewrite.kotlin.coroutines.FindRunBlockingInSuspend$KtRecipe
- Find
runBlockingcalls insidesuspendfunctions runBlockinginside asuspendfunction blocks the calling thread until the inner block finishes, defeating cooperative cancellation and pinning a thread that the dispatcher could otherwise reuse. From a suspend context, the block can be inlined or wrapped inwithContext(...)instead.
- Find
- org.openrewrite.kotlin.coroutines.FindShareInWithoutTimeout$KtRecipe
- Find
shareIncalls without a timeout-parameterized start - Same trap as
stateIn— without an explicitWhileSubscribed(timeoutMillis), an unused upstream producer keeps running, and config changes (which momentarily drop subscriber counts) can either drop state or hold work alive.
- Find
- org.openrewrite.kotlin.coroutines.FindStateInWithoutTimeout$KtRecipe
- Find
stateInwithSharingStarted.Eagerlyor unparameterized start stateIn(scope)with the defaultEagerlystart keeps the upstream Flow producing forever (no last-subscriber timeout). For UI state,WhileSubscribed(5_000)is the canonical setting — it survives configuration changes without leaking the producer.
- Find
- org.openrewrite.kotlin.coroutines.FindStructuredConcurrencyLeaks$KtRecipe
- Find structured-concurrency leaks
- Coroutine builders that escape the structured-concurrency tree:
GlobalScopebuilders, rawJob()/CoroutineScope(...)allocations, andsuspendCoroutinecalls that ignore cancellation. Each match is aSearchResultfor review.
- org.openrewrite.kotlin.coroutines.FindSuspendCoroutineWithoutCancellation$KtRecipe
- Find
suspendCoroutinecalls suspendCoroutinelacks cancellation hooks — if the surrounding coroutine is cancelled before the continuation resumes, the underlying callback work runs to completion uselessly. Switch tosuspendCancellableCoroutineso the continuation block can register aninvokeOnCancellationcallback.
- Find
- org.openrewrite.kotlin.coroutines.FindThreadSleepInSuspend$KtRecipe
- Find
Thread.sleepcalls insidesuspendfunctions Thread.sleepparks the underlying dispatcher thread and ignores coroutine cancellation. From a suspend function, usedelay(ms)— it suspends without blocking and integrates with structured cancellation.
- Find
- org.openrewrite.kotlin.coroutines.FindWithContextInsideSameDispatcher$KtRecipe
- Find nested
withContextcalls - A
withContext(...)nested inside anotherwithContext(...)rarely makes sense — the inner switch only matters if the dispatchers differ, and in either case the redundancy is worth a second look.
- Find nested
- org.openrewrite.kotlin.functional.FindCatchAllException$KtRecipe
- Find broad
catch (e: Exception)/catch (e: Throwable)clauses catch (e: Exception)catches almost everything —IllegalArgumentException,ConcurrentModificationException, even programmer-errorNullPointerException.catch (e: Throwable)is worse: it catchesOutOfMemoryErrorandkotlinx.coroutines.CancellationException. Each broad catch is a candidate for narrowing to the specific exceptions the surrounding code is prepared to handle.
- Find broad
- org.openrewrite.kotlin.functional.FindCatchAndRethrowNewExceptionWithoutCause$KtRecipe
- Find
catch (e: Exception) \{ throw OtherException(...) \}withouteas cause - Catching one exception and throwing a different one without passing the original as the
causeargument loses the original stack trace at the throw site — debugging then starts from the wrapping exception with no breadcrumbs to the actual failure. Includeein the new exception's constructor (or use.initCause(e)).
- Find
- org.openrewrite.kotlin.functional.FindCatchAndRethrowSameException$KtRecipe
- Find
catch (e: Exception) \{ throw e \}patterns - A catch whose only statement is
throw eis a no-op: the same exception flows through the same way it would have without the try. Drop the entire try/catch (or, if there's afinally, switch to a try/finally).
- Find
- org.openrewrite.kotlin.functional.FindCatchBindingUnusedException$KtRecipe
- Find
catch (e: Exception)clauses whose body never referencese - If the catch body never reads the bound exception parameter — and there's still some statement that handles the recovery — the binding name is dead weight. Use
catch (_: Exception)to make 'I have no use for the exception' explicit, and so future readers don't waste time looking for whereegets used.
- Find
- org.openrewrite.kotlin.functional.FindCatchWithoutLogging$KtRecipe
- Find non-empty catch blocks that neither log nor rethrow
- A catch that handles the exception by silently absorbing it (without logging, without rethrowing, without storing it) loses every detail of the failure. Either log with the exception as the cause (
log.error("context", e)), rethrow as a wrapping exception, or capture the exception into aResult/sealed result type.
- org.openrewrite.kotlin.functional.FindNestedTryCatch$KtRecipe
- Find
try \{ \} catch \{ \}nested inside anothertry \{ \} catch \{ \} - A try nested inside another try usually means two failure modes are being handled at two different recovery points in the same control-flow tree. Pull each failure mode into its own helper function (or into a
runCatching \{ \}.fold(...)chain) so the recovery strategy is visible at each level.
- Find
- org.openrewrite.kotlin.functional.FindNullabilityErgonomics$KtRecipe
- Find nullability idiom opportunities
- Search-only bundle for nullable-handling
if/elseshapes that map to Kotlin idioms:if (x != null) x else default(use?:),if (x != null) f(x) else null(usex?.let \{ f(it) \}),if (x == null) throw IllegalArgumentException(userequireNotNull),if (x == null) throw IllegalStateException(usecheckNotNull), andif (p(x)) x else null(usex.takeIf \{ p(it) \}).
- org.openrewrite.kotlin.functional.FindPrintStackTraceInCatch$KtRecipe
- Find
e.printStackTrace()calls inside a catch block e.printStackTrace()writes to stderr — which in most server environments is either unread, unrotated, or both. Replace with a real logger call (log.error("context", e)) so the stack trace lands in the same place every other error in the application does.
- Find
- org.openrewrite.kotlin.functional.FindResultErgonomics$KtRecipe
- Find
Result<T>API ergonomics opportunities - Search-only bundle for
Result<T>call sites where a different operator would be clearer:if (result.isSuccess) … else …(use.fold(...)),Result.map \{ … \}.getOrThrow()(drop the Result wrapper or use.fold(...)), andgetOrElse \{ default \}whose lambda ignores the failure (usegetOrDefault(default)).
- Find
- org.openrewrite.kotlin.functional.FindResultFoldImperative$KtRecipe
- Find
if (result.isSuccess) … else …patterns - Branching on
Result.isSuccess/Result.isFailureand then unwrapping withgetOrNull()/exceptionOrNull()is the imperative form ofresult.fold(onSuccess, onFailure). The.fold(...)form is total (the compiler verifies both branches are present) and reads as the value-producing expression it actually is.
- Find
- org.openrewrite.kotlin.functional.FindResultGetOrElseIgnoringFailure$KtRecipe
- Find
Result.getOrElse \{ \}whose lambda ignores the failure parameter result.getOrElse \{ default \}(lambda ignores its parameter) is exactlyresult.getOrDefault(default). ThegetOrDefaultform makes the intent — 'a constant fallback, the exception type is irrelevant' — explicit in the call name.
- Find
- org.openrewrite.kotlin.functional.FindResultGetOrThrow$KtRecipe
- Find
.getOrThrow()calls on aResult<T> Result.getOrThrow()unwraps success or rethrows the captured failure. If the call site does that immediately afterrunCatching \{ … \}, theResultround-trip is pure ceremony — the same value with the same failure mode comes out of the bare expression. Prefer the bare expression, or use.fold(...)/.getOrElse \{ … \}to actually do something with the failure.
- Find
- org.openrewrite.kotlin.functional.FindResultMapWithoutErrorHandling$KtRecipe
- Find
Result.map \{ \}.getOrThrow()chains result.map \{ transform(it) \}.getOrThrow()isresult.fold(::transform, \{ throw it \})written long-hand — and.fold(...)keeps the transformation and the failure handling next to each other. If the failure branch really is 'rethrow', drop theResultwrapper entirely and put the transformation insiderunCatching \{ \}.
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingForLogOnly$KtRecipe
- Find
runCatching \{ \}.onFailure \{ log… \}chains with no further handling runCatching \{ … \}.onFailure \{ log.error("…", it) \}— when nothing follows theonFailure— succeeds-on-error rather than just observing. Often fine, but worth a glance: usually the caller still needs to know success/failure happened (return theResult, or chain.getOrElse \{ fallback \}).
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingGetOrNullDiscardingError$KtRecipe
- Find
runCatching \{ \}.getOrNull()chains runCatching \{ … \}.getOrNull()silently swallows every failure and replaces it withnull. The shape is fine for fire-and-forget side effects, but for value-producing calls you usually want at least anonFailure \{ \}hook for diagnostics, or.getOrElse \{ default \}so the failure is observable.
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingOnSuccessOnly$KtRecipe
- Find
runCatching \{ \}.onSuccess \{ … \}chains with no failure handler runCatching \{ \}.onSuccess \{ … \}with nothing after it discards the failure side of theResult. The success block runs only on success; the failure case vanishes silently. Add a paired.onFailure \{ \}for diagnostics, or.fold(::onSuccess, ::onFailure)to make both cases explicit.
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingSmells$KtRecipe
- Find
runCatching \{ \}smells - Search-only bundle covering the most common
runCatching \{ \}pitfalls: swallowingCancellationException, collapsing failures intonullvia.getOrNull(), discarding theResultin statement context, log-only handlers that drop the failure on the floor,.onSuccess \{ \}chains with no failure handler, and.getOrThrow()patterns that turn theResultround-trip into pure ceremony.
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingSwallowingCancellation$KtRecipe
- Find
runCatching \{ \}blocks that may swallowCancellationException runCatching \{ \}catches everyThrowable, includingkotlinx.coroutines.CancellationException. Inside a coroutine that's a bug —CancellationExceptionis the cooperative-cancellation signal, and swallowing it stops the coroutine from cancelling. Either avoidrunCatchingin suspending code, or rethrow with.onFailure \{ if (it is CancellationException) throw it \}before any other handling.
- Find
- org.openrewrite.kotlin.functional.FindRunCatchingWithoutHandling$KtRecipe
- Find
runCatching \{ \}calls whose result is discarded - A
runCatching \{ \}in statement context throws nothing and returns nothing — theResult<T>is allocated and dropped on the floor. If the intent was 'do this, but don't fail the caller', wrap with.onFailure \{ log(it) \}; if the intent was 'do this, ignoring exceptions', say so withtry \{ … \} catch (_: Exception) \{ \}(or rethink whether to swallow at all).
- Find
- org.openrewrite.kotlin.functional.FindThrowCatchSmells$KtRecipe
- Find throw/catch shape smells
- Search-only bundle for throw shapes inside catch blocks: bare-
RuntimeException/Exceptionwrappers that discard contextual messages, uselesscatch \{ throw e \}blocks, and rethrows of new exception types that don't pass the caught exception ascause.
- org.openrewrite.kotlin.functional.FindTryCatchReturningDefault$KtRecipe
- Find
try \{ x \} catch (e: Exception) \{ default \}patterns - A try whose catch returns a non-null default value maps directly to
runCatching \{ x \}.getOrDefault(default)or.getOrElse \{ default \}. The latter is preferred when the default depends on the exception type.
- Find
- org.openrewrite.kotlin.functional.FindTryCatchReturningNull$KtRecipe
- Find
try \{ x \} catch (e: Exception) \{ null \}patterns - Swallowing every exception into
nulldiscards diagnostic information and conflates 'no value' with 'I lost the cause'.runCatching \{ x \}.getOrNull()matches the shape, and.onFailure \{ … \}keeps a hook for diagnostics if you decide you want one later.
- Find
- org.openrewrite.kotlin.functional.FindTryCatchSmells$KtRecipe
- Find raw
try/catchsmells - Search-only bundle for try/catch shapes worth reviewing: collapse-to-null and collapse-to-default branches (candidates for
runCatching \{ \}.getOrNull()/.getOrDefault(...)), empty catches that lose every detail of the failure, broadcatch (Exception)/catch (Throwable)clauses, catches that absorb the exception without logging or rethrowing,e.printStackTrace()calls that should be logger calls, nested try/catch trees, and catch parameters that are bound but never read.
- Find raw
- org.openrewrite.kotlin.functional.FindTryCatchSwallowingException$KtRecipe
- Find empty catch blocks
- An empty catch (
catch (e: Exception) \{ \}) eats every exception and produces no record of it ever happening. Even a logger call records that something went wrong; an empty block makes the failure undebuggable.
- org.openrewrite.kotlin.functional.FindUseCheckForState$KtRecipe
- Find
if (x == null) throw IllegalStateException(...)patterns checkNotNull(x) \{ "…" \}is the state-precondition twin ofrequireNotNull: throwsIllegalStateExceptionwhenxis null and smart-casts to non-nullable on return. Use it for invariants about the object's state, leavingrequireNotNullfor arguments.
- Find
- org.openrewrite.kotlin.functional.FindUseElvisForNullableDefault$KtRecipe
- Find
if (x != null) x else defaultpatterns if (x != null) x else defaultis the elvis operator written long-hand:x ?: default. The elvis form composes naturally with chains (a ?: b ?: c) and keeps the value derivation in a single expression.
- Find
- org.openrewrite.kotlin.functional.FindUseLetForNullableMap$KtRecipe
- Find
if (x != null) f(x) else nullpatterns if (x != null) f(x) else nullisx?.let \{ f(it) \}written long-hand. The?.let \{ \}form is more concise and (whenfis a member call) collapses further tox?.f(...).
- Find
- org.openrewrite.kotlin.functional.FindUseRequireForPrecondition$KtRecipe
- Find
if (x == null) throw IllegalArgumentException(...)patterns - Kotlin's
requireNotNull(x) \{ "…" \}is the idiomatic precondition check: it throwsIllegalArgumentExceptionwhenxis null, smart-castsxto its non-nullable type after the call, and reads as the assertion it is. Theif/throwform does the same thing without the smart-cast.
- Find
- org.openrewrite.kotlin.functional.FindUseTakeIfForFilter$KtRecipe
- Find
if (predicate(x)) x else nullpatterns if (predicate(x)) x else nullisx.takeIf \{ predicate(it) \}written long-hand. ThetakeIfform keeps the value as the focal point and composes with?.let \{ \}/ elvis (x.takeIf \{ … \} ?: default).
- Find
- org.openrewrite.kotlin.functional.FindWrappingExceptionInCatch$KtRecipe
- Find
throw RuntimeException(e)inside a catch block - Wrapping the caught exception in a bare
RuntimeException/Exceptiondiscards the contextual message the catch site should be adding. Wrap with a domain-specific subclass and a real message (throw FetchFailedException("fetch profile for $userId", e)), or rethrowedirectly if there's nothing to add.
- Find
- org.openrewrite.kotlin.functional.Functional$KtRecipe
- Modernize Kotlin functional /
Resultergonomics - Search-only recipes that surface
kotlin.Result/runCatching \{ \}smells and try/catch shapes that map cleanly to Kotlin idioms (.fold(...),.getOrNull(),.getOrDefault(...),?:,?.let \{ \},requireNotNull,checkNotNull). Most of the actual rewrites involve moving statements between try-body / catch-body / Result-chain shapes, which the declarativerewrite \{ \} to \{ \}DSL doesn't model yet — so each match is aSearchResultfor human review.
- Modernize Kotlin functional /
- org.openrewrite.kotlin.idiom.FindAlsoWithMutation$KtRecipe
- Find
also \{ \}blocks that mutate the receiver also \{ \}is for side effects that don't change the receiver — logging, validation, registering a callback. If the lambda mutatesit, preferapply \{ … \}, which is built for that and reads as configuration.
- Find
- org.openrewrite.kotlin.idiom.FindApplyResultUnused$KtRecipe
- Find
?.apply \{ \}whose result is discarded x?.apply \{ … \}returns the receiver, but if the result is discarded the safe-call's return value adds nothing. Usex?.also \{ … \}or move the side effect out ofapply, where the receiver isn't needed.
- Find
- org.openrewrite.kotlin.idiom.FindApplyThisQualifier$KtRecipe
- Find redundant
this.insideapply \{ \}blocks - Inside
apply \{ \}, every member access resolves against the implicit receiver —this.prop = vis justprop = v. Drop the qualifier; the whole point ofapplyis the implicit receiver.
- Find redundant
- org.openrewrite.kotlin.idiom.FindApplyWithoutMutation$KtRecipe
- Find
apply \{ \}blocks that perform no mutation apply \{ \}is for configuring the receiver and returning it. If the block has no assignments or property writes,also \{ \}(which exposes the receiver asitand runs for side effects) or just inlining the call expresses the intent more clearly.
- Find
- org.openrewrite.kotlin.idiom.FindCastAndNullableShapes$KtRecipe
- Find cast and nullable-shape idioms
- Unsafe
ascasts vsas?,takeIf \{ \}?.let \{ \}chains,takeUnless \{ !p \}double-negatives, deep?.safe-call chains, explicitreturn nullstatements.
- org.openrewrite.kotlin.idiom.FindCheckNotNullWithoutMessage$KtRecipe
- Find
checkNotNull(x)without an explanatory message checkNotNull(x)throws anIllegalStateExceptionwith a generic message. Pass a lazy message —checkNotNull(x) \{ "state invariant: x ready after init" \}— to make the failure self-documenting.
- Find
- org.openrewrite.kotlin.idiom.FindCollectionNullSafety$KtRecipe
- Find collection null-safety idioms
listOf(...).filterNotNull()vslistOfNotNull(...),map \{ \}.filterNotNull()vsmapNotNull \{ \},filter \{ it != null \}.map \{ it!! \}chains,firstOrNullpatterns wheresingleis intended,?.x.orEmpty()mixed-call shapes.
- org.openrewrite.kotlin.idiom.FindElvisThrowWithoutMessage$KtRecipe
- Find
x ?: throw SomeException()without a message x ?: throw IllegalStateException()(no message arg) throws with a stack trace and no context. Pass an argument that explains whyxwas expected non-null at this point — error reports are the cheapest tool we have.
- Find
- org.openrewrite.kotlin.idiom.FindFilterMapToMapNotNull$KtRecipe
- Find
filter \{ it != null \}.map \{ it!! \}chains filter \{ it != null \}.map \{ it!! \}is the long form ofmapNotNull \{ it \}. Both passes can be folded into a singlefilterNotNull(when no transform is needed) ormapNotNull(with a transform).
- Find
- org.openrewrite.kotlin.idiom.FindFirstOrNullElvisError$KtRecipe
- Find
firstOrNull \{ \} ?: error(...)patterns firstOrNull \{ p \}.let \{ it ?: error("missing") \}(or the?: errorform) is a manualsingle \{ p \}—singlethrows when there's no match or more than one, which is usually the intended precondition.
- Find
- org.openrewrite.kotlin.idiom.FindFirstOrNullOnNullableReceiver$KtRecipe
- Find
x?.firstOrNull()calls x?.firstOrNull()producesnulleither whenxis null OR whenxis empty — the two cases collapse. Usex?.firstOrNull() ?: defaultonly when both null-cases should yield the same fallback.
- Find
- org.openrewrite.kotlin.idiom.FindIfElseNullDefault$KtRecipe
- Find
if (cond) value else nullpatterns if (cond) value else nullisvalue.takeIf \{ cond \}(whenvaluedoesn't depend oncond) — the extension makes the predicate's role visible at the call site.
- Find
- org.openrewrite.kotlin.idiom.FindIfNotNullAssign$KtRecipe
- Find
if (x != null) y = x.foo()patterns if (x != null) y = x.foo()followed by a default elsewhere reads as a hand-rolledy = x?.foo() ?: default. The elvis form keeps the value derivation in one expression.
- Find
- org.openrewrite.kotlin.idiom.FindIfNotNullThenCall$KtRecipe
- Find
if (x != null) x.foo()that could use?. - An
if (x != null) x.foo()ladder reads as a manual nullable dispatch where Kotlin already hasx?.foo(). The safe-call form is shorter and folds into expression position, where theifcannot.
- Find
- org.openrewrite.kotlin.idiom.FindIfNullReturn$KtRecipe
- Find
if (x == null) return ...early-exit patterns - An
if (x == null) return …reads as a manual null guard where Kotlin'sx ?: return …says the same thing inline. The elvis form keeps the expression in line with its consumer and avoids a separate control-flow statement.
- Find
- org.openrewrite.kotlin.idiom.FindIfNullThrow$KtRecipe
- Find
if (x == null) throw ...patterns - An
if (x == null) throw …is the elvis-throw idiom written long-hand.x ?: throw …keeps the throw expression in line and reads as the assertion it is, rather than as a control-flow branch.
- Find
- org.openrewrite.kotlin.idiom.FindLetAtStatementPosition$KtRecipe
- Find
?.let \{ \}calls at statement position x?.let \{ … \}at statement position discards its return value, behaving identically tox?.also \{ … \}but reading as a transform.alsomakes the side-effect-only intent explicit.
- Find
- org.openrewrite.kotlin.idiom.FindLetElvis$KtRecipe
- Find
x?.let \{ \} ?: ypatterns x?.let \{ … \} ?: ymixes two intents — transform-when-present and fall-back — into a single expression. Inverts the natural reading order; consider an explicitif (x != null) … else yor pull the elvis branch out for clarity.
- Find
- org.openrewrite.kotlin.idiom.FindLetIdioms$KtRecipe
- Find
let \{ \}ergonomics ?.let \{ it \},?.let \{ it.foo() \}(including property reads), nestedletladders,letblocks at statement position, and the?.let \{ \} ?: ypattern — all cases wherelet \{ \}adds shape without clarity.
- Find
- org.openrewrite.kotlin.idiom.FindLetItCall$KtRecipe
- Find
?.let \{ it.foo() \}that could use?.foo() x?.let \{ it.foo() \}is the long form ofx?.foo()— the safe call already provides the non-null receiver, and theletintroduces an unused binding. Drop.let \{ \}and callfoo()directly.
- Find
- org.openrewrite.kotlin.idiom.FindLetItIdentity$KtRecipe
- Find
?.let \{ it \}no-ops x?.let \{ it \}is structurally equivalent tox— the lambda introduces a binding and immediately returns it without transforming. Drop the.let \{ it \}call.
- Find
- org.openrewrite.kotlin.idiom.FindLetWithFnOfIt$KtRecipe
- Find
obj.let \{ fn(it) \}whereobjis non-null - When
objis non-nullable,obj.let \{ fn(it) \}only adds a binding aroundfn(obj). Save the lambda allocation and passobjdirectly.
- Find
- org.openrewrite.kotlin.idiom.FindListOfFilterNotNull$KtRecipe
- Find
listOf(a, b, c).filterNotNull()patterns listOf(a, b, c).filterNotNull()materializes a list withnullentries only to discard them.listOfNotNull(a, b, c)skips thenulls up front and returns the same result with one fewer allocation and one fewer pass.
- Find
- org.openrewrite.kotlin.idiom.FindMapThenFilterNotNull$KtRecipe
- Find
map \{ ... \}.filterNotNull()chains - Two-pass
map \{ … \}.filterNotNull()builds an intermediate list of nullable values.mapNotNull \{ … \}does both in one pass with a single allocation and propagatesnullreturns naturally.
- Find
- org.openrewrite.kotlin.idiom.FindNestedLet$KtRecipe
- Find nested
let \{ \}chains a?.let \{ b?.let \{ … \} \}ladders for combining nullable values are clearer as a singleif (a != null && b != null) …or a sealed pair. Two-level nesting is a code smell; three or more is almost always a refactor opportunity.
- Find nested
- org.openrewrite.kotlin.idiom.FindNotNullAssertion$KtRecipe
- Find
!!non-null assertions - The
!!operator throws a genericNullPointerExceptionwith no context.requireNotNull(x) \{ "explain why" \}orx ?: error("explain why")produces a message that points at the assumption.
- Find
- org.openrewrite.kotlin.idiom.FindNotNullAssertionAsArgument$KtRecipe
- Find
!!passed as a function argument foo(x!!)pushes the null-check onto the call site, where the function signature could just acceptT?and document the contract. Iffoomust have a non-nullx, preferrequireNotNull(x) \{ ... \}at the call site to produce a contextual error.
- Find
- org.openrewrite.kotlin.idiom.FindNullAssertionPolish$KtRecipe
- Find null-assertion polish opportunities
!!operators (including as arguments),requireNotNull/checkNotNullcalls without a lazy message, andthrow SomeException()without a contextual message inside an elvis.
- org.openrewrite.kotlin.idiom.FindNullCheckIdioms$KtRecipe
- Find manual null-check idioms
if (x != null) x.foo()/if (x == null) return …/if (x == null) throw …patterns where Kotlin's?.,?: return, and?: throwoperators express the same intent in expression position.
- org.openrewrite.kotlin.idiom.FindOrEmptyAfterSafeCall$KtRecipe
- Find
x?.something.orEmpty()patterns x?.something.orEmpty()mixes safe-call and a null-coalescing extension. Either drop the?.(ifxis non-null) or chain through?: emptyList()— the mix obscures which call is providing the fallback.
- Find
- org.openrewrite.kotlin.idiom.FindRequireNotNullWithoutMessage$KtRecipe
- Find
requireNotNull(x)without an explanatory message requireNotNull(x)throws anIllegalArgumentExceptionwith a generic message. Pass a lazy message —requireNotNull(x) \{ "x must be set before init" \}— so the stack trace explains the precondition.
- Find
- org.openrewrite.kotlin.idiom.FindReturnNullExplicit$KtRecipe
- Find
return nullin functions with nullable returns - An explicit
return nullis rarely the clearest expression of intent — usually the calling chain that produces the nullable can use?:ormapNotNullto handle the no-value case at the boundary, not the inside.
- Find
- org.openrewrite.kotlin.idiom.FindRunWithoutReceiverUse$KtRecipe
- Find
x.run \{ ... \}that doesn't use the receiver run \{ \}is meaningful when the lambda referencesthis; otherwisex.let \{ … \}(binding viait) or even no scope function at all is clearer. The runtime cost is identical — the value is purely readability.
- Find
- org.openrewrite.kotlin.idiom.FindSafeCallChain$KtRecipe
- Find long
?.safe-call chains a?.b?.c?.d?.echains beyond 3 hops indicate a domain object hierarchy with too many nullable boundaries — the chain hides which boundary is the real concern. Flatten withletblocks at the boundary that matters, or refactor to non-nullable intermediates.
- Find long
- org.openrewrite.kotlin.idiom.FindScopeFunctionSwaps$KtRecipe
- Find scope-function correctness swaps
- The 12 well-known scope-function correctness rules:
with(x)used as a receiver expression vsx.run \{ \},?.apply \{ \}whose result is discarded vs?.also \{ \},apply \{ \}without mutation vsalso \{ \},also \{ \}with mutation vsapply \{ \}, redundantthis.insideapply \{ \},runwithoutthisreferences.
- org.openrewrite.kotlin.idiom.FindSetOfFilterNotNull$KtRecipe
- Find
setOf(a, b, c).filterNotNull()patterns - Same shape as
listOf(...).filterNotNull()— building a set withnulls and filtering them out.setOfNotNull(a, b, c)exists for exactly this case.
- Find
- org.openrewrite.kotlin.idiom.FindTakeIfChainedLet$KtRecipe
- Find
x.takeIf \{ p \}?.let \{ ... \}patterns x.takeIf \{ p \}?.let \{ … \}is a guard-then-transform expressed as two calls plus a safe-call.if (p) x.let \{ … \} else null(orx.takeIf(p)?.run \{ … \}) is the same in one operator without the implicitnullbridge.
- Find
- org.openrewrite.kotlin.idiom.FindTakeUnlessNegated$KtRecipe
- Find
takeUnless \{ !p \}(double-negative) patterns takeUnless \{ !p \}istakeIf \{ p \}written with a double negative. InvertingtakeUnless's predicate to positive form makes the intent immediate.
- Find
- org.openrewrite.kotlin.idiom.FindUnsafeCast$KtRecipe
- Find unsafe
ascasts x as TthrowsClassCastExceptionon mismatch — there's no diagnostic, just the JVM exception.x as? Treturnsnullon mismatch and folds into elvis/requireNotNull(...)with a better message.
- Find unsafe
- org.openrewrite.kotlin.idiom.FindWithAsReceiver$KtRecipe
- Find
with(x) \{ ... \}used as an expression with(x) \{ … \}returns the lambda result, which makes it interchangeable withx.run \{ … \}. The extension form chains better in safe-call sequences (x?.run \{ … \}) and reads as receiver-style throughout.
- Find
- org.openrewrite.kotlin.idiom.NullSafetyAndScopeFunctions$KtRecipe
- Apply Kotlin null-safety and scope-function idioms
- Search-only recipes covering the two most-cited stylistic categories in IntelliJ's Kotlin inspections: null-safety (
if (x != null)ladders,!!,requireNotNullpolish,mapNotNull/listOfNotNulladoption, unsafe casts) and scope-function ergonomics (the 12 well-definedlet/run/with/apply/alsocorrectness rules). Each match is aSearchResultfor review — nothing is rewritten automatically.
- org.openrewrite.kotlin.interop.FindBufferedReaderLines$KtRecipe
- Find
bufferedReader().lines()calls BufferedReader.lines()returns aStream<String>that must be closed explicitly and consumed exactly once. Kotlin offerslineSequence()(lazySequence<String>) anduseLines \{ sequence -> … \}(auto-closing) for the same use cases.
- Find
- org.openrewrite.kotlin.interop.FindBuilderClass$KtRecipe
- Find inner
class Builderclasses — default-args candidate - A Java-style nested
class Buildermirrors the outer class fields with setters that returnthis, then a terminalbuild(). In Kotlin, adata classwith default arguments composes with named-argument call syntax to express the same intent — usually with less code and no double maintenance.
- Find inner
- org.openrewrite.kotlin.interop.FindClockAndTestabilityFriction$KtRecipe
- Find non-injected clock / I/O calls (testability)
System.currentTimeMillis()/System.nanoTime()/LocalDateTime.now()and friends read the system clock implicitly. Each flagged call site is a candidate to receive aClock(or the JDKjava.time.Clock) so tests can advance time deterministically. Also flagsBufferedReader.lines()— usually alineSequence/useLinesmigration.
- org.openrewrite.kotlin.interop.FindCompletableFutureReturn$KtRecipe
- Find functions returning
CompletableFuture<T> - Returning
CompletableFuture<T>from Kotlin code obliges every caller to either.thenComposechain or.await()through thekotlinx-coroutines-jdk8bridge. Asuspend fun foo(): Tintegrates with structured concurrency at the language level — keep the future shape only at the Java boundary.
- Find functions returning
- org.openrewrite.kotlin.interop.FindCompletableFutureUsage$KtRecipe
- Find
CompletableFutureusage in Kotlin CompletableFuture<T>is the JVM equivalent of aDeferred<T>or single-emissionFlow<T>. In Kotlin,suspend fun/Flowintegrate with structured concurrency, cancellation, and exception handling at the language level — prefer them inside Kotlin modules and bridge withkotlinx-coroutines-jdk8at the boundary.
- Find
- org.openrewrite.kotlin.interop.FindInteropFriction$KtRecipe
- Find Java↔Kotlin interop friction points
- Search-only bundle: every interop-flavored
Find*recipe in this module. CoversOptional/Stream/CollectionsJava factories with Kotlin replacements,CompletableFuture/Rx/Reactor types with coroutine replacements, missing@Jvm*annotations on Kotlin-defined declarations Java callers reach for, and Java-style call shapes inside Kotlin source.
- org.openrewrite.kotlin.interop.FindIterableForEach$KtRecipe
- Find Java-style
iterable.forEach(Consumer)calls Iterable.forEach(Consumer<T>)is the Java-8 functional terminal; Kotlin source can use the same shape but the inlinekotlin.collections.forEachis preferred — it doesn't allocate aConsumerand integrates with non-localreturn/breakinside the lambda.
- Find Java-style
- org.openrewrite.kotlin.interop.FindJavaGetterCallStyleInKotlin$KtRecipe
- Find Java-style
getX()calls in Kotlin source - Kotlin synthesizes property syntax for any Java getter that follows the
getX()/isX()no-arg convention:obj.xreads the same value asobj.getX(). Writing the JVM-style call in Kotlin source obscures that — flag the call sites for migration to property access.
- Find Java-style
- org.openrewrite.kotlin.interop.FindJavaIdiomsInKotlin$KtRecipe
- Find Java-style call shapes inside Kotlin source
- Search-only bundle of Java idioms that have idiomatic Kotlin equivalents at the call site:
getX()/isX()getters where property syntax reads the same value,iterable.forEach(Consumer),requireNotNull(javaCall())over platform types, manualgetX/setXpairs, static-utility/constantsobjectholders,Builderclasses, and manualequals/hashCode.
- org.openrewrite.kotlin.interop.FindJavaUtilArraysAsList$KtRecipe
- Find
Arrays.asList(...)calls Arrays.asList(a, b, c)is the Java idiom for a small read-onlyList. In Kotlin,listOf(a, b, c)is more concise, properly read-only (the returned list is structurally immutable), and avoids leaking the array-backed quirk wheresetis allowed butaddis not.
- Find
- org.openrewrite.kotlin.interop.FindJavaUtilCollectionsEmptyList$KtRecipe
- Find
Collections.emptyList/Set/Map()calls Collections.emptyList()(and itsemptySet/emptyMapsiblings) predate Kotlin's stdlib factories.emptyList<T>()/emptySet<T>()/emptyMap<K, V>()carry the same singletons, infer the type parameter at the call site, and don't drag thejava.util.Collectionsimport into Kotlin code.
- Find
- org.openrewrite.kotlin.interop.FindJavaUtilCollectionsFriction$KtRecipe
- Find
java.util.Collections/Arraysfactory usage inside Kotlin Arrays.asList,Collections.emptyList,Collections.singletonList, andCollections.unmodifiableList(plus Set/Map siblings) all have idiomatic Kotlin stdlib replacements —listOf,emptyList<T>(),setOf,mapOf, and.toList()/.toSet()/.toMap()for immutable copies.
- Find
- org.openrewrite.kotlin.interop.FindJavaUtilCollectionsSingleton$KtRecipe
- Find
Collections.singletonList/Set/Map(...)calls Collections.singletonList(x)is the Java idiom for a one-element read-only list.listOf(x)returns the same shape with cleaner syntax and consistent overload selection forsetOf/mapOf.
- Find
- org.openrewrite.kotlin.interop.FindJavaUtilCollectionsUnmodifiable$KtRecipe
- Find
Collections.unmodifiableList/Set/Map(...)wrappers Collections.unmodifiableList(x)wraps a collection in a view that throws on mutation. Kotlin'sx.toList()/x.toSet()/x.toMap()produce a fresh immutable copy — safer in concurrent contexts and removes the runtime wrapper.
- Find
- org.openrewrite.kotlin.interop.FindKotlinDefaultMethodInterface$KtRecipe
- Find interface declarations with default-method bodies
- An
interface I \{ fun foo() \{ … \} \}exposes the body to Java callers only on JDK-8+ targets and only when the Kotlin compiler emits real default methods (@JvmDefault/-Xjvm-default=all). Without the right compiler flags, the body lives in a syntheticDefaultImplsand Java sees an abstract method.
- org.openrewrite.kotlin.interop.FindLocalDateTimeNow$KtRecipe
- Find
LocalDateTime.now()/Instant.now()calls LocalDateTime.now()(and itsInstant/LocalDate/ZonedDateTimesiblings) read the system clock implicitly. Inject aClockand use the overloadLocalDateTime.now(clock)so tests can advance time deterministically.
- Find
- org.openrewrite.kotlin.interop.FindManualEqualsHashCode$KtRecipe
- Find classes with manual
equals/hashCodeoverrides —data classcandidate - A non-
dataclass that overrides bothequalsandhashCodeover its own fields is the canonical shapedata classexists for. Migrating givesequals/hashCode/toString/copy()/componentN()for free and removes the maintenance hazard of editing one of the two implementations.
- Find classes with manual
- org.openrewrite.kotlin.interop.FindManualGetterSetter$KtRecipe
- Find manual
getX()/setX(v)pairs in Kotlin classes - A class that exposes state through hand-rolled
getX()/setX(v)is reimplementing whatvar x: Talready provides — Kotlin generates the same accessors on the JVM. Migrate to a property and let the compiler emit the getter/setter pair.
- Find manual
- org.openrewrite.kotlin.interop.FindMissingJvmAnnotations$KtRecipe
- Find Kotlin declarations missing
@Jvm*interop annotations - Search-only bundle of declarations where the JVM-visible API surface would benefit from one of the
@JvmStatic/@JvmField/@JvmOverloads/@JvmName/@Throwsannotations. Each match is a candidate for review — none should be applied blindly, but the absence is the primary friction Java callers feel.
- Find Kotlin declarations missing
- org.openrewrite.kotlin.interop.FindMissingJvmFieldOnConst$KtRecipe
- Find
const val/ companionvaldeclarations missing@JvmField - A companion-object
valwithout@JvmFieldis exposed to Java asOuter.Companion.getX()— a getter on a synthetic singleton.@JvmFieldlifts the property to a true staticpublic finalfield onOuter, matching the Java idiom of named constants.
- Find
- org.openrewrite.kotlin.interop.FindMissingJvmNameOnExtensionFunction$KtRecipe
- Find top-level functions missing
@JvmName - Top-level Kotlin functions (including extension functions) compile to static methods on a
<FileName>Ktfacade — Java callers seeMyKotlinUtilsKt.bar(...)with a name the source file doesn't suggest.@JvmName("bar")on the function (or@file:JvmName("...")on the file) gives Java callers a name to bind against.
- Find top-level functions missing
- org.openrewrite.kotlin.interop.FindMissingJvmNameOnIsGetter$KtRecipe
- Find
val isXBoolean properties missing@get:JvmName - A Kotlin property named
isEnabledcompiles to a Java gettergetIsEnabled()— not the idiomaticisEnabled().@get:JvmName("isEnabled")(or naming the underlying property differently) restores the boolean-getter convention Java callers expect.
- Find
- org.openrewrite.kotlin.interop.FindMissingJvmOverloadsOnDefaults$KtRecipe
- Find functions with default parameters missing
@JvmOverloads - A Kotlin function with default arguments compiles to a single JVM method — Java callers see only the all-parameters form.
@JvmOverloadssynthesizes overloads at every default-parameter boundary so Java callers can drop trailing arguments naturally.
- Find functions with default parameters missing
- org.openrewrite.kotlin.interop.FindMissingJvmStaticInCompanion$KtRecipe
- Find
companion objectfunctions missing@JvmStatic - Without
@JvmStatic, Java callers must reach companion-object functions through the syntheticCompanionholder:Outer.Companion.foo(...). Adding@JvmStaticlifts the function toOuter.foo(...), matching what a Java reader expects from a class with static methods. Flag-only — sometimes the wrapper is intentional.
- Find
- org.openrewrite.kotlin.interop.FindMissingThrowsAnnotation$KtRecipe
- Find functions with
throwof a checked exception missing@Throws - Kotlin doesn't track checked exceptions, so a function that throws
IOExceptionlooks unchecked to a Java caller —try \{ … \} catch (IOException e) \{ … \}won't compile without@Throws(IOException::class)on the Kotlin declaration. Flag declarations that throw aThrowablewhose Java analog is checked.
- Find functions with
- org.openrewrite.kotlin.interop.FindOptionalFriction$KtRecipe
- Find
java.util.Optionalfriction inside Kotlin - Bundle every
Optional-related search: declarations that return or acceptOptional<T>,Optional.ofNullable(...)constructions, and.isPresent/.get()/.orElse(...)consumption sites. Once an upstream switchesOptional<T>toT?, each flagged call site collapses to a?:/?.let \{ … \}/!!expression.
- Find
- org.openrewrite.kotlin.interop.FindOptionalGet$KtRecipe
- Find
Optional.get()/orElseThrow()calls opt.get()is the unsafe unwrap that throwsNoSuchElementExceptionwhen the Optional is empty — the equivalent of Kotlin's!!on a nullable. Once the underlying value type isT?, the call site becomesvalue!!(or, better, arequireNotNull(value)).
- Find
- org.openrewrite.kotlin.interop.FindOptionalIsPresent$KtRecipe
- Find
Optional.isPresent/isEmptychecks opt.isPresentandopt.isEmptyare the Optional-flavored analogs ofx != nullandx == null. Once the upstream returnsT?instead ofOptional<T>, the check collapses to a Kotlin null comparison plus a smart-cast.
- Find
- org.openrewrite.kotlin.interop.FindOptionalOfNullable$KtRecipe
- Find
Optional.ofNullable(...)calls Optional.ofNullable(x)is the conversionT? -> Optional<T>— the very wrapping Kotlin's null type system was designed to make unnecessary. Inside Kotlin code, returnxand let?:/?.let \{ … \}express the absent-value branch directly.
- Find
- org.openrewrite.kotlin.interop.FindOptionalOrElse$KtRecipe
- Find
Optional.orElse(...)calls opt.orElse(default)is the Optional version ofvalue ?: default. Once the producer returnsT?directly, the elvis operator reads more naturally and produces tighter bytecode.
- Find
- org.openrewrite.kotlin.interop.FindOptionalParam$KtRecipe
- Find function parameters typed
Optional<T> - Taking
Optional<T>as a parameter is strictly weaker thanT?— every caller wraps the same value in an Optional, the function unwraps it, and the type system stops helping with null checking. The nullable parameter form composes with default arguments and?./?:operators.
- Find function parameters typed
- org.openrewrite.kotlin.interop.FindOptionalReturn$KtRecipe
- Find functions returning
Optional<T> - A Kotlin function that returns
Optional<T>forces every caller into a.isPresent/.get()dance the language already expresses withT?. Returning the nullable type instead lets the call site use?:,let, and smart-casts directly.
- Find functions returning
- org.openrewrite.kotlin.interop.FindOptionalUsage$KtRecipe
- Find
java.util.Optionalusage in Kotlin - Kotlin already models the absent-value case with the nullable type system (
T?).Optional<T>is a JVM-only crutch that's worth keeping at the Java boundary only — converting Kotlin-internalOptionalusage toT?improves null-safety and removes one wrapper allocation per call.
- Find
- org.openrewrite.kotlin.interop.FindReactiveInteropFriction$KtRecipe
- Find reactive-framework return types in Kotlin
- RxJava's
Observable/Flowable/Single/Maybe/Completableand Reactor'sMono/Fluxpredate Kotlin coroutines. Each match is a candidate for migration tosuspend fun(single-shot) orFlow<T>(stream); the correspondingkotlinx-coroutines-rx*/-reactoradapters cover the boundary to downstream Java callers.
- org.openrewrite.kotlin.interop.FindReactorPublisherInKotlin$KtRecipe
- Find Reactor
Mono/Fluxreturns in Kotlin - Project Reactor's
Mono<T>/Flux<T>are the Spring-WebFlux reactive types. Inside Kotlin code the canonical shape issuspend fun(forMono) andFlow<T>(forFlux);kotlinx-coroutines-reactorprovides the boundary adapters for downstream Reactor APIs.
- Find Reactor
- org.openrewrite.kotlin.interop.FindRequireNotNullOnJavaCall$KtRecipe
- Find
requireNotNull(javaCall())patterns requireNotNull(javaApi.something())is the safe-conversion idiom when a Java API returns an unannotated reference (platform typeT!). Once the underlying API is annotated@Nullable/@NotNull(or migrated to Kotlin), the wrapper either becomesjavaApi.something()!!or disappears entirely.
- Find
- org.openrewrite.kotlin.interop.FindRequiresOptInOnExperimentalApi$KtRecipe
- Find
@RequiresOptInannotation declarations @RequiresOptInmarks an annotation as a feature opt-in marker — every caller of an annotated declaration must acknowledge the experimental status via@OptIn(...). The marker itself is a stability contract worth surfacing for review whenever a new Kotlin-defined API claims experimental status.
- Find
- org.openrewrite.kotlin.interop.FindRxObservableInKotlin$KtRecipe
- Find
io.reactivex.Observable/Flowable/Single/Maybeusage in Kotlin - RxJava's reactive types predate Kotlin coroutines.
Flow<T>covers cold-streamObservable/Flowable,suspend funcoversSingle/Maybe, andkotlinx-coroutines-rx2/-rx3bridges the interop boundary. Inside Kotlin code, migrate to the coroutine equivalent.
- Find
- org.openrewrite.kotlin.interop.FindStaticHolderObject$KtRecipe
- Find
object Constants \{ const val A = ... \}static-constants holders - An
object Constantswhose body is exclusivelyconst valdeclarations is a holder for compile-time constants. Promote eachconst valto a top-level declaration — both forms inline identically at the JVM bytecode level, but the top-level form is one import shorter at every call site.
- Find
- org.openrewrite.kotlin.interop.FindStaticUtilObject$KtRecipe
- Find
object Utils \{ fun foo() = ... \}static-utility holders - An
object Utilswhose members are all functions (no state) is the Kotlin spelling of a Java static-utility class. Promote the functions to top-level — they're indexable, importable directly, and don't carry the synthetic singleton-load overhead Java callers see.
- Find
- org.openrewrite.kotlin.interop.FindStreamCollectorsToList$KtRecipe
- Find
stream.collect(Collectors.toList())calls - The
collect(Collectors.toList())terminal materializes aStreaminto aList. In Kotlin source, the natural shape isiterable.toList()(eager) orsequence.toList()(lazy) — both avoid theCollectormachinery and read at a glance.
- Find
- org.openrewrite.kotlin.interop.FindStreamFilterMap$KtRecipe
- Find
stream.filter(...).map(...)chains - A
filter().map()chain onStreamis structurally identical to the same chain onIterable/Sequence— the Stream machinery just adds Collector requirements at the terminal. Migrate to Kotlin collections; if laziness matters, useasSequence()once at the head.
- Find
- org.openrewrite.kotlin.interop.FindStreamFriction$KtRecipe
- Find
java.util.stream.Streamfriction inside Kotlin - Bundle every Stream-related search: declarations returning
Stream<T>,Collectors.toList()terminals,filter.mapchains, andStream.ofconstructions. Each match has a Kotlin equivalent inSequence/Iterable/Flowthat's idiomatic at the same call site.
- Find
- org.openrewrite.kotlin.interop.FindStreamOfCall$KtRecipe
- Find
Stream.of(...)calls Stream.of(...)is a varargs-to-Stream constructor used to bootstrap a Stream pipeline. In Kotlin,sequenceOf(...)(lazy) orlistOf(...)(eager) cover the same uses without committing to the Stream type at the boundary.
- Find
- org.openrewrite.kotlin.interop.FindStreamReturn$KtRecipe
- Find functions returning
java.util.stream.Stream<T> Stream<T>is the Java 8 lazy-pipeline type — single-use, no built-in cancellation, only consumable throughcollect. In Kotlin,Sequence<T>is the equivalent for lazy iterable pipelines;List<T>andFlow<T>cover the eager and async-lazy cases respectively.
- Find functions returning
- org.openrewrite.kotlin.interop.FindSystemCurrentTimeMillis$KtRecipe
- Find
System.currentTimeMillis()calls - Direct
System.currentTimeMillis()calls are convenient but couple the call site to wall-clock time, making tests deterministic only by mocking the whole class. Inject aClock(or, on JDK 8+,java.time.Clock) and read time through it.
- Find
- org.openrewrite.kotlin.interop.ImproveKotlinInterop$KtRecipe
- Apply Java↔Kotlin interop rewrites
- Autofix-only interop bundle: collapses
Optional.of(x).get()round-trips that have a direct value equivalent. Excludes the search-onlyFind*recipes (Optional / CompletableFuture / Stream / Collections factories, Jvm-annotation gaps, Java-style call shapes, reactive return types) — for diff-only output, use this recipe instead.
- org.openrewrite.kotlin.interop.Interop$KtRecipe
- Improve Java↔Kotlin interop ergonomics
- Opinionated bundle of every interop recipe in this module: the
Optional.of(x).get()collapse plus search-only flags for Java idioms that have first-class Kotlin replacements (Optional, CompletableFuture, Stream, Collections factories,@Jvm*-annotation gaps, Java-style call shapes, reactive return types, non-injected clocks). For diff-only output, useImproveKotlinInterop.
- org.openrewrite.kotlin.interop.UseValueForOptionalOfGet$KtRecipe
- Use
xinstead ofOptional.of(x).get() Optional.of(x).get()is a JVM-style round-trip that's equivalent tox. In Kotlin you'd model the same thing with a non-nullablexdirectly, and Java callers already see the same value via the cross-language binding.
- Use
- org.openrewrite.kotlin.logging.FindCompanionLoggerWithoutPrivate$KtRecipe
- Find companion-object loggers missing
private - A companion-object
val log = LoggerFactory.getLogger(...)withoutprivateis exposed to Java callers asFoo.Companion.getLog()— they can mutate the logger reference (well, not the val, but the visibility is wider than needed). Mark itprivate.
- Find companion-object loggers missing
- org.openrewrite.kotlin.logging.FindEagerLogMessages$KtRecipe
- Find eager log-message construction
- Bundles the trace/debug/info/warn/error eager-interpolation and string-concatenation finders. Every hit is a candidate for migration to kotlin-logging's lambda form (
log.debug \{ "..." \}) or SLF4J's parameterized form (log.debug("x=\{\}", x)).
- org.openrewrite.kotlin.logging.FindEagerStringInterpolationInLogDebug$KtRecipe
- Find eager string interpolation in
log.debug(...) log.debug("x=$x")evaluates the template (including anytoString()work onx) before the call even reaches the logger — if debug is disabled, the work is wasted. With kotlin-logging uselog.debug \{ "x=$x" \}; with SLF4J use the parameterized formlog.debug("x=\{\}", x).
- Find eager string interpolation in
- org.openrewrite.kotlin.logging.FindEagerStringInterpolationInLogError$KtRecipe
- Find eager string interpolation in
log.error(...) - Error logs almost always fire, so cost is rarely the issue — but a parameterized message keeps the template stable for log aggregators that group errors by template hash, and lets the throwable argument flow through SLF4J's last-arg-is-Throwable convention cleanly.
- Find eager string interpolation in
- org.openrewrite.kotlin.logging.FindEagerStringInterpolationInLogInfo$KtRecipe
- Find eager string interpolation in
log.info(...) log.info("x=$x")evaluates the template eagerly. If your application turns info off in production, thetoString()calls inside the template still run. Use the lambda form (kotlin-logging) or the SLF4J\{\}placeholder form.
- Find eager string interpolation in
- org.openrewrite.kotlin.logging.FindEagerStringInterpolationInLogTrace$KtRecipe
- Find eager string interpolation in
log.trace(...) log.trace("x=$x")evaluates the template (including anytoString()work onx) before the call even reaches the logger — if trace is disabled, the work is wasted. With kotlin-logging uselog.trace \{ "x=$x" \}; with SLF4J use the parameterized formlog.trace("x=\{\}", x).
- Find eager string interpolation in
- org.openrewrite.kotlin.logging.FindEagerStringInterpolationInLogWarn$KtRecipe
- Find eager string interpolation in
log.warn(...) - Warning logs are usually enabled in production, so eager interpolation is less of a hot-path issue — but the parameterized form (
log.warn("x=\{\}", x)) still keeps the message template stable for log aggregators that group by template hash.
- Find eager string interpolation in
- org.openrewrite.kotlin.logging.FindIsDebugEnabledGuard$KtRecipe
- Find
if (log.isDebugEnabled) ...guards if (log.isDebugEnabled) log.debug(...)is the Java-1.4-era idiom — replaced by kotlin-logging'slog.debug \{ "..." \}lambda or SLF4J'slog.debug("x=\{\}", x)placeholder form. Either defers the work without the explicit guard.
- Find
- org.openrewrite.kotlin.logging.FindIsErrorEnabledGuard$KtRecipe
- Find
if (log.isErrorEnabled) ...guards - Errors are practically always enabled. The guard suggests the code was once shared with debug/trace machinery — drop it.
- Find
- org.openrewrite.kotlin.logging.FindIsInfoEnabledGuard$KtRecipe
- Find
if (log.isInfoEnabled) ...guards - Info is usually on in production, so the guard rarely saves anything. If you keep it, prefer the lambda or
\{\}-placeholder form for consistency with debug/trace.
- Find
- org.openrewrite.kotlin.logging.FindIsTraceEnabledGuard$KtRecipe
- Find
if (log.isTraceEnabled) ...guards - With kotlin-logging's lambda form (
log.trace \{ "..." \}) the level-check is built into the call — wrapping it inif (log.isTraceEnabled)repeats the check. With SLF4J's parameterized form, the placeholder substitution is also deferred, so the explicit guard is only worthwhile if the argument construction itself is expensive.
- Find
- org.openrewrite.kotlin.logging.FindIsWarnEnabledGuard$KtRecipe
- Find
if (log.isWarnEnabled) ...guards - Warning logs are nearly always enabled. The guard is almost certainly dead code — drop it and use the parameterized form.
- Find
- org.openrewrite.kotlin.logging.FindJulLoggerGetLogger$KtRecipe
- Find
java.util.logging.Logger.getLogger(...)calls java.util.loggingships with the JDK but lacks the structured-logging, MDC, and parameterized-message ergonomics of SLF4J or kotlin-logging. Migratej.u.l.Logger.getLogger(...)toLoggerFactory.getLogger(...)(SLF4J) orKotlinLogging.logger \{ \}(kotlin-logging).
- Find
- org.openrewrite.kotlin.logging.FindJulLoggerLog$KtRecipe
- Find
julLogger.log(level, msg)and level-specificjulLogger.fine/info/severe/...calls - Each
j.u.l.Logger.log(Level, ...)call (and the level-specific shortcutsfine/info/warning/severe/config) needs to be re-expressed against SLF4J/kotlin-logging when migrating. Flag for review.
- Find
- org.openrewrite.kotlin.logging.FindLegacyLoggerLibraries$KtRecipe
- Find legacy logger-library usage
- Bundles
java.util.loggingand log4j 1.x finders. Both predate structured logging and should migrate to SLF4J or kotlin-logging.
- org.openrewrite.kotlin.logging.FindLog4j1Logger$KtRecipe
- Find
org.apache.log4j.Loggerreferences - Log4j 1.x reached end-of-life in 2015 and has known unfixed vulnerabilities. Migrate to log4j 2.x (
org.apache.logging.log4j.Logger) or SLF4J. The migration is mechanical for the basic getLogger / log methods, but custom appenders and layouts need a manual rewrite.
- Find
- org.openrewrite.kotlin.logging.FindLoggerDeclarationSmells$KtRecipe
- Find logger declaration smells
- Bundles
logvsloggernaming, missingprivateon companion-object loggers, and instance-field loggers (one per allocation). The shape consensus isprivate val log = LoggerFactory.getLogger(...)in a companion object.
- org.openrewrite.kotlin.logging.FindLoggerFactoryGetLogger$KtRecipe
- Find
LoggerFactory.getLogger(SomeClass::class.java)calls LoggerFactory.getLogger(Foo::class.java)is the Java idiom Kotlin code inherited. kotlin-logging'sKotlinLogging.logger \{ \}infers the enclosing class automatically (via the stack frame at site of declaration) and avoids the::class.javareflection round-trip.
- Find
- org.openrewrite.kotlin.logging.FindLoggerFactoryGetLoggerWithStringName$KtRecipe
- Find
LoggerFactory.getLogger("some-name")calls - A string logger name is fine for named/structured loggers but is a smell when the string happens to spell out a class FQN — that should be
getLogger(Foo::class.java)(orKotlinLogging.logger \{ \}) so renames track. Flag for human review.
- Find
- org.openrewrite.kotlin.logging.FindLoggerFactoryGetLoggerWithThisClass$KtRecipe
- Find
LoggerFactory.getLogger(this::class.java)calls this::class.javaresolves the runtime class — fine for non-final classes, but kotlin-logging'sKotlinLogging.logger \{ \}already infers the declaring class lexically and avoids the runtime reflection. Either form binds the same logger name for a final class.
- Find
- org.openrewrite.kotlin.logging.FindLoggerFactoryMigrationCandidates$KtRecipe
- Find
LoggerFactory.getLoggermigration candidates - Bundles the SLF4J
LoggerFactory.getLoggershapes — class-literal,this::class.java, and string-name. Each is a candidate for kotlin-logging'sKotlinLogging.logger \{ \}.
- Find
- org.openrewrite.kotlin.logging.FindLoggerFieldNamedLog$KtRecipe
- Find top-level/companion logger fields named
log - Both
logandloggerare common — pick one and stick with it across the codebase. The naming convention is the only thing that lets a reader skim a file and spot the logger declaration in two seconds. Flaglog-named declarations so the team can confirm the project convention.
- Find top-level/companion logger fields named
- org.openrewrite.kotlin.logging.FindLoggerGuards$KtRecipe
- Find redundant logger level-check guards
- Bundles
if (log.isXxxEnabled) ...finders. With kotlin-logging's lambda form or SLF4J's\{\}placeholder form, the level check is built into the call.
- org.openrewrite.kotlin.logging.FindLoggerNotInCompanion$KtRecipe
- Find loggers declared as instance fields (one per object)
- An instance-field
val log = LoggerFactory.getLogger(...)allocates one logger per object. Logger factories cache by name, so the runtime cost is one extra map lookup per allocation — but the conventional shape is aprivate val login the companion object (or a top-levelprivate val logfor top-level functions), so a per-instance logger usually reflects accidental code placement.
- org.openrewrite.kotlin.logging.FindPrintAndPrintStackTrace$KtRecipe
- Find
println/System.err.println/printStackTrace - Bundles the unstructured-output finders. Each call writes outside the logger pipeline, so it bypasses level filters, MDCs, and structured sinks.
- Find
- org.openrewrite.kotlin.logging.FindPrintErr$KtRecipe
- Find
System.err.println(...)calls System.err.printlnwrites to stderr — better than stdout for errors, but still bypasses whatever structured logger the application uses. Route throughlog.error("...", throwable)so log aggregators see the context.
- Find
- org.openrewrite.kotlin.logging.FindPrintStackTrace$KtRecipe
- Find
Throwable.printStackTrace()calls e.printStackTrace()writes the throwable's stack frames straight toSystem.err, bypassing whatever logger the application configures. Uselog.error("context", e)so the throwable flows through SLF4J's last-arg-is-Throwable convention and ends up in the same sink as the rest of your errors.
- Find
- org.openrewrite.kotlin.logging.FindPrintln$KtRecipe
- Find
println(...)calls printlnwrites to stdout, which in containerized deployments lands in log files without structure, level filtering, or correlation IDs. Replace with a proper logger; if this is a CLI tool, consider the kotlin-logging level filter so tests can silence noisy output.
- Find
- org.openrewrite.kotlin.logging.FindStringConcatInLogDebug$KtRecipe
- Find string concatenation in
log.debug(...) log.debug("x=" + x)performs the concatenation eagerly. Use kotlin-logging'slog.debug \{ "x=$x" \}lambda form or SLF4J'slog.debug("x=\{\}", x)placeholder form.
- Find string concatenation in
- org.openrewrite.kotlin.logging.FindStringConcatInLogError$KtRecipe
- Find string concatenation in
log.error(...) log.error("failed: " + e)mixes the throwable into the message string, losing the stack trace. Use the parameterized form with the throwable as the last argument:log.error("failed", e).
- Find string concatenation in
- org.openrewrite.kotlin.logging.FindStringConcatInLogInfo$KtRecipe
- Find string concatenation in
log.info(...) log.info("x=" + x)is the Java-1.4-era logging idiom — replaced in SLF4J bylog.info("x=\{\}", x)so the template is stable and the work is deferred.
- Find string concatenation in
- org.openrewrite.kotlin.logging.FindStringConcatInLogTrace$KtRecipe
- Find string concatenation in
log.trace(...) log.trace("x=" + x)performs the concatenation (and thetoStringonx) before the call — wasted work if trace is disabled. Use the lambda form or SLF4J\{\}placeholders.
- Find string concatenation in
- org.openrewrite.kotlin.logging.FindStringConcatInLogWarn$KtRecipe
- Find string concatenation in
log.warn(...) log.warn("x=" + x)does the concatenation up front. Use the parameterized form so log aggregators can group by message template.
- Find string concatenation in
- org.openrewrite.kotlin.logging.FindThrowablePrintStackTraceWithStream$KtRecipe
- Find
e.printStackTrace(out)calls - Writing the stack trace to a
PrintStream/PrintWriteris the Java idiom for re-routing it manually. With a structured logger you don't need to —log.error("context", e)already carries the throwable to the configured sink. Review whether the explicit redirection still serves a purpose.
- Find
- org.openrewrite.kotlin.logging.Logging$KtRecipe
- Find Kotlin logging smells
- Search-only recipes for SLF4J, kotlin-logging,
java.util.logging, log4j 1.x, andprintln/printStackTraceusage. Covers eager-message construction (string templates and concatenation), redundant level-check guards,LoggerFactory.getLoggershapes that could beKotlinLogging.logger \{ \}, unstructured-output calls that bypass the logger, and logger-declaration smells (naming, visibility, instance-field placement).
- org.openrewrite.kotlin.migrate.Kotlin1To2$KtRecipe
- Migrate to Kotlin 2.x
- Modernizes a Kotlin 1.x codebase for Kotlin 2.x: replaces stdlib APIs deprecated between 1.4 and 2.0 with their modern equivalents, swaps JVM-only
java.lang/java.utilhelpers for multiplatform Kotlin extensions, migratesinline classto@JvmInline value class, and removes@OptInannotations for experimental markers that have since graduated to stable.
- org.openrewrite.kotlin.migrate.RemoveRedundantOptIns$KtRecipe
- Remove redundant
@OptInannotations - Removes
@OptInannotations for stdlib experimental markers that have since graduated to stable (ExperimentalStdlibApi,ExperimentalTime,ExperimentalUnsignedTypes,ExperimentalPathApi). The annotations no longer suppress anything and just add noise.
- Remove redundant
- org.openrewrite.kotlin.migrate.UseAppendLine$KtRecipe
- Use
appendLine()instead ofappendln() Appendable.appendln()was deprecated in Kotlin 1.4 in favor ofappendLine()(consistent naming withReader.readLine()).
- Use
- org.openrewrite.kotlin.migrate.UseAppendLineAny$KtRecipe
- Use
appendLine(value)instead ofappendln(value)(Any?) StringBuilder.appendln(value: Any?)was deprecated in Kotlin 1.4 in favor ofappendLine(value: Any?).
- Use
- org.openrewrite.kotlin.migrate.UseAppendLineChar$KtRecipe
- Use
appendLine(char)instead ofappendln(char) Appendable.appendln(value: Char)was deprecated in Kotlin 1.4 in favor ofappendLine(value: Char).
- Use
- org.openrewrite.kotlin.migrate.UseAppendLineCharSequence$KtRecipe
- Use
appendLine(cs)instead ofappendln(cs)(CharSequence) Appendable.appendln(value: CharSequence?)was deprecated in Kotlin 1.4 in favor ofappendLine(value: CharSequence?).
- Use
- org.openrewrite.kotlin.migrate.UseAppendLineWithValue$KtRecipe
- Use
appendLine(value)instead ofappendln(value) Appendable.appendln(value)was deprecated in Kotlin 1.4 in favor ofappendLine(value).
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentDeepEquals$KtRecipe
- Use
Array.contentDeepEquals()instead ofArrays.deepEquals(a, b) java.util.Arrays.deepEquals(a, b)recursively compares nested arrays;a.contentDeepEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentDeepHashCode$KtRecipe
- Use
Array.contentDeepHashCode()instead ofArrays.deepHashCode(arr) java.util.Arrays.deepHashCode(arr)recursively hashes nested arrays;arr.contentDeepHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentDeepToString$KtRecipe
- Use
Array.contentDeepToString()instead ofArrays.deepToString(arr) java.util.Arrays.deepToString(arr)recursively unrolls nested arrays;arr.contentDeepToString()is the multiplatform Kotlin extension producing the same representation.
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentEquals$KtRecipe
- Use
Array.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: Object[], b: Object[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension. For nested arrays use the deep variant.
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentHashCode$KtRecipe
- Use
Array.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: Object[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension. For nested arrays use the deep variant.
- Use
- org.openrewrite.kotlin.migrate.UseArrayContentToString$KtRecipe
- Use
Array.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: Object[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension. For nested arrays use the deep variant.
- Use
- org.openrewrite.kotlin.migrate.UseBooleanArrayContentEquals$KtRecipe
- Use
BooleanArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: boolean[], b: boolean[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseBooleanArrayContentHashCode$KtRecipe
- Use
BooleanArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: boolean[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseBooleanArrayContentToString$KtRecipe
- Use
BooleanArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: boolean[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseBooleanArrayCopyOf$KtRecipe
- Use
BooleanArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: boolean[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseBooleanArrayFill$KtRecipe
- Use
BooleanArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: boolean[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayBinarySearch$KtRecipe
- Use
ByteArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: byte[], key: Byte)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayContentEquals$KtRecipe
- Use
ByteArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: byte[], b: byte[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayContentHashCode$KtRecipe
- Use
ByteArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: byte[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayContentToString$KtRecipe
- Use
ByteArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: byte[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayCopyOf$KtRecipe
- Use
ByteArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: byte[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArrayFill$KtRecipe
- Use
ByteArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: byte[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseByteArraySort$KtRecipe
- Use
ByteArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: byte[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCapitalize$KtRecipe
- Use
replaceFirstChar \{ … \}instead ofcapitalize() String.capitalize()was deprecated in Kotlin 1.5 in favor of the locale-explicitreplaceFirstChar \{ if (it.isLowerCase()) it.titlecase() else it.toString() \}.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayBinarySearch$KtRecipe
- Use
CharArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: char[], key: Char)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayContentEquals$KtRecipe
- Use
CharArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: char[], b: char[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayContentHashCode$KtRecipe
- Use
CharArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: char[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayContentToString$KtRecipe
- Use
CharArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: char[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension. Note this produces a bracketed list — useString(arr)if you want a String view of the characters.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayCopyOf$KtRecipe
- Use
CharArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: char[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharArrayFill$KtRecipe
- Use
CharArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: char[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharArraySort$KtRecipe
- Use
CharArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: char[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseCharCode$KtRecipe
- Use
Char.codeinstead ofChar.toInt() Char.toInt()was deprecated in Kotlin 1.5; the replacementChar.codemakes the conversion-to-codepoint intent explicit (the old name collided withNumber.toInt()).
- Use
- org.openrewrite.kotlin.migrate.UseCharCodeAsByte$KtRecipe
- Use
Char.code.toByte()instead ofChar.toByte() Char.toByte()was deprecated in Kotlin 1.5 in favor of going throughChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharCodeAsDouble$KtRecipe
- Use
Char.code.toDouble()instead ofChar.toDouble() Char.toDouble()was deprecated in Kotlin 1.5 in favor of going throughChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharCodeAsFloat$KtRecipe
- Use
Char.code.toFloat()instead ofChar.toFloat() Char.toFloat()was deprecated in Kotlin 1.5 in favor of going throughChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharCodeAsLong$KtRecipe
- Use
Char.code.toLong()instead ofChar.toLong() Char.toLong()was deprecated in Kotlin 1.5 in favor of going throughChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharCodeAsShort$KtRecipe
- Use
Char.code.toShort()instead ofChar.toShort() Char.toShort()was deprecated in Kotlin 1.5 in favor of going throughChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharCompareTo$KtRecipe
- Use
Char.compareToinstead ofjava.lang.Character.compare Character.compare(a, b)becomesa.compareTo(b)— the multiplatform receiver call onCharreturns the sameIntordering.
- Use
- org.openrewrite.kotlin.migrate.UseCharCtor$KtRecipe
- Use
Char(int)instead ofInt.toChar() Int.toChar()was deprecated in Kotlin 1.5; the replacementChar(int)constructor expresses the codepoint-to-char intent symmetrically withChar.code.
- Use
- org.openrewrite.kotlin.migrate.UseCharDigitToInt$KtRecipe
- Use
Char.digitToInt(radix)instead ofCharacter.digit(c, radix) Character.digit(c, radix)returns -1 for non-digits; the Kotlin extensionc.digitToInt(radix)throwsIllegalArgumentExceptioninstead. Usec.digitToIntOrNull(radix)if the JVM null-on-failure semantic is required.
- Use
- org.openrewrite.kotlin.migrate.UseCharIsDefined$KtRecipe
- Use
Char.isDefined()instead ofCharacter.isDefined(c) - Prefer the multiplatform Kotlin extension
c.isDefined()over the JVM-onlyCharacter.isDefined(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsDigit$KtRecipe
- Use
Char.isDigit()instead ofCharacter.isDigit(c) - Java's
Character.isDigit(c)is JVM-only; the Kotlin extensionc.isDigit()is multiplatform and reads more naturally as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseCharIsHighSurrogate$KtRecipe
- Use
Char.isHighSurrogate()instead ofCharacter.isHighSurrogate(c) - Prefer the multiplatform Kotlin extension
c.isHighSurrogate()over the JVM-onlyCharacter.isHighSurrogate(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsISOControl$KtRecipe
- Use
Char.isISOControl()instead ofCharacter.isISOControl(c) - Prefer the multiplatform Kotlin extension
c.isISOControl()over the JVM-onlyCharacter.isISOControl(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsLetter$KtRecipe
- Use
Char.isLetter()instead ofCharacter.isLetter(c) - Prefer the multiplatform Kotlin extension
c.isLetter()over the JVM-onlyCharacter.isLetter(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsLetterOrDigit$KtRecipe
- Use
Char.isLetterOrDigit()instead ofCharacter.isLetterOrDigit(c) - Prefer the multiplatform Kotlin extension
c.isLetterOrDigit()over the JVM-onlyCharacter.isLetterOrDigit(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsLowSurrogate$KtRecipe
- Use
Char.isLowSurrogate()instead ofCharacter.isLowSurrogate(c) - Prefer the multiplatform Kotlin extension
c.isLowSurrogate()over the JVM-onlyCharacter.isLowSurrogate(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsLowerCase$KtRecipe
- Use
Char.isLowerCase()instead ofCharacter.isLowerCase(c) - Prefer the multiplatform Kotlin extension
c.isLowerCase()over the JVM-onlyCharacter.isLowerCase(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsTitleCase$KtRecipe
- Use
Char.isTitleCase()instead ofCharacter.isTitleCase(c) - Prefer the multiplatform Kotlin extension
c.isTitleCase()over the JVM-onlyCharacter.isTitleCase(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsUpperCase$KtRecipe
- Use
Char.isUpperCase()instead ofCharacter.isUpperCase(c) - Prefer the multiplatform Kotlin extension
c.isUpperCase()over the JVM-onlyCharacter.isUpperCase(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharIsWhitespace$KtRecipe
- Use
Char.isWhitespace()instead ofCharacter.isWhitespace(c) - Prefer the multiplatform Kotlin extension
c.isWhitespace()over the JVM-onlyCharacter.isWhitespace(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharLowercaseCharForCharacter$KtRecipe
- Use
Char.lowercaseChar()instead ofCharacter.toLowerCase(c) - Prefer the multiplatform Kotlin extension
c.lowercaseChar()over the JVM-onlyCharacter.toLowerCase(c).
- Use
- org.openrewrite.kotlin.migrate.UseCharToString$KtRecipe
- Use
Char.toString()instead ofCharacter.toString(c) java.lang.Character.toString(c)is JVM-only;c.toString()is the multiplatform receiver call and produces the same one-characterString.
- Use
- org.openrewrite.kotlin.migrate.UseCharUppercaseCharForCharacter$KtRecipe
- Use
Char.uppercaseChar()instead ofCharacter.toUpperCase(c) - Prefer the multiplatform Kotlin extension
c.uppercaseChar()over the JVM-onlyCharacter.toUpperCase(c).
- Use
- org.openrewrite.kotlin.migrate.UseCollectionMax$KtRecipe
- Use
Collection.max()instead ofCollections.max(coll) java.util.Collections.max(coll)is JVM-only; Kotlin'sCollection.max()extension is multiplatform and reads as a receiver call. Both throwNoSuchElementExceptionon an empty collection.
- Use
- org.openrewrite.kotlin.migrate.UseCollectionMin$KtRecipe
- Use
Collection.min()instead ofCollections.min(coll) java.util.Collections.min(coll)is JVM-only; Kotlin'sCollection.min()extension is multiplatform and reads as a receiver call. Both throwNoSuchElementExceptionon an empty collection.
- Use
- org.openrewrite.kotlin.migrate.UseConcatToString$KtRecipe
- Use
CharArray.concatToString()instead ofString(charArray) - The
String(CharArray)constructor is JVM-only;charArray.concatToString()is the multiplatform Kotlin extension producing the sameString.
- Use
- org.openrewrite.kotlin.migrate.UseDecapitalize$KtRecipe
- Use
replaceFirstChar \{ it.lowercase() \}instead ofdecapitalize() String.decapitalize()was deprecated in Kotlin 1.5 in favor ofreplaceFirstChar \{ it.lowercase() \}.
- Use
- org.openrewrite.kotlin.migrate.UseDecodeToString$KtRecipe
- Use
ByteArray.decodeToString()instead ofString(byteArray) - The
String(ByteArray)constructor is JVM-only and uses the platform default charset;byteArray.decodeToString()is the multiplatform Kotlin extension and always uses UTF-8.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayBinarySearch$KtRecipe
- Use
DoubleArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: double[], key: Double)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayContentEquals$KtRecipe
- Use
DoubleArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: double[], b: double[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension. LikeArrays.equals, NaN compares equal to NaN.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayContentHashCode$KtRecipe
- Use
DoubleArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: double[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayContentToString$KtRecipe
- Use
DoubleArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: double[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayCopyOf$KtRecipe
- Use
DoubleArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: double[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArrayFill$KtRecipe
- Use
DoubleArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: double[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleArraySort$KtRecipe
- Use
DoubleArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: double[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleIEEErem$KtRecipe
- Use
Double.IEEEreminstead ofjava.lang.Math.IEEEremainder Math.IEEEremainder(x, y)becomesx.IEEErem(y)— the multiplatform Kotlin extension, also shorter.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleNextDown$KtRecipe
- Use
Double.nextDown()instead ofjava.lang.Math.nextDown Math.nextDown(x)becomesx.nextDown()— multiplatform Kotlin extension onDouble.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleNextTowards$KtRecipe
- Use
Double.nextTowards()instead ofjava.lang.Math.nextAfter Math.nextAfter(x, y)becomesx.nextTowards(y)— multiplatform Kotlin extension onDouble. Only the(Double, Double)overload is rewritten; the(Float, Double)overload's mixed types don't line up with Kotlin'sFloat.nextTowards(Float).
- Use
- org.openrewrite.kotlin.migrate.UseDoubleNextUp$KtRecipe
- Use
Double.nextUp()instead ofjava.lang.Math.nextUp Math.nextUp(x)becomesx.nextUp()— multiplatform Kotlin extension onDouble.
- Use
- org.openrewrite.kotlin.migrate.UseDoublePow$KtRecipe
- Use
Double.powinstead ofjava.lang.Math.pow Math.pow(x, y)is JVM-only; the Kotlin extensionx.pow(y)reads as a receiver call and is multiplatform.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleRoundToLong$KtRecipe
- Use
Double.roundToLong()instead ofjava.lang.Math.round Math.round(d: Double): Longbecomesd.roundToLong()as a multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseDoubleWithSign$KtRecipe
- Use
Double.withSigninstead ofjava.lang.Math.copySign Math.copySign(magnitude, sign)becomesmagnitude.withSign(sign)— the multiplatform Kotlin extension expresses the same magnitude/sign combination as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseEnumEntries$KtRecipe
- Use
enumEntries<T>()instead ofenumValues<T>() - Kotlin 1.9 introduced
enumEntries<T>()returning a stableEnumEntries<T>view. Prefer it overenumValues<T>(), which allocates a fresh array on each call.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayBinarySearch$KtRecipe
- Use
FloatArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: float[], key: Float)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayContentEquals$KtRecipe
- Use
FloatArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: float[], b: float[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension. LikeArrays.equals, NaN compares equal to NaN.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayContentHashCode$KtRecipe
- Use
FloatArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: float[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayContentToString$KtRecipe
- Use
FloatArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: float[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayCopyOf$KtRecipe
- Use
FloatArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: float[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArrayFill$KtRecipe
- Use
FloatArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: float[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatArraySort$KtRecipe
- Use
FloatArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: float[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseFloatRoundToInt$KtRecipe
- Use
Float.roundToInt()instead ofjava.lang.Math.round Math.round(f: Float): Intbecomesf.roundToInt()as a multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayBinarySearch$KtRecipe
- Use
IntArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: int[], key: Int)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayContentEquals$KtRecipe
- Use
IntArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: int[], b: int[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayContentHashCode$KtRecipe
- Use
IntArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: int[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension and produces the same value.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayContentToString$KtRecipe
- Use
IntArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: int[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension producing the same bracketed representation.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayCopyOf$KtRecipe
- Use
IntArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: int[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseIntArrayFill$KtRecipe
- Use
IntArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: int[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseIntArraySort$KtRecipe
- Use
IntArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: int[])is JVM-only;arr.sort()is the multiplatform Kotlin extension that sorts in place ascending.
- Use
- org.openrewrite.kotlin.migrate.UseIntCompareTo$KtRecipe
- Use
Int.compareToinstead ofjava.lang.Integer.compare Integer.compare(a, b)is the JVM-only static comparator; the multiplatforma.compareTo(b)reads as a receiver call and returns the sameIntordering.
- Use
- org.openrewrite.kotlin.migrate.UseIntCountLeadingZeroBits$KtRecipe
- Use
Int.countLeadingZeroBits()instead ofInteger.numberOfLeadingZeros Integer.numberOfLeadingZeros(i)becomesi.countLeadingZeroBits()— the multiplatform Kotlin extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseIntCountOneBits$KtRecipe
- Use
Int.countOneBits()instead ofjava.lang.Integer.bitCount Integer.bitCount(i)is the JVM-only popcount; the multiplatformi.countOneBits()extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseIntCountTrailingZeroBits$KtRecipe
- Use
Int.countTrailingZeroBits()instead ofInteger.numberOfTrailingZeros Integer.numberOfTrailingZeros(i)becomesi.countTrailingZeroBits()— the multiplatform Kotlin extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseIntDigitToChar$KtRecipe
- Use
Int.digitToChar(radix)instead ofCharacter.forDigit(digit, radix) Character.forDigit(digit, radix)returns the null'\u0000'for invalid input; the Kotlin extensiondigit.digitToChar(radix)throwsIllegalArgumentExceptioninstead.
- Use
- org.openrewrite.kotlin.migrate.UseIntFloorDiv$KtRecipe
- Use
Int.floorDivinstead ofjava.lang.Math.floorDiv Math.floorDiv(a, b)becomesa.floorDiv(b)— the multiplatform Kotlin extension onInt.
- Use
- org.openrewrite.kotlin.migrate.UseIntMod$KtRecipe
- Use
Int.mod()instead ofjava.lang.Math.floorMod Math.floorMod(a, b)becomesa.mod(b). Kotlin'sInt.moduses floored-division semantics — the result is non-negative when the divisor is positive — matchingMath.floorMod. Reads as a receiver call and is multiplatform.
- Use
- org.openrewrite.kotlin.migrate.UseIntRotateLeft$KtRecipe
- Use
Int.rotateLeft(n)instead ofInteger.rotateLeft(i, n) Integer.rotateLeft(i, n)is JVM-only; the multiplatformi.rotateLeft(n)extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseIntRotateRight$KtRecipe
- Use
Int.rotateRight(n)instead ofInteger.rotateRight(i, n) Integer.rotateRight(i, n)is JVM-only; the multiplatformi.rotateRight(n)extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseIntToString$KtRecipe
- Use
Int.toString()instead ofInteger.toString(i) Integer.toString(i)is the JVM-only spelling;i.toString()reads as a receiver call and is multiplatform.
- Use
- org.openrewrite.kotlin.migrate.UseIntToStringBinary$KtRecipe
- Use
Int.toString(2)instead ofInteger.toBinaryString Integer.toBinaryString(i)is JVM-only; the multiplatformi.toString(2)produces the same binary text.
- Use
- org.openrewrite.kotlin.migrate.UseIntToStringHex$KtRecipe
- Use
Int.toString(16)instead ofInteger.toHexString Integer.toHexString(i)is JVM-only; the multiplatformi.toString(16)produces the same hexadecimal text.
- Use
- org.openrewrite.kotlin.migrate.UseIntToStringOctal$KtRecipe
- Use
Int.toString(8)instead ofInteger.toOctalString Integer.toOctalString(i)is JVM-only; the multiplatformi.toString(8)produces the same octal text.
- Use
- org.openrewrite.kotlin.migrate.UseIntToStringWithRadix$KtRecipe
- Use
Int.toString(radix)instead ofInteger.toString(i, radix) Integer.toString(i, radix)is the JVM-only spelling;i.toString(radix)is the multiplatform Kotlin receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinArray$KtRecipe
- Use Kotlin array extensions instead of
java.util.Arrays - Replaces JVM-only
java.util.Arraysstatic helpers with the multiplatform Kotlin extensions on each primitive array (andArray<*>):contentToString(),contentEquals(),contentHashCode(),fill(),sort(),binarySearch(),copyOf(), the deep variants for nested arrays, and theString(charArray)/String(byteArray)constructors that becomecharArray.concatToString()/byteArray.decodeToString().
- Use Kotlin array extensions instead of
- org.openrewrite.kotlin.migrate.UseKotlinChar$KtRecipe
- Use
Charextensions instead ofjava.lang.Character - Replaces JVM-only static helpers on
java.lang.Character(isDigit(c),isLetter(c),toUpperCase(c),digit(c, radix),compare(a, b),toString(c), surrogate predicates) with the multiplatform Kotlin extensions onChar(c.isDigit(),c.uppercaseChar(),c.digitToInt(radix), …).
- Use
- org.openrewrite.kotlin.migrate.UseKotlinCollections$KtRecipe
- Use Kotlin collection extensions instead of
java.util.Collections - Replaces JVM-only
java.util.Collectionsstatic helpers with the multiplatform Kotlin equivalents:list.sort(),list.reverse(),list.shuffle(),listOf(x)/setOf(x), andCollection.max()/min().
- Use Kotlin collection extensions instead of
- org.openrewrite.kotlin.migrate.UseKotlinIntMax$KtRecipe
- Use
Int.MAX_VALUEinstead ofjava.lang.Integer.MAX_VALUE Integer.MAX_VALUEis the JVM-only spelling; Kotlin'sInt.MAX_VALUEis the multiplatform equivalent.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinIntMin$KtRecipe
- Use
Int.MIN_VALUEinstead ofjava.lang.Integer.MIN_VALUE Integer.MIN_VALUEis the JVM-only spelling; Kotlin'sInt.MIN_VALUEis the multiplatform equivalent.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMath$KtRecipe
- Use
kotlin.mathinstead ofjava.lang.Math - Replaces JVM-only
java.lang.Mathcalls with their multiplatformkotlin.mathequivalents — top-level functions (abs,sqrt,sin, …), constants (PI,E), and receiver-style extensions onDouble/Int/Long(pow,roundToInt,floorDiv,mod, …).
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathAbs$KtRecipe
- Use
kotlin.math.absinstead ofjava.lang.Math.abs kotlin.math.absis the multiplatform-friendly form. Java'sMath.absonly works on the JVM and is a thin pass-through; the Kotlin call site reads more naturally in shared modules.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathAcos$KtRecipe
- Use
kotlin.math.acosinstead ofjava.lang.Math.acos - Prefer the multiplatform-friendly
kotlin.math.acosover the JVM-onlyMath.acos.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathAsin$KtRecipe
- Use
kotlin.math.asininstead ofjava.lang.Math.asin - Prefer the multiplatform-friendly
kotlin.math.asinover the JVM-onlyMath.asin.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathAtan$KtRecipe
- Use
kotlin.math.ataninstead ofjava.lang.Math.atan - Prefer the multiplatform-friendly
kotlin.math.atanover the JVM-onlyMath.atan.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathAtan2$KtRecipe
- Use
kotlin.math.atan2instead ofjava.lang.Math.atan2 - Prefer the multiplatform-friendly
kotlin.math.atan2over the JVM-onlyMath.atan2.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathCbrt$KtRecipe
- Use
kotlin.math.cbrtinstead ofjava.lang.Math.cbrt - Prefer the multiplatform-friendly
kotlin.math.cbrtover the JVM-onlyMath.cbrt.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathCeil$KtRecipe
- Use
kotlin.math.ceilinstead ofjava.lang.Math.ceil - Prefer the multiplatform-friendly
kotlin.math.ceilover the JVM-onlyMath.ceil.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathCos$KtRecipe
- Use
kotlin.math.cosinstead ofjava.lang.Math.cos - Prefer the multiplatform-friendly
kotlin.math.cosover the JVM-onlyMath.cos.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathCosh$KtRecipe
- Use
kotlin.math.coshinstead ofjava.lang.Math.cosh - Prefer the multiplatform-friendly
kotlin.math.coshover the JVM-onlyMath.cosh.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathE$KtRecipe
- Use
kotlin.math.Einstead ofjava.lang.Math.E - Prefer the multiplatform-friendly
kotlin.math.Eover the JVM-onlyMath.E.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathExp$KtRecipe
- Use
kotlin.math.expinstead ofjava.lang.Math.exp - Prefer the multiplatform-friendly
kotlin.math.expover the JVM-onlyMath.exp.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathExpm1$KtRecipe
- Use
kotlin.math.expm1instead ofjava.lang.Math.expm1 - Prefer the multiplatform-friendly
kotlin.math.expm1over the JVM-onlyMath.expm1.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathFloor$KtRecipe
- Use
kotlin.math.floorinstead ofjava.lang.Math.floor - Prefer the multiplatform-friendly
kotlin.math.floorover the JVM-onlyMath.floor.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathHypot$KtRecipe
- Use
kotlin.math.hypotinstead ofjava.lang.Math.hypot - Prefer the multiplatform-friendly
kotlin.math.hypotover the JVM-onlyMath.hypot.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathLn$KtRecipe
- Use
kotlin.math.lninstead ofjava.lang.Math.log Math.logis natural log; the multiplatformkotlin.mathpackage spells itlnto disambiguate fromlog(b, x)(log base b).
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathLn1p$KtRecipe
- Use
kotlin.math.ln1pinstead ofjava.lang.Math.log1p Math.log1p(x)computesln(1 + x). The multiplatformkotlin.mathpackage spells itln1p, mirroring thelog→lnrename.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathLog10$KtRecipe
- Use
kotlin.math.log10instead ofjava.lang.Math.log10 - Prefer the multiplatform-friendly
kotlin.math.log10over the JVM-onlyMath.log10.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathMax$KtRecipe
- Use
kotlin.math.maxinstead ofjava.lang.Math.max - Prefer the multiplatform-friendly
kotlin.math.maxover the JVM-onlyMath.max.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathMin$KtRecipe
- Use
kotlin.math.mininstead ofjava.lang.Math.min - Prefer the multiplatform-friendly
kotlin.math.minover the JVM-onlyMath.min.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathPi$KtRecipe
- Use
kotlin.math.PIinstead ofjava.lang.Math.PI - Prefer the multiplatform-friendly
kotlin.math.PIover the JVM-onlyMath.PI.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathSign$KtRecipe
- Use
kotlin.math.signinstead ofjava.lang.Math.signum Math.signum(x)is renamed tokotlin.math.sign(x)in the multiplatformkotlin.mathpackage.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathSin$KtRecipe
- Use
kotlin.math.sininstead ofjava.lang.Math.sin - Prefer the multiplatform-friendly
kotlin.math.sinover the JVM-onlyMath.sin.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathSinh$KtRecipe
- Use
kotlin.math.sinhinstead ofjava.lang.Math.sinh - Prefer the multiplatform-friendly
kotlin.math.sinhover the JVM-onlyMath.sinh.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathSqrt$KtRecipe
- Use
kotlin.math.sqrtinstead ofjava.lang.Math.sqrt - Prefer the multiplatform-friendly
kotlin.math.sqrtover the JVM-onlyMath.sqrt.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathTan$KtRecipe
- Use
kotlin.math.taninstead ofjava.lang.Math.tan - Prefer the multiplatform-friendly
kotlin.math.tanover the JVM-onlyMath.tan.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinMathTanh$KtRecipe
- Use
kotlin.math.tanhinstead ofjava.lang.Math.tanh - Prefer the multiplatform-friendly
kotlin.math.tanhover the JVM-onlyMath.tanh.
- Use
- org.openrewrite.kotlin.migrate.UseKotlinNumberApis$KtRecipe
- Use Kotlin number extensions instead of
java.lang.Integer/Long/Double/Float/Boolean - Replaces JVM-only static helpers on boxed primitive types with their multiplatform Kotlin counterparts: parsing (
s.toInt(),s.toLong(radix),s.toDouble(),s.toBoolean()), formatting (i.toString(2),l.toString(16)), bit operations (i.countOneBits(),l.rotateLeft(n)), constants (Int.MIN_VALUE), andcompareTo.
- Use Kotlin number extensions instead of
- org.openrewrite.kotlin.migrate.UseKotlinRegex$KtRecipe
- Use
kotlin.text.Regexinstead ofjava.util.regex.Pattern - Replaces JVM-only
java.util.regex.Patterncalls with their multiplatform Kotlin equivalents:s.toRegex()andRegex.escape(s).
- Use
- org.openrewrite.kotlin.migrate.UseListOf$KtRecipe
- Use
listOf(x)instead ofCollections.singletonList(x) java.util.Collections.singletonList(x)is JVM-only; Kotlin's multiplatformlistOf(x)produces an immutable single-element list.
- Use
- org.openrewrite.kotlin.migrate.UseListReverse$KtRecipe
- Use
MutableList.reverse()instead ofCollections.reverse(list) java.util.Collections.reverse(list)is JVM-only; Kotlin'sMutableList.reverse()extension is multiplatform and reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseListShuffle$KtRecipe
- Use
MutableList.shuffle()instead ofCollections.shuffle(list) java.util.Collections.shuffle(list)is JVM-only; Kotlin'sMutableList.shuffle()extension is multiplatform and reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseListSort$KtRecipe
- Use
MutableList.sort()instead ofCollections.sort(list) java.util.Collections.sort(list)is JVM-only; Kotlin'sMutableList.sort()extension is multiplatform and reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseLocalizedMessage$KtRecipe
- Use
Throwable.localizedMessageinstead ofThrowable.message - Prefer the i18n-aware
localizedMessageproperty overmessagewhen surfacing exception text to end users. Both are Kotlin properties onjava.lang.Throwable— the rewrite is a pure property-access rename.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayBinarySearch$KtRecipe
- Use
LongArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: long[], key: Long)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayContentEquals$KtRecipe
- Use
LongArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: long[], b: long[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayContentHashCode$KtRecipe
- Use
LongArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: long[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayContentToString$KtRecipe
- Use
LongArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: long[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayCopyOf$KtRecipe
- Use
LongArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: long[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArrayFill$KtRecipe
- Use
LongArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: long[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongArraySort$KtRecipe
- Use
LongArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: long[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseLongCountOneBits$KtRecipe
- Use
Long.countOneBits()instead ofjava.lang.Long.bitCount Long.bitCount(l)is the JVM-only popcount; the multiplatforml.countOneBits()extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseLongFloorDiv$KtRecipe
- Use
Long.floorDivinstead ofjava.lang.Math.floorDiv Math.floorDiv(a, b)becomesa.floorDiv(b)— the multiplatform Kotlin extension onLong.
- Use
- org.openrewrite.kotlin.migrate.UseLongMod$KtRecipe
- Use
Long.mod()instead ofjava.lang.Math.floorMod Math.floorMod(a, b)becomesa.mod(b)for the(Long, Long)overload. Kotlin'sLong.modmatchesMath.floorModfloored-division semantics.
- Use
- org.openrewrite.kotlin.migrate.UseLongModInt$KtRecipe
- Use
Long.mod(Int)instead ofjava.lang.Math.floorMod Math.floorMod(a: Long, b: Int): Intbecomesa.mod(b). Like the Java overload,Long.mod(Int)returns anInt.
- Use
- org.openrewrite.kotlin.migrate.UseLongRotateLeft$KtRecipe
- Use
Long.rotateLeft(n)instead ofLong.rotateLeft(l, n) java.lang.Long.rotateLeft(l, n)is JVM-only; the multiplatforml.rotateLeft(n)extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseLongRotateRight$KtRecipe
- Use
Long.rotateRight(n)instead ofLong.rotateRight(l, n) java.lang.Long.rotateRight(l, n)is JVM-only; the multiplatforml.rotateRight(n)extension reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseLongToString$KtRecipe
- Use
Long.toString()instead ofLong.toString(l) java.lang.Long.toString(l)is the JVM-only spelling;l.toString()reads as a receiver call and is multiplatform.
- Use
- org.openrewrite.kotlin.migrate.UseLongToStringWithRadix$KtRecipe
- Use
Long.toString(radix)instead ofLong.toString(l, radix) java.lang.Long.toString(l, radix)is the JVM-only spelling;l.toString(radix)is the multiplatform Kotlin receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseLowercase$KtRecipe
- Use
lowercase()instead oftoLowerCase() String.toLowerCase()was deprecated in Kotlin 1.5 in favor of the locale-explicitlowercase().
- Use
- org.openrewrite.kotlin.migrate.UseLowercaseChar$KtRecipe
- Use
Char.lowercaseChar()instead ofChar.toLowerCase() Char.toLowerCase()was deprecated in Kotlin 1.5 in favor of the locale-explicitlowercaseChar().
- Use
- org.openrewrite.kotlin.migrate.UseLowercaseWithLocale$KtRecipe
- Use
lowercase(locale)instead oftoLowerCase(locale) - The JVM
String.toLowerCase(Locale)overload was deprecated in Kotlin 1.5 alongside the no-arg form; the replacementlowercase(Locale)keeps the locale parameter and uses the new spelling.
- Use
- org.openrewrite.kotlin.migrate.UseModernKotlinStdlibApis$KtRecipe
- Use modern Kotlin stdlib idioms
- Replaces Kotlin stdlib APIs deprecated between 1.4 and 2.0 with their modern equivalents, and adopts newer language features (open-ended range
..<,enumEntries<T>()) where the older spelling still compiles but reads worse.
- org.openrewrite.kotlin.migrate.UseRangeUntilOperator$KtRecipe
- Use
..<instead ofuntil - Kotlin 1.7.20 introduced the
..<open-ended range operator. Prefer it over the olderuntilinfix function.
- Use
- org.openrewrite.kotlin.migrate.UseReadln$KtRecipe
- Use
readln()instead ofreadLine()!! - Kotlin 1.6 introduced
readln()to replace the commonreadLine()!!idiom — the new spelling makes the EOF-throws contract explicit and drops the not-null assertion.
- Use
- org.openrewrite.kotlin.migrate.UseReadlnOrNull$KtRecipe
- Use
readlnOrNull()instead ofreadLine() readLine()was deprecated in Kotlin 1.6 in favor ofreadlnOrNull()(and the assertingreadln()), which spells the EOF-handling intent explicitly.
- Use
- org.openrewrite.kotlin.migrate.UseRegexEscape$KtRecipe
- Use
Regex.escape(s)instead ofPattern.quote(s) java.util.regex.Pattern.quote(s)migrates tokotlin.text.Regex.escape(s)— same behavior, multiplatform.
- Use
- org.openrewrite.kotlin.migrate.UseRemoveAtLastIndexForRemoveLast$KtRecipe
- Use
removeAt(lastIndex)instead ofremoveLast() MutableList.removeLast()was deprecated in Kotlin 2.0 alongsideremoveFirst()for the same SequencedCollection conflict. PreferremoveAt(lastIndex).
- Use
- org.openrewrite.kotlin.migrate.UseRemoveAtZeroForRemoveFirst$KtRecipe
- Use
removeAt(0)instead ofremoveFirst() MutableList.removeFirst()was deprecated in Kotlin 2.0 because Java 21'sSequencedCollection.removeFirst()introduced a conflicting signature with different return-on-empty semantics. PreferremoveAt(0)to keep the throwing behavior unambiguous.
- Use
- org.openrewrite.kotlin.migrate.UseSetOf$KtRecipe
- Use
setOf(x)instead ofCollections.singleton(x) java.util.Collections.singleton(x)is JVM-only; Kotlin's multiplatformsetOf(x)produces an immutable single-element set.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayBinarySearch$KtRecipe
- Use
ShortArray.binarySearch()instead ofArrays.binarySearch(arr, key) java.util.Arrays.binarySearch(arr: short[], key: Short)is JVM-only;arr.binarySearch(key)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayContentEquals$KtRecipe
- Use
ShortArray.contentEquals()instead ofArrays.equals(a, b) java.util.Arrays.equals(a: short[], b: short[])is JVM-only;a.contentEquals(b)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayContentHashCode$KtRecipe
- Use
ShortArray.contentHashCode()instead ofArrays.hashCode(arr) java.util.Arrays.hashCode(arr: short[])is JVM-only;arr.contentHashCode()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayContentToString$KtRecipe
- Use
ShortArray.contentToString()instead ofArrays.toString(arr) java.util.Arrays.toString(arr: short[])is JVM-only;arr.contentToString()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayCopyOf$KtRecipe
- Use
ShortArray.copyOf()instead ofArrays.copyOf(arr, newLength) java.util.Arrays.copyOf(arr: short[], newLength)is JVM-only;arr.copyOf(newLength)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArrayFill$KtRecipe
- Use
ShortArray.fill()instead ofArrays.fill(arr, value) java.util.Arrays.fill(arr: short[], value)is JVM-only;arr.fill(value)is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseShortArraySort$KtRecipe
- Use
ShortArray.sort()instead ofArrays.sort(arr) java.util.Arrays.sort(arr: short[])is JVM-only;arr.sort()is the multiplatform Kotlin extension.
- Use
- org.openrewrite.kotlin.migrate.UseStringToBoolean$KtRecipe
- Use
String.toBoolean()instead ofjava.lang.Boolean.parseBoolean(s) - Java-idiom
Boolean.parseBoolean(s)migrates to the Kotlin extensions.toBoolean(); for strict parsing that throws on non-true/false, uses.toBooleanStrict()instead.
- Use
- org.openrewrite.kotlin.migrate.UseStringToDouble$KtRecipe
- Use
String.toDouble()instead ofjava.lang.Double.parseDouble(s) - Java-idiom
Double.parseDouble(s)migrates to the Kotlin extensions.toDouble().
- Use
- org.openrewrite.kotlin.migrate.UseStringToFloat$KtRecipe
- Use
String.toFloat()instead ofjava.lang.Float.parseFloat(s) - Java-idiom
Float.parseFloat(s)migrates to the Kotlin extensions.toFloat().
- Use
- org.openrewrite.kotlin.migrate.UseStringToInt$KtRecipe
- Use
String.toInt()instead ofInteger.parseInt(s) - Java-idiom
Integer.parseInt(s)migrates to the Kotlin extensions.toInt(). The behavior is identical — both throwNumberFormatExceptionon invalid input.
- Use
- org.openrewrite.kotlin.migrate.UseStringToIntWithRadix$KtRecipe
- Use
String.toInt(radix)instead ofInteger.parseInt(s, radix) Integer.parseInt(s, radix)is JVM-only; the Kotlin extensions.toInt(radix)is multiplatform and reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseStringToLong$KtRecipe
- Use
String.toLong()instead ofjava.lang.Long.parseLong(s) - Java-idiom
Long.parseLong(s)migrates to the Kotlin extensions.toLong().
- Use
- org.openrewrite.kotlin.migrate.UseStringToLongWithRadix$KtRecipe
- Use
String.toLong(radix)instead ofLong.parseLong(s, radix) java.lang.Long.parseLong(s, radix)is JVM-only; the Kotlin extensions.toLong(radix)is multiplatform and reads as a receiver call.
- Use
- org.openrewrite.kotlin.migrate.UseStringToRegex$KtRecipe
- Use
String.toRegex()instead ofPattern.compile(s) java.util.regex.Pattern.compile(s)migrates to the Kotlin extensions.toRegex(), which returns akotlin.text.Regexand reads more naturally.
- Use
- org.openrewrite.kotlin.migrate.UseSumOf$KtRecipe
- Use
sumOfinstead ofsumBy Iterable.sumBy \{ … \}was deprecated in Kotlin 1.5 in favor of the type-inferredsumOf \{ … \}(which avoids the unchecked Int return).
- Use
- org.openrewrite.kotlin.migrate.UseSumOfDouble$KtRecipe
- Use
sumOfinstead ofsumByDouble Iterable.sumByDouble \{ … \}was deprecated in Kotlin 1.5 in favor of the type-inferredsumOf \{ … \}.
- Use
- org.openrewrite.kotlin.migrate.UseUppercase$KtRecipe
- Use
uppercase()instead oftoUpperCase() String.toUpperCase()was deprecated in Kotlin 1.5 in favor of the locale-explicituppercase().
- Use
- org.openrewrite.kotlin.migrate.UseUppercaseChar$KtRecipe
- Use
Char.uppercaseChar()instead ofChar.toUpperCase() Char.toUpperCase()was deprecated in Kotlin 1.5 in favor of the locale-explicituppercaseChar().
- Use
- org.openrewrite.kotlin.migrate.UseUppercaseWithLocale$KtRecipe
- Use
uppercase(locale)instead oftoUpperCase(locale) - The JVM
String.toUpperCase(Locale)overload was deprecated in Kotlin 1.5 alongside the no-arg form; the replacementuppercase(Locale)keeps the locale parameter and uses the new spelling.
- Use
- org.openrewrite.kotlin.migrate.UseValueClass$KtRecipe
- Use
@JvmInline value classinstead ofinline class inline classwas deprecated in Kotlin 1.5 in favor of the explicit@JvmInline value classpair; the new spelling separates the JVM mapping (@JvmInline) from the language-level semantics (value).
- Use
- org.openrewrite.kotlin.performance.CollapseFilterTerminals$KtRecipe
- Collapse
filter \{ p \}.<terminal>()chains - Folds predicate-taking terminals (
first,last,count,any,none,single,firstOrNull,lastOrNull,singleOrNull) andsumOf/maxOf/minOfselectors into the upstreamfilterormap, avoiding the intermediate list materialization.
- Collapse
- org.openrewrite.kotlin.performance.CollapseSortAndReverse$KtRecipe
- Collapse
sorted().first/last()andreversed().first/last()chains - Replaces O(n log n) sorts whose only purpose is to read one element with the equivalent O(n)
min/max/minBy/maxBy, and elides unnecessaryreversed()copies beforefirst/last.
- Collapse
- org.openrewrite.kotlin.performance.FindAllocationsInCollectionLambdas$KtRecipe
- Find expensive allocations inside collection lambdas
- Search-only recipes that flag heavyweight allocations sitting inside the trailing lambda of a
map/filter/forEach/flatMapcall. Each such lambda runs once per element — the same allocation-cost profile as a loop body.
- org.openrewrite.kotlin.performance.FindAllocationsInHotPaths$KtRecipe
- Find expensive allocations on hot paths
- Search-only recipes that flag heavyweight allocations sitting on a path the runtime exercises repeatedly — inside a loop, inside
View.onDraw/onMeasure/onLayout. Each match shows up as aSearchResultfor review; nothing is rewritten automatically.
- org.openrewrite.kotlin.performance.FindAllocationsInOnDraw$KtRecipe
- Find graphics allocations inside
View.onDraw - Android views call
onDrawon every frame. AllocatingPaint,Path,Rect,RectF,Region,Matrix, orBitmapinstances per draw causes GC pressure and dropped frames — hoist them into field initializers orlazy \{ \}properties.
- Find graphics allocations inside
- org.openrewrite.kotlin.performance.FindAllocationsInOnLayout$KtRecipe
- Find graphics allocations inside
View.onLayout onLayoutruns whenever a view's children are repositioned. AllocatingPaint,Path,Rect,RectF,Region,Matrix, orBitmapinstances per layout causes per-frame GC pressure — hoist them to fields.
- Find graphics allocations inside
- org.openrewrite.kotlin.performance.FindAllocationsInOnMeasure$KtRecipe
- Find graphics allocations inside
View.onMeasure onMeasureruns whenever the measurement pass walks a view. AllocatingPaint,Path,Rect,RectF,Region,Matrix, orBitmapinstances per measure makes layout reflows hit the GC — hoist them to fields.
- Find graphics allocations inside
- org.openrewrite.kotlin.performance.FindBase64GetDecoderInLoops$KtRecipe
- Find
Base64.getDecoder()calls inside loops Base64.getDecoder()returns a shared singleton, so the call itself is cheap — but reading the decoder from afinalfield is cheaper still. Hoist the decoder to a top-levelprivate valfor clarity.
- Find
- org.openrewrite.kotlin.performance.FindBigDecimalFromStringInLoops$KtRecipe
- Find
BigDecimal("...")allocations inside loops - Parsing a
BigDecimalfrom aStringliteral inside a loop reparses the same value every iteration. Hoist the literalBigDecimalout of the loop or use a cached constant.
- Find
- org.openrewrite.kotlin.performance.FindBigIntegerFromStringInLoops$KtRecipe
- Find
BigInteger("...")allocations inside loops - Parsing a
BigIntegerfrom aStringliteral inside a loop reparses the same value every iteration. Hoist the literalBigIntegerto a top-level property orBigInteger.valueOfconstant.
- Find
- org.openrewrite.kotlin.performance.FindBigIntegerValueOfInLoops$KtRecipe
- Find
BigInteger.valueOf(long)calls inside loops BigInteger.valueOfcaches small values (-16..16) but allocates freshBigIntegerinstances outside that range. Loop bodies frequently feed it dynamic values — hoist a constant where possible or accept the allocation cost.
- Find
- org.openrewrite.kotlin.performance.FindCalendarGetInstanceInLoops$KtRecipe
- Find
Calendar.getInstance()calls inside loops Calendar.getInstance()resolves the defaultTimeZoneandLocaleand allocates a freshGregorianCalendaron every call. Inside a loop the timezone lookup dominates — hoist the calendar or migrate tojava.timetypes.
- Find
- org.openrewrite.kotlin.performance.FindCharsetForNameInLoops$KtRecipe
- Find
Charset.forName(...)calls inside loops Charset.forName("UTF-8")walks the charset alias map on every call. Prefer the cached constants onkotlin.text.Charsets(Charsets.UTF_8,Charsets.ISO_8859_1, etc.) — or hoist a singleCharsetout of the loop.
- Find
- org.openrewrite.kotlin.performance.FindClassForNameInLoops$KtRecipe
- Find
Class.forNamecalls inside loops Class.forName(...)walks the classloader hierarchy on every call. Resolving the same class on every loop iteration burns CPU — cache the resolvedClass<*>in a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindDateTimeFormatterInLoops$KtRecipe
- Find
DateTimeFormatter.ofPatternallocations inside loops DateTimeFormatter.ofPattern(...)parses the pattern up-front. Doing that on every loop iteration burns CPU repeatedly — hoist the formatter into a top-level property. UnlikeSimpleDateFormat,DateTimeFormatteris thread-safe, so the hoisted instance can be shared.
- Find
- org.openrewrite.kotlin.performance.FindEagerMapOnSequence$KtRecipe
- Find
seq.toList().map \{ ... \}patterns - Calling
.toList()on aSequenceand then.map \{ … \}materializes the full sequence into aListand then walks it again — defeating the lazy-pipeline purpose ofSequence. Drop thetoList()so themapstays in the sequence.
- Find
- org.openrewrite.kotlin.performance.FindFileNewBufferedReaderInLoops$KtRecipe
- Find
File(...).bufferedReader()calls inside loops - Constructing a
Fileand opening aBufferedReaderper loop iteration multiplies the OS-level open/read/close cost. If the same path is read each pass, read it once before the loop; if every iteration reads a different path, batch the work or reuse aReader.
- Find
- org.openrewrite.kotlin.performance.FindForEachWithIndexedAccess$KtRecipe
- Find
for (i in xs.indices) \{ val x = xs[i] \}patterns - Iterating over
xs.indicesand indexing back intoxs[i]is the explicit-index form ofxs.forEachIndexed \{ i, x -> \}. The indexed form is clearer and avoids re-resolvingxs[i]on every access.
- Find
- org.openrewrite.kotlin.performance.FindGsonInCollectionLambdas$KtRecipe
- Find
Gson()allocations inside collection lambdas - Gson's default constructor builds the type-adapter registry up front. Allocating a fresh
Gsonper element repeats that work — hoist oneGsoninstance to a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindGsonInLoops$KtRecipe
- Find
Gson()allocations inside loops - Gson's default constructor builds the type-adapter registry up front. Allocating one per loop iteration repeats that work — hoist a single
Gsoninstance to a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindIterationSmells$KtRecipe
- Find iteration-shape smells
- Flags iteration idioms that have a clearer, allocation-equivalent Kotlin form — currently the
for (i in xs.indices) \{ val x = xs[i] \}shape thatforEachIndexed \{ i, x -> \}replaces.
- org.openrewrite.kotlin.performance.FindLargeListPipeline$KtRecipe
- Find long
Listpipelines that should useSequence - A pipeline with three or more chained collection operations (
map/filter/flatMap/etc.) on aListmaterializes an intermediate collection per stage. Long pipelines on large inputs typically run faster (and allocate less) asxs.asSequence().…toList().
- Find long
- org.openrewrite.kotlin.performance.FindListOfInLoops$KtRecipe
- Find
listOf(...)calls inside loops - An immutable
listOf(...)built inside a loop allocates a fresh list every iteration. If the contents are constant, hoist the list to avaloutside the loop. If the contents change per iteration, the allocation is necessary — review and accept.
- Find
- org.openrewrite.kotlin.performance.FindLocaleConstructionInLoops$KtRecipe
- Find
Locale(...)allocations inside loops Locale("en", "US")walks the locale provider list on every construction. For common locales prefer the cached constants onLocale(e.g.Locale.US,Locale.ENGLISH). Otherwise hoist a singleLocaleout of the loop.
- Find
- org.openrewrite.kotlin.performance.FindLoggerFactoryGetLoggerInCollectionLambdas$KtRecipe
- Find
LoggerFactory.getLoggercalls inside collection lambdas LoggerFactory.getLogger(...)resolves the logger through SLF4J on every call. Inside a collection lambda that resolves the same logger per element — hoist it to aprivate valcompanion property.
- Find
- org.openrewrite.kotlin.performance.FindLoggerFactoryGetLoggerInLoops$KtRecipe
- Find
LoggerFactory.getLoggercalls inside loops LoggerFactory.getLogger(...)resolves the logger through the SLF4J binding on every call. Hoist the logger to aprivate valcompanion property — there's exactly one logger per class.
- Find
- org.openrewrite.kotlin.performance.FindLoopAllocations$KtRecipe
- Find collection construction inside loops
- Flags
listOf/mutableListOf/mutableMapOfcalls that allocate a fresh collection on every loop iteration. Hoist constants orclear()-and-reuse a single instance.
- org.openrewrite.kotlin.performance.FindMessageDigestGetInstanceInLoops$KtRecipe
- Find
MessageDigest.getInstancecalls inside loops MessageDigest.getInstance("MD5")walks the security-provider list on every call. Hoist the digest to a per-thread cache or reset it per use.
- Find
- org.openrewrite.kotlin.performance.FindMutableListOfInLoops$KtRecipe
- Find
mutableListOf<T>()allocations inside loops - A
mutableListOf<T>()allocated per iteration produces garbage proportional to the loop count. If the list is filled and consumed each pass, considerclear()-and-reuse on a single hoisted list.
- Find
- org.openrewrite.kotlin.performance.FindMutableMapOfInLoops$KtRecipe
- Find
mutableMapOf<K, V>()allocations inside loops - A
mutableMapOf<K, V>()allocated per iteration produces garbage proportional to the loop count. If the map is filled and consumed each pass, considerclear()-and-reuse on a single hoisted map.
- Find
- org.openrewrite.kotlin.performance.FindObjectMapperInCollectionLambdas$KtRecipe
- Find Jackson
ObjectMapper()allocations inside collection lambdas - Allocating a fresh
ObjectMapperper element rebuilds Jackson's module/serializer registry on every call. Hoist one mapper to a top-level property — it is thread-safe once configured.
- Find Jackson
- org.openrewrite.kotlin.performance.FindObjectMapperInLoops$KtRecipe
- Find Jackson
ObjectMapper()allocations inside loops - Jackson's
ObjectMapperis expensive to construct — it builds the default module and serializer registries on every allocation. Hoist a singleObjectMapperinstance to a top-level property; it is thread-safe once configured.
- Find Jackson
- org.openrewrite.kotlin.performance.FindOptionalGetInLoops$KtRecipe
- Find
Optional.get()calls inside loops Optional.get()throwsNoSuchElementExceptionwhen the optional is empty — the loop body usually relies on a precedingisPresentcheck. PreferorElse,orElseThrow, orifPresent \{ \}to make the empty branch explicit and avoid the double-check.
- Find
- org.openrewrite.kotlin.performance.FindPatternCompileInCollectionLambdas$KtRecipe
- Find
Pattern.compilecalls inside collection lambdas Pattern.compile(...)parses the pattern up front; running it inside amap/filter/forEachlambda recompiles the pattern for every element. Hoist thePatternto a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindPatternCompileInLoops$KtRecipe
- Find
Pattern.compileallocations inside loops - Compiling a
java.util.regex.Patternis expensive — allocating one inside a loop recompiles it on every iteration. Hoist thePatternout of the loop or cache it in a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindRegexAllocationsInCollectionLambdas$KtRecipe
- Find
Regexallocations inside collection lambdas - A
Regexallocated inside the lambda passed tomap,filter,forEach,flatMap, etc. is compiled once per element. Hoist the regex to a top-level property — collection-pipeline lambdas run on every element, just like a loop body.
- Find
- org.openrewrite.kotlin.performance.FindRegexAllocationsInLoops$KtRecipe
- Find
Regexallocations inside loops - Compiling a
Regexis expensive — allocating one inside a loop pays the cost on every iteration. Hoist the regex out of the loop or cache it in a top-level property.
- Find
- org.openrewrite.kotlin.performance.FindSequencePipelineSmells$KtRecipe
- Find
Sequence/Listpipeline shape smells - Flags pipelines where the
List/Sequencechoice fights the data flow — longListpipelines that materialize between every stage, andSequencepipelines that eagerly fall back toListmid-pipeline.
- Find
- org.openrewrite.kotlin.performance.FindSimpleDateFormatInLoops$KtRecipe
- Find
SimpleDateFormatallocations inside loops SimpleDateFormatparses its pattern string in the constructor and is not thread-safe — allocating one per iteration is a common per-row hot spot. Hoist it out of the loop or use a thread-local cache (or migrate toDateTimeFormatter).
- Find
- org.openrewrite.kotlin.performance.FindStringConcatSmells$KtRecipe
- Find string-allocation smells
- Flags
s = s + "…"-inside-loop patterns that allocate a freshStringon every iteration. TheStringBuilder.length-vs-sizerewrite lives in the autofix bundle.
- org.openrewrite.kotlin.performance.FindStringFormatInCollectionLambdas$KtRecipe
- Find
String.formatcalls inside collection lambdas String.format(...)reparses the format string on every call. Inside a collection lambda that runs per element — prefer Kotlin string templates ("$\{x\}") or hoist aFormatter.
- Find
- org.openrewrite.kotlin.performance.FindStringFormatInLoops$KtRecipe
- Find
String.formatcalls inside loops String.format(...)parses the format string on every call. Inside a loop this re-parses the same template every iteration — prefer string templates ("$\{x\}") or extract theFormatterif you must use%-style specifiers.
- Find
- org.openrewrite.kotlin.performance.FindStringPlusInLoop$KtRecipe
- Find
s = s + "..."string concatenation inside loops - Repeated
Stringconcatenation inside a loop allocates a newStringon every iteration — each+produces a freshStringBuilder. Prefer building once withStringBuilder(orbuildString \{ … \}).
- Find
- org.openrewrite.kotlin.performance.FindURIConstructorInLoops$KtRecipe
- Find
URI("...")allocations inside loops java.net.URI's constructor parses and validates the URI string. Doing that per loop iteration burns CPU on the same string — hoist constants out of the loop.
- Find
- org.openrewrite.kotlin.performance.FindURLConstructorInLoops$KtRecipe
- Find
URL("...")allocations inside loops java.net.URL's constructor parses the URL string and dispatches throughURLStreamHandlerFactory. Inside a loop that adds up — hoist URLs that don't change per iteration, or migrate toURI/HttpRequestbuilders.
- Find
- org.openrewrite.kotlin.performance.ImproveKotlinPerformance$KtRecipe
- Improve performance of Kotlin code
- Autofix-only performance bundle: collapses allocating call chains (filter/map/sort/reverse), promotes Compose primitive state holders, and rewrites
StringBuilder.lengthtosize. Excludes the search-onlyFind*recipes so the run output is just diffs, not a flood of search results.
- org.openrewrite.kotlin.performance.Performance$KtRecipe
- Apply Kotlin performance idioms
- Opinionated bundle of every performance recipe in this module: chain collapses (filter/map/sort/reverse), Compose primitive-state holders, and hot-path allocation finders. Search-result recipes coexist with rewriting recipes — for diff-only output, use
ImproveKotlinPerformanceinstead.
- org.openrewrite.kotlin.performance.UseAnyWithPredicate$KtRecipe
- Use
any \{ predicate \}instead offilter \{ predicate \}.isNotEmpty() any \{ predicate \}short-circuits on the first match and avoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseAnyWithPredicateInsteadOfFilterAny$KtRecipe
- Use
any \{ predicate \}instead offilter \{ predicate \}.any() any \{ predicate \}short-circuits on the first match. Callingany()afterfilterfirst materializes the entire filtered list.
- Use
- org.openrewrite.kotlin.performance.UseComposePrimitiveStateOf$KtRecipe
- Use primitive
mutable<Int|Long|Float|Double>StateOfin Compose - Inside
@Composablefunctions, replacesmutableStateOf(<primitive>)with the matching primitive-specializedmutableIntStateOf/mutableLongStateOf/mutableFloatStateOf/mutableDoubleStateOf. The specialized state holders keep the wrapped value unboxed across reads and writes during recomposition.
- Use primitive
- org.openrewrite.kotlin.performance.UseCountWithPredicate$KtRecipe
- Use
count \{ predicate \}instead offilter \{ predicate \}.count() - Folding the predicate into
countavoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseFilterNotToForFilterNotToMutableList$KtRecipe
- Use
filterNotTo(mutableListOf(), p)instead offilterNot(p).toMutableList() filterNot \{ p \}allocates aList<T>andtoMutableListcopies it.filterNotTo(mutableListOf(), p)writes directly into the target without the intermediate.
- Use
- org.openrewrite.kotlin.performance.UseFilterToForFilterToMutableList$KtRecipe
- Use
filterTo(mutableListOf(), p)instead offilter(p).toMutableList() filter \{ p \}allocates aList<T>andtoMutableListcopies it.filterTo(mutableListOf(), p)writes directly into the target without the intermediate.
- Use
- org.openrewrite.kotlin.performance.UseFirstForReversedLast$KtRecipe
- Use
first()instead ofreversed().last() reversed()allocates an intermediate reversed copy.first()returns the same element directly.
- Use
- org.openrewrite.kotlin.performance.UseFirstNotNullOfForMapFirst$KtRecipe
- Use
firstNotNullOf \{ f \}instead ofmapNotNull \{ f \}.first() firstNotNullOfshort-circuits on the first non-null result.mapNotNull \{ f \}.first()walks the whole input.
- Use
- org.openrewrite.kotlin.performance.UseFirstNotNullOfOrNullForMapFirstOrNull$KtRecipe
- Use
firstNotNullOfOrNull \{ f \}instead ofmapNotNull \{ f \}.firstOrNull() firstNotNullOfOrNullshort-circuits on the first non-null result.mapNotNull \{ f \}.firstOrNull()walks the whole input.
- Use
- org.openrewrite.kotlin.performance.UseFirstOrNullWithPredicate$KtRecipe
- Use
firstOrNull \{ predicate \}instead offilter \{ predicate \}.firstOrNull() - Folding the predicate into
firstOrNullshort-circuits on the first match and avoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseFirstWithPredicate$KtRecipe
- Use
first \{ predicate \}instead offilter \{ predicate \}.first() - Folding the predicate into
firstavoids materializing the intermediate filtered list and short-circuits on the first match.
- Use
- org.openrewrite.kotlin.performance.UseFlatMapToForFlatMapToMutableList$KtRecipe
- Use
flatMapTo(mutableListOf(), f)instead offlatMap(f).toMutableList() flatMap \{ f \}allocates aList<R>andtoMutableListcopies it.flatMapTo(mutableListOf(), f)writes directly into the target without the intermediate.
- Use
- org.openrewrite.kotlin.performance.UseLastForReversedFirst$KtRecipe
- Use
last()instead ofreversed().first() reversed()allocates an intermediate reversed copy.last()walks to the same element directly.
- Use
- org.openrewrite.kotlin.performance.UseLastOrNullWithPredicate$KtRecipe
- Use
lastOrNull \{ predicate \}instead offilter \{ predicate \}.lastOrNull() - Folding the predicate into
lastOrNullavoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseLastWithPredicate$KtRecipe
- Use
last \{ predicate \}instead offilter \{ predicate \}.last() - Folding the predicate into
lastavoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseLengthForStringBuilderSize$KtRecipe
- Use
sb.lengthinstead ofsb.toString().length - Calling
toString()on aStringBuilderallocates a snapshotStringjust to read its length.StringBuilderexposeslengthdirectly without the copy.
- Use
- org.openrewrite.kotlin.performance.UseMapNotNullForMapFilterNotNull$KtRecipe
- Use
mapNotNull \{ f \}instead ofmap \{ f \}.filterNotNull() mapNotNulldrops nulls in the same pass that produces them.map \{ f \}.filterNotNull()materializes the fullList<R?>first.
- Use
- org.openrewrite.kotlin.performance.UseMapToForMapToMutableList$KtRecipe
- Use
mapTo(mutableListOf(), f)instead ofmap(f).toMutableList() map \{ f \}allocates aList<R>andtoMutableListcopies it.mapTo(mutableListOf(), f)writes directly into the target without the intermediate.
- Use
- org.openrewrite.kotlin.performance.UseMaxByForSortedByLast$KtRecipe
- Use
maxBy \{ selector \}instead ofsortedBy \{ selector \}.last() sortedBy(f).last()does an O(n log n) sort just to read the maximum-by-f.maxBy(f)finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMaxForSortedDescendingFirst$KtRecipe
- Use
max()instead ofsortedDescending().first() sortedDescending().first()does an O(n log n) sort just to read the maximum.max()finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMaxForSortedLast$KtRecipe
- Use
max()instead ofsorted().last() sorted().last()does an O(n log n) sort just to read the maximum.max()finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMaxOfWithSelector$KtRecipe
- Use
maxOf \{ selector \}instead ofmap \{ selector \}.max() maxOfwalks the input once and tracks the running maximum without materializing the intermediateList<Int>.
- Use
- org.openrewrite.kotlin.performance.UseMinByForSortedByFirst$KtRecipe
- Use
minBy \{ selector \}instead ofsortedBy \{ selector \}.first() sortedBy(f).first()does an O(n log n) sort just to read the minimum-by-f.minBy(f)finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMinForSortedDescendingLast$KtRecipe
- Use
min()instead ofsortedDescending().last() sortedDescending().last()does an O(n log n) sort just to read the minimum.min()finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMinForSortedFirst$KtRecipe
- Use
min()instead ofsorted().first() sorted().first()does an O(n log n) sort just to read the minimum.min()finds it in a single linear pass.
- Use
- org.openrewrite.kotlin.performance.UseMinOfWithSelector$KtRecipe
- Use
minOf \{ selector \}instead ofmap \{ selector \}.min() minOfwalks the input once and tracks the running minimum without materializing the intermediateList<Int>.
- Use
- org.openrewrite.kotlin.performance.UseMutableDoubleStateOf$KtRecipe
- Use
mutableDoubleStateOfinstead ofmutableStateOf<Double>in Compose - Compose's
mutableDoubleStateOfkeeps the wrapped value as a primitiveDouble, avoiding the autobox-and-unbox cost thatmutableStateOf<Double>pays on every read and write inside a recomposition.
- Use
- org.openrewrite.kotlin.performance.UseMutableFloatStateOf$KtRecipe
- Use
mutableFloatStateOfinstead ofmutableStateOf<Float>in Compose - Compose's
mutableFloatStateOfkeeps the wrapped value as a primitiveFloat, avoiding the autobox-and-unbox cost thatmutableStateOf<Float>pays on every read and write inside a recomposition.
- Use
- org.openrewrite.kotlin.performance.UseMutableIntStateOf$KtRecipe
- Use
mutableIntStateOfinstead ofmutableStateOf<Int>in Compose - Compose's
mutableIntStateOfkeeps the wrapped value as a primitiveInt, avoiding the autobox-and-unbox cost thatmutableStateOf<Int>pays on every read and write inside a recomposition.
- Use
- org.openrewrite.kotlin.performance.UseMutableLongStateOf$KtRecipe
- Use
mutableLongStateOfinstead ofmutableStateOf<Long>in Compose - Compose's
mutableLongStateOfkeeps the wrapped value as a primitiveLong, avoiding the autobox-and-unbox cost thatmutableStateOf<Long>pays on every read and write inside a recomposition.
- Use
- org.openrewrite.kotlin.performance.UseNoneWithPredicate$KtRecipe
- Use
none \{ predicate \}instead offilter \{ predicate \}.isEmpty() none \{ predicate \}short-circuits on the first match and avoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseNoneWithPredicateInsteadOfFilterNone$KtRecipe
- Use
none \{ predicate \}instead offilter \{ predicate \}.none() none \{ predicate \}short-circuits on the first match. Callingnone()afterfilterfirst materializes the entire filtered list.
- Use
- org.openrewrite.kotlin.performance.UseSingleOrNullWithPredicate$KtRecipe
- Use
singleOrNull \{ predicate \}instead offilter \{ predicate \}.singleOrNull() - Folding the predicate into
singleOrNullavoids materializing the intermediate filtered list.
- Use
- org.openrewrite.kotlin.performance.UseSingleWithPredicate$KtRecipe
- Use
single \{ predicate \}instead offilter \{ predicate \}.single() - Folding the predicate into
singleavoids materializing the intermediate filtered list and preserves the same throwing semantics on the no-match and multi-match cases.
- Use
- org.openrewrite.kotlin.performance.UseSortedByDescendingForSortedByReversed$KtRecipe
- Use
sortedByDescending \{ f \}instead ofsortedBy \{ f \}.reversed() sortedByDescendingsorts directly into the target order.sortedBy(f).reversed()allocates an intermediate ascending-sorted list and then a reversed copy.
- Use
- org.openrewrite.kotlin.performance.UseSortedDescendingForSortedReversed$KtRecipe
- Use
sortedDescending()instead ofsorted().reversed() sortedDescendingsorts directly into descending order.sorted().reversed()allocates an intermediate ascending-sorted list and then a reversed copy.
- Use
- org.openrewrite.kotlin.performance.UseSumOfWithSelector$KtRecipe
- Use
sumOf \{ selector \}instead ofmap \{ selector \}.sum() sumOfaccumulates the result directly without materializing the intermediateList<Int>.
- Use
- org.openrewrite.kotlin.search.FindApiSurface$KtRecipe
- Find public-API and binary-stability surface
- Public
const val/lateinit vardeclarations,@OptIn/@RequiresOptInannotations,@Deprecateddeclarations, and JVM-interop annotations (@JvmStatic,@JvmField,@JvmOverloads). Each match is a position where API stability or external-consumer constraints are encoded in the source.
- org.openrewrite.kotlin.search.FindAssertJChains$KtRecipe
- Find AssertJ
assertThat(...)assertion chains - AssertJ chains are the heart of the test suite's verification logic. Surfacing them helps a reviewer or LLM agent locate the assertions in a long test method and reason about coverage.
- Find AssertJ
- org.openrewrite.kotlin.search.FindAtomicAllocations$KtRecipe
- Find
AtomicReference/AtomicInteger/AtomicLong/AtomicBooleanallocations - Atomic primitives indicate concurrent state — each one is a place where a reviewer or LLM agent should look for happens-before reasoning. In coroutine-only code,
MutableStateFloworMutex-guarded state is usually a clearer alternative.
- Find
- org.openrewrite.kotlin.search.FindBuildHygiene$KtRecipe
- Find build- and source-hygiene smells
- Wildcard imports and similar source-organization smells that obscure where names come from.
- org.openrewrite.kotlin.search.FindClassForName$KtRecipe
- Find
Class.forName(...)calls Class.forNameis the entrypoint to runtime reflection — the receiver type isn't known at compile time, so type-safety analyses can't follow what happens next. Each match is a position an LLM agent should single out when reasoning about what a function can touch.
- Find
- org.openrewrite.kotlin.search.FindClipboardAccess$KtRecipe
- Find Android
ClipboardManageraccess - Clipboard reads and writes carry user data into and out of a process boundary the user typically does not associate with the app. Each call is a candidate for review of secret-leak and accidental-paste scenarios.
- Find Android
- org.openrewrite.kotlin.search.FindCommandExecutionSinks$KtRecipe
- Find process-execution sinks (
Runtime.exec,ProcessBuilder.start) - Spawning a process with attacker-controlled arguments is the canonical command-injection sink. Each call here is a position where a reviewer or LLM agent should verify that the argument list is statically built or properly quoted.
- Find process-execution sinks (
- org.openrewrite.kotlin.search.FindConcurrencySurface$KtRecipe
- Find concurrency primitives
- Raw threads, executor-service factories, JUC locks, atomic primitives, futures, synchronized blocks,
@Volatilefields,ThreadLocalallocations, and JUC coordination primitives (Semaphore,CountDownLatch,CyclicBarrier). Each match is a position to inspect for cancellation semantics, happens-before edges, and pool lifecycle.
- org.openrewrite.kotlin.search.FindCryptoSeeds$KtRecipe
- Find cryptographic primitive entries (
KeyGenerator.generateKey,Cipher.getInstance, etc.) - Every cryptographic operation is a place where algorithm choice and key handling matter —
Cipher.getInstance("AES")is not the same asCipher.getInstance("AES/GCM/NoPadding"). Each match is a position for security review.
- Find cryptographic primitive entries (
- org.openrewrite.kotlin.search.FindDataFlowSinks$KtRecipe
- Find data-flow sink positions
- Locations where data crosses a trust or persistence boundary: SQL execution, filesystem writes, process execution, logger writes, outbound network, cryptographic operations, and Android clipboard access. Each match is a seed an LLM agent can connect back to upstream sources.
- org.openrewrite.kotlin.search.FindDataFlowSources$KtRecipe
- Find data-flow source positions
- Locations where untrusted or configuration-controlled data enters the program:
readLine/Scannerreads, environment/system-property reads, HTTP request reads, and filesystem reads. Each match is a seed an LLM agent (or human reviewer) can connect to downstream sinks.
- org.openrewrite.kotlin.search.FindDatabaseSeeds$KtRecipe
- Find database-query seeds
- Individual SQL execution and JPA query construction calls (
Statement.executeQuery,Statement.executeUpdate,EntityManager.createQuery). Each match is a position where a SQL/JPQL string crosses into the database layer.
- org.openrewrite.kotlin.search.FindDeepNesting$KtRecipe
- Find functions with nesting depth greater than 4
- Deeply nested control flow is the canonical hard-to-read code smell. For human reviewers and LLM agents alike, nesting beyond 4 levels signals the body should be split or flattened with early returns.
- org.openrewrite.kotlin.search.FindDeprecatedDeclarations$KtRecipe
- Find declarations annotated
@Deprecated - A
@Deprecateddeclaration is API the maintainers want callers to migrate away from. Each match is a candidate to revisit either the deprecation timeline or the replacement strategy.
- Find declarations annotated
- org.openrewrite.kotlin.search.FindEmptyCatchBlocks$KtRecipe
- Find
catchblocks with empty bodies - An empty
catchblock silently swallows failures — usually a bug or, at minimum, a missing comment explaining the intent. Flag for review so a reviewer or LLM agent can either log, rethrow, or document the swallow.
- Find
- org.openrewrite.kotlin.search.FindEmptyFunctions$KtRecipe
- Find functions with empty bodies
- An empty function body either belongs to a stub, an abstract-method override that intentionally does nothing, or forgotten work. For a reviewer or LLM agent reading the file, each match is a position where the contract claims something happens but nothing does.
- org.openrewrite.kotlin.search.FindEntityManagerCreateQuery$KtRecipe
- Find
EntityManager.createQuery(...)calls - Each JPA
createQueryis a JPQL/HQL execution seed — when the query string is built from user input, the same injection class applies as for raw SQL. Flag for parameter-binding review.
- Find
- org.openrewrite.kotlin.search.FindEnvironmentSources$KtRecipe
- Find
System.getenv(...)/System.getProperty(...)reads - Environment variables and system properties are operator-controlled configuration values. Each read is a configuration seam — a reviewer or LLM agent reading the code should know which knobs the program exposes.
- Find
- org.openrewrite.kotlin.search.FindExecutorServiceFactories$KtRecipe
- Find
Executors.newXxxThreadPoolfactory calls - Each
Executors.newXxxcall allocates a thread pool that needs explicit lifecycle (shutdownon teardown). For services that need bounded resources, each allocation is a candidate for review — and for an LLM agent, the call site reveals where the application's parallelism budget lives.
- Find
- org.openrewrite.kotlin.search.FindFieldReflection$KtRecipe
- Find
java.lang.reflect.Field.get/setcalls - Direct field reads/writes via reflection bypass property accessors and
privatevisibility. Each call is a position where invariants the surrounding code relies on can be silently violated.
- Find
- org.openrewrite.kotlin.search.FindFileReadBytes$KtRecipe
- Find
File.readBytes()calls - Each
File.readBytescall reads a file's raw bytes into memory — useful as a filesystem-read seed and as a hint that the program holds the whole file in memory (vs. streaming).
- Find
- org.openrewrite.kotlin.search.FindFileReadSources$KtRecipe
- Find filesystem read calls (
File.readText,Files.readString, etc.) - Filesystem reads are the application's IO surface — each call is data crossing a trust boundary set by the deployment's filesystem permissions. Useful as a seed for reasoning about cold-path latency, security boundaries, and what the program depends on at runtime.
- Find filesystem read calls (
- org.openrewrite.kotlin.search.FindFileReadText$KtRecipe
- Find
File.readText()calls - Each
File.readTextcall reads bytes off the filesystem — a trust-boundary position where the file's content becomes program data. Useful as an individual read seed for path-traversal or cold-path latency analysis.
- Find
- org.openrewrite.kotlin.search.FindFileSystemSeeds$KtRecipe
- Find filesystem-operation seeds
- Individual filesystem reads, writes, deletes, and copies via
java.io.Fileandjava.nio.file.Files. Each match is a position where the program crosses the filesystem trust boundary.
- org.openrewrite.kotlin.search.FindFileWriteSinks$KtRecipe
- Find filesystem write calls (
File.writeText,Files.write, etc.) - Filesystem writes are persistent side effects — each call is data crossing a trust boundary in the other direction. Useful as a seed for reasoning about what the application persists and where path-traversal vulnerabilities can land.
- Find filesystem write calls (
- org.openrewrite.kotlin.search.FindFileWriteText$KtRecipe
- Find
File.writeText(...)calls - Each
File.writeTextcall writes data to disk — a persistent side effect at the application's IO boundary. Useful as an individual write seed for path-traversal or trust-boundary analysis.
- Find
- org.openrewrite.kotlin.search.FindFilesCopy$KtRecipe
- Find
Files.copy(...)calls - Each
Files.copycall duplicates filesystem content — flag as a write seed where source/destination path provenance andCopyOptions (REPLACE_EXISTING, etc.) should be reviewed.
- Find
- org.openrewrite.kotlin.search.FindFilesDelete$KtRecipe
- Find
Files.delete(...)/Files.deleteIfExists(...)calls - Each call deletes a file from disk — a destructive filesystem operation. Flag as a seed for review of path provenance, e.g. whether the path is attacker-controlled and whether the deletion is intentional.
- Find
- org.openrewrite.kotlin.search.FindFilesNewBufferedWriter$KtRecipe
- Find
Files.newBufferedWriter(...)calls - Each
Files.newBufferedWritercall opens a streaming writer to a file — a long-lived write seed where charset,OpenOptions, and close handling all matter.
- Find
- org.openrewrite.kotlin.search.FindFilesWriteString$KtRecipe
- Find
Files.writeString(...)calls - Each
java.nio.file.Files.writeStringcall commits text to disk via the NIO API. Useful as an individual write seed and a position where charset andOpenOptions should be reviewed.
- Find
- org.openrewrite.kotlin.search.FindFutureAllocations$KtRecipe
- Find
CompletableFuture/FutureTaskallocations CompletableFuture(andFutureTask) interleave with their own thread pool; from Kotlin,Deferred/asyncintegrates with structured concurrency. Each allocation is a candidate to migrate or at minimum to review for cancellation handling.
- Find
- org.openrewrite.kotlin.search.FindGenericExceptionCatch$KtRecipe
- Find
catch (e: Exception)andcatch (e: Throwable)clauses - Catching
ExceptionorThrowableis almost always too broad — it sweeps upNullPointerException,IllegalStateException, andOutOfMemoryErrorinto one branch. Narrow the catch to the specific exception types the block actually handles.
- Find
- org.openrewrite.kotlin.search.FindGodClasses$KtRecipe
- Find classes with more than 25 methods
- A class with this many methods has likely accreted responsibility over time. Flag for splitting along the methods' natural seams — repository vs mapper, view-model vs presenter, etc.
- org.openrewrite.kotlin.search.FindHardcodedColorLiterals$KtRecipe
- Find
Color(0xFF...)color-literal constructions - Hardcoded ARGB literals inside
Color(0xFF...)calls are a design-token leak — they should usually live in a theme or material color scheme. Each match is a candidate to extract toMaterialTheme.colorScheme.X.
- Find
- org.openrewrite.kotlin.search.FindHardcodedLiterals$KtRecipe
- Find hardcoded literals and error-handling smells
- Hardcoded design tokens (
Color(0xFF...)), emptycatchblocks, overly-broadcatch (e: Exception)clauses, andthrow RuntimeException(...)calls. Each match is a position where intent is unclear or recovery is too broad.
- org.openrewrite.kotlin.search.FindHotspots$KtRecipe
- Find hotspots and complexity points
- Surface large classes, long functions, wide parameter lists, sprawling
whenexpressions, deep nesting, god classes, magic numbers, and unmarked self-recursion. Each match is a candidate for a reviewer (or LLM agent) to refactor or to read carefully when building a mental model of the file.
- org.openrewrite.kotlin.search.FindHttpClientConstructions$KtRecipe
- Find HTTP client construction sites
- Each HTTP client construction is a place where connection pooling, timeouts, retry policy, and TLS settings are committed. Flag for review so a reviewer or LLM agent can confirm the call site picks the right policy rather than the defaults.
- org.openrewrite.kotlin.search.FindHttpRequestSources$KtRecipe
- Find
HttpServletRequest.getParameter/getHeader/getCookiesreads - Servlet-API request reads return raw, attacker-controlled strings. Each call is a taint root — anywhere the returned value flows into an SQL query, a filesystem path, or HTML output is a candidate vulnerability the reviewer should trace.
- Find
- org.openrewrite.kotlin.search.FindHttpURLConnection$KtRecipe
- Find
HttpURLConnectionreferences HttpURLConnectionis the JVM's built-in HTTP client — each reference is a position where external HTTP traffic is configured (timeouts, redirects, request method). Flag as an outbound-network seed.
- Find
- org.openrewrite.kotlin.search.FindIgnoredTests$KtRecipe
- Find
@Disabled/@Ignoretest annotations - An ignored test is a regression-detection gap — at minimum it represents technical debt; at worst it's a silenced failure that turned chronic. Each match is a candidate to triage.
- Find
- org.openrewrite.kotlin.search.FindInsecureRandomSources$KtRecipe
- Find non-cryptographic random sources (
Math.random,kotlin.random.Random,java.util.Random) - Non-cryptographic randomness is fine for jitter, simulation, sampling — but each call is a position to verify that no security-relevant value (session token, password reset link, nonce) flows from it. Use
SecureRandominstead in those positions.
- Find non-cryptographic random sources (
- org.openrewrite.kotlin.search.FindJacksonObjectMapperReadValue$KtRecipe
- Find Jackson
ObjectMapper.readValue(...)calls - Each
readValueis a JSON-deserialization sink — when the input bytes are attacker-controlled, the configured polymorphic-typing and visibility settings of theObjectMapperbecome security-relevant. Flag as a deserialization seed.
- Find Jackson
- org.openrewrite.kotlin.search.FindJacksonObjectMapperWriteValue$KtRecipe
- Find Jackson
ObjectMapper.writeValue*(...)calls - Each
writeValue/writeValueAsString/writeValueAsBytescall serializes a Kotlin object to JSON — useful as a seed for tracking which types cross the JSON boundary (DTO surface) and where sensitive fields might leak.
- Find Jackson
- org.openrewrite.kotlin.search.FindJvmFieldAnnotations$KtRecipe
- Find
@JvmFieldannotations @JvmFieldexposes a Kotlin property as a public Java field — bypassing the generated getter/setter and freezing the storage layout in the binary API. Each match is a constraint on future refactors.
- Find
- org.openrewrite.kotlin.search.FindJvmOverloadsAnnotations$KtRecipe
- Find
@JvmOverloadsannotations @JvmOverloadsemits N synthetic Java overloads for a Kotlin function with default parameters. Each annotation is a hint the function is part of the Java-facing surface; reordering parameters or changing defaults breaks the synthetic overloads.
- Find
- org.openrewrite.kotlin.search.FindJvmStaticAnnotations$KtRecipe
- Find
@JvmStaticannotations @JvmStaticdeclares a member function that should appear as a JVM static — a Java-interop affordance. Each annotation is a hint that the API is consumed from Java code, which constrains how it can evolve.
- Find
- org.openrewrite.kotlin.search.FindKClassConstructors$KtRecipe
- Find
KClass.constructorsaccess - Reflective access to
KClass.constructorsreveals every constructor of a Kotlin class at runtime. Each match is a seed where reflective allocation is plausible — opaque to static analysis.
- Find
- org.openrewrite.kotlin.search.FindKClassDeclaredFunctions$KtRecipe
- Find
KClass.declaredFunctions/declaredMemberFunctionsaccess - Access to
KClass.declaredFunctions(and its variants) walks every declared function of a Kotlin class via reflection. Each call is a reflection seed — opaque to static analysis and requireskotlin-reflect.jarat runtime.
- Find
- org.openrewrite.kotlin.search.FindKClassMembers$KtRecipe
- Find
KClass.members/memberFunctions/memberPropertiesaccess - Access to
KClass.members(and its sibling reflective collections) requireskotlin-reflect.jarat runtime and walks every declared member of the class. Each call is a position where reflection over a Kotlin type is happening — opaque to static analysis.
- Find
- org.openrewrite.kotlin.search.FindKClassMembersAccess$KtRecipe
- Find Kotlin reflection (
KClass.memberFunctions,KClass.members, etc.) - Kotlin reflection (
kotlin.reflect.*) needskotlin-reflect.jaron the classpath and adds significant cold-start cost. Each call is also a reflective dispatch — invisible to static analysis — so a reviewer/agent should know it's there.
- Find Kotlin reflection (
- org.openrewrite.kotlin.search.FindKotestSpecs$KtRecipe
- Find Kotest spec classes
- A class extending a Kotest spec (
FunSpec,BehaviorSpec, etc.) is a test entrypoint. Listing them helps a reviewer or LLM agent map a module's test surface without crawling annotations.
- org.openrewrite.kotlin.search.FindLargeClasses$KtRecipe
- Find classes with more than 200 statements
- Large classes accumulate responsibility — they bury invariants and slow every cross-cutting edit. As LLM context, an oversized class dominates the window with details that may not be relevant to the task; flagging them helps a reviewer (or an agent) decide where to split.
- org.openrewrite.kotlin.search.FindLargeWhenBranches$KtRecipe
- Find
whenexpressions with more than 10 branches - A
whenwith many branches is often hiding a sealed-class or strategy-table refactor — and even when it isn't, it's a hotspot a reviewer or LLM agent should see when scanning a file. Each match is a candidate for restructuring.
- Find
- org.openrewrite.kotlin.search.FindLogWriteSinks$KtRecipe
- Find logger write calls (
info/warn/error/debug) - Logger calls can persistently capture user-controlled data into log aggregators — a PII-leak seed. Each match is a candidate to verify that the format arguments don't include sensitive fields or that a redaction layer wraps the call.
- Find logger write calls (
- org.openrewrite.kotlin.search.FindLongFunctions$KtRecipe
- Find functions with more than 30 statements
- Long functions hide branching and are harder to test, refactor, and reason about. For an LLM agent reading the file, an oversized body eats tokens disproportionately and obscures the contract — flag for review or extraction.
- org.openrewrite.kotlin.search.FindMagicNumbers$KtRecipe
- Find numeric literals other than 0, 1, -1
- Magic numbers in code hide units, bounds, and protocol constants from a reader. Each match is a candidate to extract to a named
const valso a reviewer or LLM agent can see the intent (MAX_RETRIES,BUFFER_BYTES, etc.) rather than the bare literal.
- org.openrewrite.kotlin.search.FindManyParameters$KtRecipe
- Find functions with more than 5 parameters
- A long parameter list usually signals a missing aggregate (data class, builder, parameter object). For a reviewer or LLM agent, the parameter signature is the contract — when it's too wide, the call sites become hard to read and refactor in lockstep.
- org.openrewrite.kotlin.search.FindMethodInvoke$KtRecipe
- Find
java.lang.reflect.Method.invoke(...)calls - Calls through
Method.invokeare reflective dispatch — the target body is opaque to static analysis. Flag for review whenever a reader needs to know which functions are actually reachable.
- Find
- org.openrewrite.kotlin.search.FindMockkAllocations$KtRecipe
- Find
mockk<X>()/mockk(...)calls - Each
mockkallocation is a test-time fake — the production type it stands in for is the seam under test. Flagging them helps a reviewer or LLM agent see what is real and what is faked inside a test.
- Find
- org.openrewrite.kotlin.search.FindNetworkSinks$KtRecipe
- Find outbound-network sinks (
URL.openConnection,OkHttpClient.newCall, etc.) - Outbound network calls are SSRF candidates whenever the URL or request body flows from a request parameter. Each match is a seed for tracing where the program reaches into the outside world.
- Find outbound-network sinks (
- org.openrewrite.kotlin.search.FindNetworkingSeeds$KtRecipe
- Find outbound-networking seeds
- HTTP client and connection construction sites:
HttpURLConnection,okhttp3.OkHttpClient,okhttp3.Request.Builder. Each match is a position where the program reaches out to the network.
- org.openrewrite.kotlin.search.FindNotNullAssertions$KtRecipe
- Find
!!not-null assertions - Each
!!is a runtime promise — when the receiver turns out to benull, the program crashes with aNullPointerException. A reviewer or LLM agent reading the code should know which positions are betting against the type system; many of them are candidates for?.let \{ … \}or arequireNotNullwith a better diagnostic.
- Find
- org.openrewrite.kotlin.search.FindObjectOutputStreamWriteObject$KtRecipe
- Find
ObjectOutputStream.writeObject(...)calls - Java serialization is brittle and a known security hazard on the read side; the write side is a seed where the on-wire/on-disk format gets fixed. Flag for review when migrating away from Java serialization.
- Find
- org.openrewrite.kotlin.search.FindOkHttpClient$KtRecipe
- Find
okhttp3.OkHttpClientconstructions - Each
OkHttpClientallocation commits a set of timeouts, interceptors, and connection-pool settings for outbound HTTP. Flag as an outbound-network seed and a configuration-policy review point.
- Find
- org.openrewrite.kotlin.search.FindOkHttpRequestBuilder$KtRecipe
- Find
okhttp3.Request.Builder()constructions - Each
Request.Builder()is the construction site of an outbound OkHttp request. Flag as an outbound-network seed — a reviewer or LLM agent should check the URL source and request body for attacker-controlled data.
- Find
- org.openrewrite.kotlin.search.FindOptInAnnotations$KtRecipe
- Find
@OptIn(...)annotations - An
@OptInannotation acknowledges that the annotated declaration uses an experimental API. The site of the opt-in is where the contract risk lives — if the upstream changes the API, this is the file that breaks.
- Find
- org.openrewrite.kotlin.search.FindParameterizedTests$KtRecipe
- Find
@ParameterizedTestannotations - Parameterized tests cover families of inputs in a single declaration. Each annotation is a position where one test class line generates many test instances — useful context when reading coverage reports.
- Find
- org.openrewrite.kotlin.search.FindPublicConstants$KtRecipe
- Find public
const valdeclarations - A public
const valis part of the binary API surface — changing its value at the source recompiles dependents, but stale clients keep the old constant inlined. Flag for awareness when reviewing API stability.
- Find public
- org.openrewrite.kotlin.search.FindPublicLateinit$KtRecipe
- Find public
lateinit vardeclarations lateinit vardefers initialization but exposes a mutable, possibly-uninitialized property. As public API, every caller can both read (and potentially triggerUninitializedPropertyAccessException) and write the field. Flag for review of encapsulation.
- Find public
- org.openrewrite.kotlin.search.FindRecursionWithoutTailrec$KtRecipe
- Find recursive functions not marked
tailrec - A self-recursive function that doesn't carry the
tailrecmodifier won't get the Kotlin compiler's stack-elimination transform. Each match is a candidate to either annotate (if the recursive call is in tail position) or rewrite to an iterative form.
- Find recursive functions not marked
- org.openrewrite.kotlin.search.FindReentrantLockAllocations$KtRecipe
- Find
ReentrantLock()/ReentrantReadWriteLock()allocations - Each
ReentrantLockallocation is a manual concurrency primitive. Flag for review — in coroutine code,Mutexis usually the cooperative-cancellation-friendly replacement.
- Find
- org.openrewrite.kotlin.search.FindReflectionGetField$KtRecipe
- Find
Class.getDeclaredField/Class.getFieldcalls - Each
getDeclaredField/getFieldcall is a reflective lookup of a field by name — the name is opaque to static analysis, so the field reference is invisible to rename refactorings. Flag as a reflection seed.
- Find
- org.openrewrite.kotlin.search.FindReflectionSeeds$KtRecipe
- Find reflection seeds
- Field/member/constructor reflection over Java and Kotlin types (
Class.getDeclaredField,KClass.members,KClass.declaredFunctions,KClass.constructors). Each match is a position where program behavior is opaque to static analysis and depends on runtime symbol lookup.
- org.openrewrite.kotlin.search.FindReflectionSurface$KtRecipe
- Find reflection and runtime introspection
- Reflection entry points (
Class.forName,Method.invoke,Field.get/set, kotlin.reflect calls,ServiceLoader.load), visibility overrides (setAccessible(true)), and unsafeascasts. Each match is opaque to static analysis — a reviewer/agent should know it's there before reasoning about what the program touches.
- org.openrewrite.kotlin.search.FindRequiresOptInDeclarations$KtRecipe
- Find declarations annotated
@RequiresOptIn - A
@RequiresOptInannotation defines a new opt-in marker — every caller must explicitly acknowledge it via@OptIn. Each match here is a place where stability semantics are being defined, not just consumed.
- Find declarations annotated
- org.openrewrite.kotlin.search.FindSemaphoreOrLatchAllocations$KtRecipe
- Find
Semaphore/CountDownLatch/CyclicBarrierallocations - Classic JUC coordination primitives indicate hand-rolled concurrency. In coroutine code,
kotlinx.coroutines.sync.SemaphoreandCompletableDeferredare the cooperative equivalents. Flag the call site for review.
- Find
- org.openrewrite.kotlin.search.FindSerializationSeeds$KtRecipe
- Find serialization seeds
- Java serialization writes and Jackson read/write calls (
ObjectOutputStream.writeObject,ObjectMapper.readValue,ObjectMapper.writeValue*). Each match is a position where Kotlin objects cross an external wire/disk format boundary.
- org.openrewrite.kotlin.search.FindServiceLoader$KtRecipe
- Find
ServiceLoader.load(...)calls ServiceLoader.loadwalks META-INF/services at boot time and instantiates each provider via reflection. The set of loaded classes isn't visible to static analysis — each call is a fan-out point for a reviewer to understand.
- Find
- org.openrewrite.kotlin.search.FindSetAccessibleTrue$KtRecipe
- Find
AccessibleObject.setAccessible(true)calls setAccessible(true)bypasses Java/Kotlin visibility. It's a strong signal of either a serialization library at work or a workaround for a missing API — either way, a reviewer/agent reading the code should be aware that visibility cannot be trusted here.
- Find
- org.openrewrite.kotlin.search.FindSqlExecutionSinks$KtRecipe
- Find SQL execution sinks (
Statement.execute*,prepareStatement,createNativeQuery) - SQL execution is the canonical SQL-injection sink — every string argument that reaches one of these calls without parameter binding is a candidate vulnerability. As a data-flow seed, the call site is where untrusted strings either become parameter-bound or stay concatenated.
- Find SQL execution sinks (
- org.openrewrite.kotlin.search.FindStatementExecuteQuery$KtRecipe
- Find
Statement.executeQuery(sql)calls - Each
executeQueryis a SQL read sink — ifsqlis built from user-controlled strings without binding, it's a SQL-injection candidate. Useful as an individual seed even when the broaderFindSqlExecutionSinkscomposite is too coarse.
- Find
- org.openrewrite.kotlin.search.FindStatementExecuteUpdate$KtRecipe
- Find
Statement.executeUpdate(sql)calls - Each
executeUpdateis a SQL write sink — INSERT/UPDATE/DELETE built from string concatenation is the canonical injection pattern. Useful as an individual seed even when the broader composite is too coarse.
- Find
- org.openrewrite.kotlin.search.FindStdinSources$KtRecipe
- Find
readLine()/Scanner.next*()calls - Standard-input reads are user-controlled bytes — every downstream use of the returned string is a candidate taint root. Tagging the call site lets a downstream analysis (human or LLM agent) trace where untrusted data flows.
- Find
- org.openrewrite.kotlin.search.FindSynchronizedBlocks$KtRecipe
- Find
synchronized(lock) \{ ... \}calls - Each
synchronizedblock is a JVM monitor-acquire/release — incompatible with coroutine cancellation and a candidate forMutex/withLockin suspend code. Flag for review of contention and cancellation semantics.
- Find
- org.openrewrite.kotlin.search.FindTestNameAnnotations$KtRecipe
- Find
@DisplayName(...)test annotations - JUnit 5
@DisplayNameoverrides the rendered test name. Listing them helps a reviewer or LLM agent see where the source's function name and the test's reported name diverge — relevant for triaging CI failures.
- Find
- org.openrewrite.kotlin.search.FindTestSurface$KtRecipe
- Find test-surface positions
- Disabled/ignored tests, slow-tagged tests, mockk fakes, AssertJ assertion chains, and Kotest spec classes. Each match helps a reviewer or LLM agent navigate a module's test surface and verification logic.
- org.openrewrite.kotlin.search.FindTestsTaggedSlow$KtRecipe
- Find tests tagged
@Tag("slow") - Slow-tagged tests usually live behind a separate CI lane. Each match is a candidate to either speed up (find the underlying source of slowness) or to verify the tag is wired into the build's test selection.
- Find tests tagged
- org.openrewrite.kotlin.search.FindThreadConstructors$KtRecipe
- Find
Thread(...)constructor calls - Each raw
Thread(...)constructor is an unmanaged thread allocation — no pool, no lifecycle. On JVM/Android code that ships with Kotlin coroutines or a structured executor service, these are usually candidates to migrate to a managed scope.
- Find
- org.openrewrite.kotlin.search.FindThreadLocalAllocations$KtRecipe
- Find
ThreadLocal()allocations ThreadLocalties state to a thread identity that coroutines do not preserve across suspension. Each allocation is a candidate to migrate to aCoroutineContext.Elementor to confirm the call site is non-suspending.
- Find
- org.openrewrite.kotlin.search.FindThrowGenericException$KtRecipe
- Find
throw Exception(...)andthrow RuntimeException(...)calls - Throwing a bare
Exception/RuntimeExceptionforces every caller into a generic catch. Each match is a candidate to use a more specific exception type (IllegalArgumentException,IllegalStateException, a domain-specific subclass).
- Find
- org.openrewrite.kotlin.search.FindUnsafeCast$KtRecipe
- Find bare
ascasts (unsafe) - A bare
ascast throwsClassCastExceptionon a mismatch — every cast is a runtime contract the compiler can't enforce. Where the result might legitimately be the wrong type, preferas?(returningnull) so the failure surfaces as a nullable handling decision rather than an exception.
- Find bare
- org.openrewrite.kotlin.search.FindVolatileFields$KtRecipe
- Find
@Volatileproperties @Volatileproperties announce concurrent mutation — every read/write is a happens-before edge that downstream code relies on. Each match is a position a reviewer or LLM agent should inspect for memory-ordering bugs.
- Find
- org.openrewrite.kotlin.search.FindWildcardImports$KtRecipe
- Find
import x.*wildcard imports - Wildcard imports pull every public name from a package into the file's symbol table — making it harder for a reviewer or LLM agent to tell where a name comes from. Each match is a candidate to expand into explicit imports.
- Find
- org.openrewrite.kotlin.search.Search$KtRecipe
- Surface impact-analysis findings
- Search-only recipes that help an LLM coding agent or human reviewer build a mental map of the codebase: hotspots, hardcoded literals, reflection, concurrency primitives, public-API stability surface, dataflow source/sink locations, the test surface, and source-organization smells. Each match is a
SearchResult— nothing is rewritten automatically.
- org.openrewrite.kotlin.security.FindAesDefaultMode$KtRecipe
- Find
Cipher.getInstance("AES")calls without a mode - Bare
"AES"defaults toAES/ECB/PKCS5Paddingon the SunJCE provider — ECB mode is broken for any data with structure. Specify"AES/GCM/NoPadding"explicitly so the cipher is portable and authenticated.
- Find
- org.openrewrite.kotlin.security.FindAllowAllHostnameVerifierLambda$KtRecipe
- Find
HostnameVerifier \{ _, _ -> true \}lambdas - A
HostnameVerifierthat returnstrueaccepts a certificate for any hostname — defeats the purpose of TLS hostname pinning and enables straightforward MITM. Verify the hostname against the cert's CN/SAN, or use the platform default verifier.
- Find
- org.openrewrite.kotlin.security.FindAndroidLogSensitive$KtRecipe
- Find
android.util.Log.\{d,i,v,w,e\}calls with sensitive content android.util.Logwrites tologcat, which on rooted devices and viaadb logcatis world-readable. Don't putpassword,token, or any PII into log messages — production builds should strip logging via R8/ProGuard rules.
- Find
- org.openrewrite.kotlin.security.FindAndroidSecuritySmells$KtRecipe
- Find Android-specific security smells
- Deprecated world-readable/writeable file modes,
WebViewJavaScript enablement andaddJavascriptInterfaceexposure, plaintextSharedPreferencesfor sensitive data, and implicitIntentbroadcasts that any app on the device can intercept.
- org.openrewrite.kotlin.security.FindAwsAccessKeyLiteral$KtRecipe
- Find AWS Access Key literals (
AKIA…) - AWS access keys begin with
AKIAfollowed by 16+ uppercase/digit characters. A literalAKIA…in source means the key is in every artifact build, every git commit, and every developer machine. Rotate immediately and load from environment orSecretsManager.
- Find AWS Access Key literals (
- org.openrewrite.kotlin.security.FindBasicAuthLiteral$KtRecipe
- Find
"Basic <base64>"literals in source - A literal
Basic <base64>header in source is a static credential; rotating it requires a deploy. Build the header from credentials loaded at startup.
- Find
- org.openrewrite.kotlin.security.FindCipherCbcWithoutMac$KtRecipe
- Find
Cipher.getInstance("AES/CBC/...")calls — verify integrity - AES/CBC is unauthenticated — without a separate MAC, the ciphertext is vulnerable to padding-oracle attacks (BEAST, POODLE family). Prefer
AES/GCM/NoPaddingfor AEAD in one step, or pair CBC with an HMAC under encrypt-then-MAC.
- Find
- org.openrewrite.kotlin.security.FindCipherEcbMode$KtRecipe
- Find
Cipher.getInstance("AES/ECB/...")calls - ECB mode encrypts identical plaintext blocks to identical ciphertext blocks, leaking structure (the famous "ECB penguin"). Use AES/GCM/NoPadding or AES/CBC/PKCS5Padding with a random IV per message.
- Find
- org.openrewrite.kotlin.security.FindCipherInitWithoutSecureRandom$KtRecipe
- Find two-argument
Cipher.init(opmode, key)calls - The two-argument
Cipher.init(opmode, key)lets the JCE pick an IV — that IV is generated from a provider-defaultSecureRandom, which is fine, but for CBC/GCM you usually want to control the IV explicitly so it can be transmitted alongside the ciphertext. Pass anIvParameterSpec(orGCMParameterSpec) generated fromSecureRandom.
- Find two-argument
- org.openrewrite.kotlin.security.FindClassForNameWithNonLiteral$KtRecipe
- Find
Class.forName(...)calls with non-literal arguments Class.forName(input)lets the caller choose a class to load — the classic gadget chain for deserialization-style attacks and unsafe reflection. Match against a sealed allowlist instead.
- Find
- org.openrewrite.kotlin.security.FindCookieHttpOnlyFalse$KtRecipe
- Find
Cookie.setHttpOnly(false)calls setHttpOnly(false)makes the cookie readable from JavaScript — directly exfiltratable by any XSS bug in the same origin. SethttpOnly = truefor every session cookie.
- Find
- org.openrewrite.kotlin.security.FindCookieSecureFalse$KtRecipe
- Find
Cookie.setSecure(false)calls setSecure(false)lets the cookie travel over plain HTTP — anyone on the path (coffee-shop wifi, ISP) can read it. For any session cookie, setsecure = trueandhttpOnly = true, and preferSameSite=Strict.
- Find
- org.openrewrite.kotlin.security.FindFilePathConcat$KtRecipe
- Find
File("..." + input)constructions - Concatenating user input into a
File(...)path is the canonical path-traversal vector (../etc/passwd). Resolve against a fixed base withFile(base, name)plus an explicitcanonicalPath.startsWith(baseCanonicalPath)check.
- Find
- org.openrewrite.kotlin.security.FindGitHubPatLiteral$KtRecipe
- Find GitHub PAT literals (
ghp_…) - GitHub personal access tokens begin with
ghp_and are full-scope unless the PAT is fine-grained. A literalghp_…in source must be revoked at github.com/settings/tokens immediately.
- Find GitHub PAT literals (
- org.openrewrite.kotlin.security.FindGoogleApiKeyLiteral$KtRecipe
- Find Google API key literals (
AIza…) - Google Cloud / Firebase / Maps API keys follow the
AIza…39-char pattern. Even when client-restricted, a leaked literal lets attackers fingerprint your project and run up bills via unrestricted endpoints.
- Find Google API key literals (
- org.openrewrite.kotlin.security.FindHardCodedSecrets$KtRecipe
- Find hard-coded secret literals
- High-confidence regex matches for AWS access keys, GitHub PATs, Stripe API keys, Google API keys, Slack tokens, and JWTs — plus a heuristic match for properties named
password/secret/token/apiKeywith non-empty string defaults. Each match needs immediate rotation if it is a real credential.
- org.openrewrite.kotlin.security.FindHttpUrlLiteral$KtRecipe
- Find
URL("http://...")literal constructions - Constructing a
java.net.URLfrom anhttp://literal opts out of TLS. If the host genuinely is HTTP-only, document the exception; otherwise switch the literal tohttps://.
- Find
- org.openrewrite.kotlin.security.FindInjectionVectors$KtRecipe
- Find injection vectors
- SQL string concatenation into
Statement/PreparedStatement, command injection viaRuntime.execandProcessBuilder, path traversal viaFileconcatenation, unsafe reflection viaClass.forName(input), and dynamic-script evaluation viaScriptEngine.
- org.openrewrite.kotlin.security.FindInsecureSessionConfig$KtRecipe
- Find insecure cookie / session configuration
- Cookies missing the
SecureorHttpOnlyflag leak to plain HTTP or JavaScript. Each match should set both flags totrueand considerSameSite=Strict.
- org.openrewrite.kotlin.security.FindInsecureTls$KtRecipe
- Find insecure TLS configuration
- Trust-everything
X509TrustManagerimplementations, allow-allHostnameVerifierlambdas / setters, deprecated SSL/TLS protocol versions, and plain-HTTP URL literals.
- org.openrewrite.kotlin.security.FindIntentExplicitActionLiteral$KtRecipe
- Find
Intent("some.implicit.action")constructions - An
Intentconstructed with a string action becomes an implicit broadcast — any app declaring a matching<intent-filter>can receive it (and potentially read PII the sender attached). Prefer explicit intents withIntent(context, Activity::class.java), or send withLocalBroadcastManager/setPackage(...).
- Find
- org.openrewrite.kotlin.security.FindJavaUtilRandomForSecurity$KtRecipe
- Find
java.util.Random()allocations java.util.Randomis a linear-congruential generator — its state is recoverable from a handful of outputs, so it must not produce session IDs, tokens, salts, IVs, or password reset values. Usejava.security.SecureRandomfor any security-adjacent randomness.
- Find
- org.openrewrite.kotlin.security.FindJjwtSetSigningKeyLiteral$KtRecipe
- Find
JwtBuilder.setSigningKey("literal".toByteArray())patterns - A hard-coded signing key compromises every token your service ever issues — anyone with the source (or the artifact, since literals end up in the constant pool) can forge tokens. Load the key from a secret store; rotate on a schedule.
- Find
- org.openrewrite.kotlin.security.FindJjwtSignWithNone$KtRecipe
- Find
JwtBuilder.signWith(SignatureAlgorithm.NONE, ...)patterns alg=nonelets anyone forge a JWT — there is no signature to verify. Use HS256 (with a strong secret) or RS256/ES256 (with an asymmetric key pair).
- Find
- org.openrewrite.kotlin.security.FindJndiLookupWithNonLiteral$KtRecipe
- Find
InitialContext.lookup(input)calls with non-literal arguments - Dynamic JNDI lookups are the Log4Shell (CVE-2021-44228) pattern — a controlled URL can fetch a remote class file and execute it. Pin lookup names to a literal allowlist; disable remote codebase loading.
- Find
- org.openrewrite.kotlin.security.FindJwtAlgNoneLiteral$KtRecipe
- Find
"alg":"none"literal strings - Any literal containing
alg=noneis suspicious — even in tests, copy-paste tends to leak these into production assertions. Replace with HS256/RS256/ES256.
- Find
- org.openrewrite.kotlin.security.FindJwtLiteral$KtRecipe
- Find JWT literals (
eyJ…-prefixed three-segment tokens) - A literal JWT in source is a long-lived signed token sitting in git history. Even if it's expired, it documents the claims structure and signing context. Replace with a fixture-generated token in tests; remove entirely from production code.
- Find JWT literals (
- org.openrewrite.kotlin.security.FindJwtMisuse$KtRecipe
- Find JWT misuse
- Hard-coded JJWT signing keys,
signWith(NONE)patterns that produce unsigned tokens, and literal"alg":"none"strings that show up in headers and test fixtures alike.
- org.openrewrite.kotlin.security.FindKeyGeneratorDes$KtRecipe
- Find
KeyGenerator.getInstance("DES")calls - Generating a DES key feeds a known-broken cipher. Use
KeyGenerator.getInstance("AES").apply \{ init(256) \}instead.
- Find
- org.openrewrite.kotlin.security.FindKotlinRandomForSecurity$KtRecipe
- Find
kotlin.random.Random.Defaultreferences kotlin.random.Random.Defaultdelegates to a platform default RNG that on JVM isThreadLocalRandom— not cryptographically secure. For tokens, session IDs, salts, etc. usejava.security.SecureRandom.
- Find
- org.openrewrite.kotlin.security.FindModeWorldReadable$KtRecipe
- Find
MODE_WORLD_READABLEreferences MODE_WORLD_READABLE(andMODE_WORLD_WRITEABLE) were deprecated in API 17 and removed for security reasons — any other app on the device can read/write the file. Use the defaultMODE_PRIVATEmode and grant explicit cross-app access viaFileProvider.
- Find
- org.openrewrite.kotlin.security.FindNullCipher$KtRecipe
- Find
NullCipher()allocations javax.crypto.NullCipheris a no-op cipher — itsdoFinalreturns the plaintext unchanged. Useful only for testing; if it ships in production code, the data is effectively unencrypted.
- Find
- org.openrewrite.kotlin.security.FindObjectInputStream$KtRecipe
- Find
ObjectInputStream(...)constructions - Java native deserialization is the source of the CVE-2015-4852 / Apache Commons gadget-chain family — any classpath gadget can fire on
readObject. Replace with a JSON or Protobuf decoder; if you must keep Java serialization, install anObjectInputFilter.
- Find
- org.openrewrite.kotlin.security.FindPathsGetWithConcat$KtRecipe
- Find
Paths.get("..." + input)calls - Same path-traversal risk as
File(...)concatenation. Resolve against a fixed base withPath.resolve(name)plus an explicitnormalize().startsWith(base)check.
- Find
- org.openrewrite.kotlin.security.FindPbkdf2LowIterationCount$KtRecipe
- Find
PBEKeySpec(..., iterations, ...)with low iteration counts - OWASP's PBKDF2 guidance (2023) recommends 600,000 iterations for SHA-256, 210,000 for SHA-512. Counts below 10,000 leak passwords to cheap GPU brute force.
- Find
- org.openrewrite.kotlin.security.FindPredictableIv$KtRecipe
- Find
IvParameterSpec(byteArrayOf(...))constructions with a literal IV - A constant IV defeats the IND-CPA guarantees of CBC/GCM/CTR — every message encrypted under the same key/IV pair leaks the same prefix structure. Generate a fresh IV per message from
SecureRandomand prepend it to the ciphertext.
- Find
- org.openrewrite.kotlin.security.FindPrepareStatementWithConcat$KtRecipe
- Find
prepareStatement("... " + x)calls PreparedStatementis only safe if the SQL is a fixed template — concatenating user input into the template beforeprepareStatementdefeats the parameter binding. Parameterize the variable portion with?.
- Find
- org.openrewrite.kotlin.security.FindPrintlnSensitive$KtRecipe
- Find
println("... password ...")patterns printlnwrites to stdout, which on production tends to land in container logs. Treat it like any other log sink — strip sensitive values before printing, or use a structured logger that redacts at the formatter.
- Find
- org.openrewrite.kotlin.security.FindPrivateKeyHeaderLiteral$KtRecipe
- Find
-----BEGIN ... PRIVATE KEY-----literals - A PEM-formatted private key in source means the private key is in every artifact, every git commit, and every developer machine. Load from a secrets store or a file outside the build.
- Find
- org.openrewrite.kotlin.security.FindProcessBuilderWithNonLiteral$KtRecipe
- Find
ProcessBuilder(varargs)constructions whose first arg is non-literal ProcessBuilderis safer thanRuntime.execbecause it bypasses the shell, but a dynamic program name (the first argument) still lets the caller pick any executable on thePATH. Pin the program name to a literal.
- Find
- org.openrewrite.kotlin.security.FindResponseSendRedirectWithNonLiteral$KtRecipe
- Find
HttpServletResponse.sendRedirect(input)calls with non-literal arguments - An unvalidated redirect URL lets an attacker craft a link that looks like it leads to your site but bounces to an attacker-controlled page (open-redirect / phishing). Validate against an allowlist or use a relative path.
- Find
- org.openrewrite.kotlin.security.FindRsaKeySizeBelow2048$KtRecipe
- Find
KeyPairGenerator.getInstance("RSA")callers — verify 2048+ key size - RSA key sizes below 2048 bits are deprecated by NIST. Without seeing the
initialize(...)call this recipe surfaces everygetInstance("RSA")for review — confirm the key size is at least 2048 (preferably 3072 or migrate to Ed25519/X25519).
- Find
- org.openrewrite.kotlin.security.FindRuntimeExecWithNonLiteral$KtRecipe
- Find
Runtime.getRuntime().exec(...)calls with non-literal arguments Runtime.exec(...)passes its argument to the shell on some platforms — concatenating any user input invites command injection. UseProcessBuilder(arrayOf("prog", arg))so each argument is passed as a discrete argv slot.
- Find
- org.openrewrite.kotlin.security.FindScriptEngineEval$KtRecipe
- Find
ScriptEngine.eval(...)calls ScriptEngine.eval(input)executes its argument as JavaScript (or Groovy / JRuby) — full code execution from a string. Replace with a domain-specific parser, or whitelist the script before evaluation.
- Find
- org.openrewrite.kotlin.security.FindScriptEngineManager$KtRecipe
- Find
ScriptEngineManager.getEngineByName(...)calls - Constructing a
ScriptEngineat all is usually a smell — once present, the engine is oneeval(...)away from a remote-code-execution finding. Confirm the engine is loaded from a trusted source and the inputs it receives are not user-controlled.
- Find
- org.openrewrite.kotlin.security.FindSecretKeySpecDes$KtRecipe
- Find
SecretKeySpec(_, "DES")constructions - A
SecretKeySpectagged for"DES"will only feedCipher.getInstance("DES")— the algorithm name flows through the JCE provider lookup. Replace with"AES"and a 256-bit key.
- Find
- org.openrewrite.kotlin.security.FindSecureRandomSetSeed$KtRecipe
- Find
SecureRandom.setSeed(...)with a literal seed SecureRandom.setSeed(literal)makes the RNG deterministic — defeats the whole point of using a CSPRNG. LetSecureRandomseed itself from the platform entropy source.
- Find
- org.openrewrite.kotlin.security.FindSensitiveDataInLogs$KtRecipe
- Find sensitive data in log calls
- Log calls (SLF4J,
println,android.util.Log) whose message string mentionspassword/token/secret/api_key/credit_card— each match likely renders the secret value into a log destination that isn't designed for secret storage.
- org.openrewrite.kotlin.security.FindSensitiveNamedVariableLiteral$KtRecipe
- Find variables named
password/secret/token/apiKeywith a non-empty literal default - A property literally named
password = "hunter2"(orval token = "…", etc.) is almost always a hard-coded secret. False positives include unit-test fixtures and placeholder strings — review each match before treating as a CVE.
- Find variables named
- org.openrewrite.kotlin.security.FindSetAllHostnameVerifier$KtRecipe
- Find
setHostnameVerifier(ALLOW_ALL)calls - Setting an Apache-style
ALLOW_ALL(or a custom always-true) hostname verifier disables one of TLS's two integrity checks. Remove the override and let the default verifier run.
- Find
- org.openrewrite.kotlin.security.FindSharedPreferencesForSensitiveData$KtRecipe
- Find
getSharedPreferences(_, MODE_PRIVATE)callers SharedPreferencesis stored as plain XML in app-private storage — on rooted or backed-up devices, that's readable. For tokens, refresh credentials, or PII useEncryptedSharedPreferences(androidx.security.crypto).
- Find
- org.openrewrite.kotlin.security.FindSlackTokenLiteral$KtRecipe
- Find Slack token literals (
xoxb-/xoxp-/xoxa-/xoxr-/xoxs-) - Slack bot/user/app tokens follow the
xox[abprs]-pattern. A leaked token lets a third party read channels, post as your bot, and pull workspace metadata.
- Find Slack token literals (
- org.openrewrite.kotlin.security.FindSlf4jLogSensitive$KtRecipe
- Find SLF4J log calls with sensitive field names in the format string
- Log messages mentioning
password,secret,token,api_key,credit_card,ssn, etc. usually concatenate or substitute the secret itself. Logs propagate to disk, log aggregators, and alerting pipelines — none of which are designed as a secret store.
- org.openrewrite.kotlin.security.FindSqlExecuteQueryWithConcat$KtRecipe
- Find
Statement.executeQuery("... " + x)calls - String concatenation into
executeQueryis the canonical SQL-injection vector. Switch toPreparedStatementwith?placeholders so the driver escapes the parameter for you.
- Find
- org.openrewrite.kotlin.security.FindSqlExecuteWithConcat$KtRecipe
- Find
Statement.execute("... " + x)/executeUpdatecalls - Same injection class as
executeQuery— string concatenation into aStatementis unsafe for any execute variant. UsePreparedStatement.setX(index, value).
- Find
- org.openrewrite.kotlin.security.FindStringToByteArrayDefaultCharset$KtRecipe
- Find
String.toByteArray()calls without an explicit charset String.toByteArray()uses the platform default charset, which differs across operating systems and produces non-portable bytes when hashed or signed. PassCharsets.UTF_8(or another explicit charset) so the resulting bytes are stable.
- Find
- org.openrewrite.kotlin.security.FindStripeKeyLiteral$KtRecipe
- Find Stripe API key literals (
sk_live_…/sk_test_…) - Stripe secret keys grant full account access;
sk_live_…lets the holder create charges on your account. Rotate at dashboard.stripe.com/apikeys.
- Find Stripe API key literals (
- org.openrewrite.kotlin.security.FindTrustAllX509TrustManager$KtRecipe
- Find
X509TrustManagerimplementations with emptycheckServerTrusted - An
X509TrustManagerwhosecheckServerTrusted/checkClientTrustedbody is empty accepts any certificate chain, defeating TLS authentication. Remove the override and use the JDK default trust manager, or pin against an explicit CA.
- Find
- org.openrewrite.kotlin.security.FindUnsafeDeserialization$KtRecipe
- Find unsafe Java deserialization
- Java native deserialization is the source of the Apache Commons gadget-chain RCE family. Each
ObjectInputStreamallocation needs an explicitObjectInputFilter(Java 9+) or a replacement encoding.
- org.openrewrite.kotlin.security.FindWeakCipherBlowfish$KtRecipe
- Find
Cipher.getInstance("Blowfish")calls - Blowfish has a 64-bit block size and is vulnerable to Sweet32 birthday collisions on long-lived sessions. Its successor Twofish is also legacy — prefer AES-GCM.
- Find
- org.openrewrite.kotlin.security.FindWeakCipherDes$KtRecipe
- Find
Cipher.getInstance("DES...")calls - DES has a 56-bit effective key length and is brute-forceable in hours on commodity GPUs. Replace with AES-256/GCM for new code; for legacy data, decrypt-and-re-encrypt under AES.
- Find
- org.openrewrite.kotlin.security.FindWeakCipherRc2$KtRecipe
- Find
Cipher.getInstance("RC2")calls - RC2 has known cryptanalytic weaknesses and a 40-bit export-grade variant; the JCE accepts both. Migrate to AES-GCM.
- Find
- org.openrewrite.kotlin.security.FindWeakCipherRc4$KtRecipe
- Find
Cipher.getInstance("RC4"/"ARCFOUR")calls - RC4 has been removed from TLS for biased-keystream reasons (IETF RFC 7465). Replace with AES-GCM or ChaCha20-Poly1305.
- Find
- org.openrewrite.kotlin.security.FindWeakCipherTripleDes$KtRecipe
- Find
Cipher.getInstance("DESede"/"TripleDES")calls - Triple-DES (3DES, DESede) is deprecated by NIST as of 2023 due to its 64-bit block size making it vulnerable to Sweet32-style birthday attacks. Migrate to AES-GCM.
- Find
- org.openrewrite.kotlin.security.FindWeakCryptography$KtRecipe
- Find weak cryptographic primitives
- Broken hash algorithms (MD2/MD5/SHA-1), broken or undersized ciphers (DES / 3DES / RC2 / RC4 / Blowfish / bare AES / AES-ECB), weak key material (DES key generation, DES
SecretKeySpec, sub-2048-bit RSA), predictable IVs, and non-cryptographic random sources used in security-adjacent code.
- org.openrewrite.kotlin.security.FindWeakHashMd2$KtRecipe
- Find
MessageDigest.getInstance("MD2")calls - MD2 is older and weaker than MD5 — preimage and collision attacks are well-known. It exists in the JDK only for legacy interop and should never appear in new code.
- Find
- org.openrewrite.kotlin.security.FindWeakHashMd5$KtRecipe
- Find
MessageDigest.getInstance("MD5")calls - MD5 is cryptographically broken; collisions are computable in seconds on commodity hardware. Use SHA-256 for non-secret hashing or HMAC-SHA-256 / Argon2id for authenticated or derived secrets.
- Find
- org.openrewrite.kotlin.security.FindWeakHashSha1$KtRecipe
- Find
MessageDigest.getInstance("SHA-1")calls - SHA-1 collisions are computationally feasible (SHAttered, 2017). NIST has deprecated SHA-1 for signature use; migrate to SHA-256 or a SHA-3 variant.
- Find
- org.openrewrite.kotlin.security.FindWeakSslProtocol$KtRecipe
- Find
SSLContext.getInstance("SSL"/"TLSv1"/"TLSv1.1")calls SSL,TLSv1, andTLSv1.1are RFC-deprecated and disabled by browsers — POODLE / BEAST / Lucky13 attacks all apply. UseTLSv1.2orTLSv1.3(or"TLS"to let the JDK pick the strongest mutually-supported version).
- Find
- org.openrewrite.kotlin.security.FindWebViewAddJsInterface$KtRecipe
- Find
WebView.addJavascriptInterface(...)calls addJavascriptInterfaceexposes a Kotlin/Java object to in-WebView JavaScript — pre-API-17 devices could call any reflectively-reachable method (CVE-2012-6636). Even on modern devices, every annotated method becomes attack surface for whatever content the WebView loads.
- Find
- org.openrewrite.kotlin.security.FindWebViewJavaScriptEnabled$KtRecipe
- Find
WebView.settings.javaScriptEnabled = true/setJavaScriptEnabled(true) - Enabling JavaScript inside a
WebViewis the precondition for the entire WebView attack surface —addJavascriptInterfaceexposure, XSS in cached HTML, prompts-as-UI-spoofs. Disable it unless you control the loaded content.
- Find
- org.openrewrite.kotlin.security.FindWebViewLoadUrlHttp$KtRecipe
- Find
WebView.loadUrl("http://...")calls - Loading an
http://URL into a WebView opts out of TLS and lets any on-path attacker rewrite the page (script injection, credential theft). Usehttps://, and if you must load HTTP, setsetAllowFileAccess(false)plus a restrictedWebViewClient.
- Find
- org.openrewrite.kotlin.security.FindWebViewSavePassword$KtRecipe
- Find
WebView.settings.setSavePassword(true)calls setSavePassword(true)stores form passwords in plaintext inside the WebView database. Deprecated in API 18 for this reason. Don't enable it.
- Find
- org.openrewrite.kotlin.security.FindWebViewSetAllowFileAccessTrue$KtRecipe
- Find
WebView.settings.setAllowFileAccessFromFileURLs(true)calls setAllowFileAccessFromFileURLs(true)(andsetAllowUniversalAccessFromFileURLs(true)) let HTML loaded fromfile://URLs read arbitrary local files — a popular Android XSS gadget. Default tofalse.
- Find
- org.openrewrite.kotlin.security.FindWebViewSetMixedContentAlwaysAllow$KtRecipe
- Find
WebView.settings.mixedContentMode = MIXED_CONTENT_ALWAYS_ALLOWsettings MIXED_CONTENT_ALWAYS_ALLOWlets an HTTPS page pull HTTP subresources — the moment a single subresource loads over HTTP, the page's integrity is compromised. UseMIXED_CONTENT_NEVER_ALLOW.
- Find
- org.openrewrite.kotlin.security.Security$KtRecipe
- Find security smells in Kotlin code
- OWASP-aligned search-only recipes covering weak cryptography, insecure TLS configuration, injection vectors, Java deserialization, JWT misuse, sensitive data in logs, Android-specific security smells, and hard-coded secret literals. Each match is a
SearchResultfor review — nothing is rewritten automatically because security findings nearly always need a human to pick the migration target.
- org.openrewrite.kotlin.spring.FindAsyncOnFinal$KtRecipe
- Find
@Asyncmethods on classes that aren'topen - Spring's
@Asyncproxy is the same CGLIB subclass mechanism@Transactionaluses; it can only intercept methods on a non-final, non-private surface. Mark the surrounding class and methodopen, or apply thekotlin-springcompiler plugin to do it for you.
- Find
- org.openrewrite.kotlin.spring.FindAsyncOnPrivate$KtRecipe
- Find
@Asynconprivatefunctions - Like
@Transactional,@Asyncis implemented by a Spring proxy that intercepts calls through the bean's public interface.privatemethods bypass the proxy and run synchronously on the caller's thread — the annotation has no effect.
- Find
- org.openrewrite.kotlin.spring.FindAutowiredLogger$KtRecipe
- Find
@Autowired lateinit varLogger fields - Injecting a
Loggerthrough Spring is unnecessarily exotic — the Logger isn't a Spring bean in any standard configuration, andLoggerFactory.getLogger(MyClass::class.java)produces an identical instance with zero container plumbing. Move the declaration into a companion object:companion object \{ private val log = LoggerFactory.getLogger(MyClass::class.java) \}.
- Find
- org.openrewrite.kotlin.spring.FindAutowiredOnConstructor$KtRecipe
- Find
@Autowiredon a single constructor - Spring 4.3+ automatically autowires the single primary constructor — the
@Autowiredannotation is redundant and adds noise. Drop it from the constructor declaration.
- Find
- org.openrewrite.kotlin.spring.FindAutowiredOnField$KtRecipe
- Find
@Autowired lateinit varfield injection - Field injection through
@Autowired lateinit varhides the dependency from the constructor, makes the class harder to test (no compile-time guarantee the field is wired), and breaks immutability. Move the dependency into the primary constructor.
- Find
- org.openrewrite.kotlin.spring.FindAutowiredOnLateinitVar$KtRecipe
- Find
@Autowired lateinit varproperties (ctor-injection candidate) @Autowired lateinit var x: Xis the most common Kotlin-Spring field-injection shape. Compared with@Autowired constructor(val x: X), it hides the dependency from the constructor signature and prevents the compiler from enforcing initialization order. Constructor inject instead.
- Find
- org.openrewrite.kotlin.spring.FindAutowiredOnVar$KtRecipe
- Find
@Autowired varproperties (notlateinit) - A
@Autowired var x: Xproperty is mutable after wiring — the Spring container sets it once, but any subsequent caller can replace the dependency at runtime. Move the dependency into a primary constructor parameter (val) so it'sfinalend-to-end.
- Find
- org.openrewrite.kotlin.spring.FindBeanLambdaCandidate$KtRecipe
- Find
@Bean fun foo(): X = X()candidates for thebeans \{ \}DSL - Single-expression
@Beandeclarations that just construct a bean are one of the cases the Spring Kotlinbeans \{ \}DSL was designed for — the DSL form drops the annotation overhead and reads as plain Kotlin. Each match here is a candidate for the migration.
- Find
- org.openrewrite.kotlin.spring.FindCacheableOnPrivate$KtRecipe
- Find
@Cacheableonprivatefunctions @Cacheableworks through the same proxy mechanism as@Transactionaland@Async— invisible onprivate(andinternal) methods. Either widen visibility or move the caching boundary up the call chain.
- Find
- org.openrewrite.kotlin.spring.FindCircularDependencyHint$KtRecipe
- Find
@Lazyannotations on@Autowiredproperties @Lazy @Autowiredis Spring's escape hatch for circular bean references. It works, but each one is a hint that the dependency graph has a cycle that should be untangled by extracting a third bean or reorganising responsibilities. Flag every occurrence for design review.
- Find
- org.openrewrite.kotlin.spring.FindConfigurationPropertiesWithoutData$KtRecipe
- Find
@ConfigurationPropertiesclasses that aren'tdata class - A
@ConfigurationPropertiescarrier should be adata classwithvalproperties: immutable,equals/hashCode/toStringfor free, and the constructor binder works without@ConstructorBinding. Plainclasscarriers either require mutablelateinit varor lose the value-class benefits.
- Find
- org.openrewrite.kotlin.spring.FindControllerInsteadOfRestController$KtRecipe
- Find
@Controllerclasses whose methods all return data (consider@RestController) - A
@Controllerclass needs@ResponseBodyon each handler that returns data;@RestControllerapplies@ResponseBodyto every method in one annotation. Where every method on a@Controlleris data-returning,@RestControllerreads more cleanly. Flag for review — view-rendering controllers are correct as-is.
- Find
- org.openrewrite.kotlin.spring.FindControllerReturningResponseEntity$KtRecipe
- Find
@RestControllermethods returningResponseEntity<T> - When the only thing a controller does with
ResponseEntityisResponseEntity.ok(body), returningTdirectly produces the same 200 OK response with less boilerplate. ReserveResponseEntityfor endpoints that actually vary status/headers per call.
- Find
- org.openrewrite.kotlin.spring.FindCoroutineControllerCandidate$KtRecipe
- Find
@GetMapping/@PostMapping/... methods returningMono<T> - A controller method returning
Mono<T>is a candidate forsuspend fun foo(): T. The suspending form reads as plain Kotlin, integrates with structured concurrency, and Spring WebFlux handles the bridge automatically.
- Find
- org.openrewrite.kotlin.spring.FindCrudRepositoryGenericList$KtRecipe
- Find repository interfaces extending
CrudRepositoryinstead ofJpaRepository CrudRepository<T, ID>returnsIterable<T>fromfindAll()— fine for streaming, awkward for everything else.JpaRepository<T, ID>returnsList<T>and adds pagination, sorting, and batch operations. Most JPA repositories should extendJpaRepository.
- Find repository interfaces extending
- org.openrewrite.kotlin.spring.FindDataAccessSmells$KtRecipe
- Find Spring Data / repository access smells
- Repository call patterns that hide a problem:
repo.findById(id).get()(usefindByIdOrNullorgetReferenceById) andfindByIdOrNull(id!!)(contradictory nullability).
- org.openrewrite.kotlin.spring.FindEnableWebMvcOnBootApp$KtRecipe
- Find
@EnableWebMvcon a Spring Boot application @EnableWebMvcopts out of Spring Boot's Web MVC auto-configuration. Most applications shouldn't apply it — they want Boot's defaults plus aWebMvcConfigurerfor tweaks. Flag the annotation so reviewers can confirm it's intentional.
- Find
- org.openrewrite.kotlin.spring.FindEnvironmentGetProperty$KtRecipe
- Find
Environment.getProperty(...)calls environment.getProperty("foo")is the lowest-level Spring config API — string-typed, untyped default, no IDE completion. Promote frequently-used properties to a@ConfigurationProperties data classso the property name and type are encoded once.
- Find
- org.openrewrite.kotlin.spring.FindEventListenerWithReturn$KtRecipe
- Find
@EventListenermethods with non-Unitreturn types - Spring's
@EventListenerrepublishes any non-Unitreturn value as a new event. That's a useful feature when intentional, but easy to trip over — a function written toreturn resultfor the caller's convenience ends up firing the event loop. Make the intent explicit (return Unitif the caller value isn't supposed to publish, or document that it should).
- Find
- org.openrewrite.kotlin.spring.FindFieldInjection$KtRecipe
- Find
@Inject lateinit varfield injection - The JSR-330
@Injectannotation has the same drawbacks as@Autowiredfor field injection: hidden dependencies, harder testing, mutable state. Migrate to constructor injection.
- Find
- org.openrewrite.kotlin.spring.FindFieldInjectionOverConstructor$KtRecipe
- Find
@Autowired valfield declarations (not in ctor) - A
@Autowired private val x: Xwritten as a class-body declaration (not a primary-constructor parameter) is functionally close to constructor injection but hides the dependency from the public constructor signature. Pull the parameter up into the primary constructor so callers and tests see the contract.
- Find
- org.openrewrite.kotlin.spring.FindFindByIdOrNullWithNonNullableId$KtRecipe
- Find
findByIdOrNull(id!!)calls - Calling
findByIdOrNull(id!!)says two contradictory things at once: the caller insists the id is non-null (!!) but is willing to accept a null result if no row matches. If the id is genuinely non-null, the!!is dead weight; if it might be null, the call should branch before the lookup.
- Find
- org.openrewrite.kotlin.spring.FindFluxBlockFirstInNonTest$KtRecipe
- Find
Flux.blockFirst()calls outside@Testmethods Flux.blockFirst()blocks the calling thread waiting for the first element of a Flux — fine in tests, a thread-pool hazard in production. Bridge withawaitFirst()/awaitFirstOrNull()fromkotlinx-coroutines-reactorinside asuspend fun.
- Find
- org.openrewrite.kotlin.spring.FindFluxBlockLastInNonTest$KtRecipe
- Find
Flux.blockLast()calls outside@Testmethods Flux.blockLast()drains the entire Flux on the calling thread to return the final element. In production code, that's almost never the intent — surface the elements throughasFlow().collect \{ \}or call from a coroutine withawaitLast().
- Find
- org.openrewrite.kotlin.spring.FindFluxFlatMapReturningFluxJust$KtRecipe
- Find
Flux.flatMap \{ x -> Mono.just(f(x)) \}patterns - A
Flux.flatMapwhose lambda only wraps a value back intoMono.just(orFlux.just) is doing the work ofmap. Drop the publisher boxing and the runtime cost of subscribing to a one-shot inner publisher per element.
- Find
- org.openrewrite.kotlin.spring.FindFluxFromIterableWithList$KtRecipe
- Find
Flux.fromIterable(listOf(...))patterns - When the source list is a constant
listOf(a, b, c)known at compile time,Flux.just(a, b, c)is the same shape with one fewer allocation (no intermediateList).fromIterableonly earns its keep when the iterable is already in hand.
- Find
- org.openrewrite.kotlin.spring.FindFluxSubscribeWithoutOnError$KtRecipe
- Find
Flux.subscribe \{ ... \}without an error consumer - Single-argument
subscribe(consumer)swallows upstream errors into Reactor's defaultonErrorDroppedhook — silent in most environments and frustrating to debug. The two-argument formsubscribe(consumer, errorConsumer)(or four-argument withonComplete/Context) forces an explicit choice.
- Find
- org.openrewrite.kotlin.spring.FindHttpServletRequestParameter$KtRecipe
- Find
HttpServletRequestparameters in controllers - Reaching for
HttpServletRequestinside a controller handler bypasses Spring's argument-resolver chain (@PathVariable,@RequestParam,@RequestHeader,@RequestBody, etc.). Each of those binds the value with type conversion and validation; using the raw servlet request loses that and couples the handler to the servlet API.
- Find
- org.openrewrite.kotlin.spring.FindJpaEntityWithVarsOnly$KtRecipe
- Find
@Entityclasses withvarproperties only - JPA entities need mutable properties for the persistence provider to hydrate them, but a
class X(var a: A, var b: B)form mixes that JPA requirement with full external mutability. Promote todata class(still mutable for JPA via thekotlin-jpacompiler plugin's synthesized no-arg ctor) to getequals/hashCode/toStringandcopy.
- Find
- org.openrewrite.kotlin.spring.FindJpaRepositoryFindByIdWithoutOptional$KtRecipe
- Find
repo.findById(id).get()chains Optional.get()on a JPA repository result throwsNoSuchElementExceptionwhen the row is missing — the same outcome asgetReferenceById(id)but without the explicit Optional dance. In Kotlin,findByIdOrNull(id)plus a null check (or?: throw) is even more direct.
- Find
- org.openrewrite.kotlin.spring.FindLateinitInjectedField$KtRecipe
- Find any
lateinit varinjected field (@Autowired/@Inject/@Value) - Any property wired via
lateinit var+ injection annotation pattern is a candidate for constructor injection. This recipe catches the union of@Autowired,@Inject, and@Valuelateinit-var declarations.
- Find any
- org.openrewrite.kotlin.spring.FindMainMethodWithSpringApplicationRun$KtRecipe
- Find top-level
mainfunctions wrappingSpringApplication.run - A top-level
main(args: Array<String>) \{ SpringApplication.run(MyApp::class.java, *args) \}collapses to one line with the reifiedrunApplication<MyApp>(*args)builder. Flag themainentry point for migration.
- Find top-level
- org.openrewrite.kotlin.spring.FindMissingResponseStatus$KtRecipe
- Find
@PostMappingmethods missing@ResponseStatus(HttpStatus.CREATED) - By convention, a successful POST that creates a resource should return
201 Created, not the default200 OK. Add@ResponseStatus(HttpStatus.CREATED)to the controller method so the status is consistent with the action.
- Find
- org.openrewrite.kotlin.spring.FindMockBeanOnField$KtRecipe
- Find
@MockBeanonlateinit varfields @MockBean lateinit var xmutates the bean at field-injection time, which works but ties the test to Spring's container even when the unit under test could be exercised with constructor injection of a plainmockk<X>(). Flag for review — preferred where the surrounding test can be a plain unit test.
- Find
- org.openrewrite.kotlin.spring.FindMockMvcStandalone$KtRecipe
- Find
MockMvcBuilders.standaloneSetup(...)calls standaloneSetupwires a single controller into a minimal MockMvc — fast, but misses any application-level configuration (interceptors, exception handlers, argument resolvers).@AutoConfigureMockMvcproduces a MockMvc that mirrors the running application; flag standalone setups as candidates for replacement.
- Find
- org.openrewrite.kotlin.spring.FindMonoAwaitSingle$KtRecipe
- Find
mono.awaitSingle()calls inside Flux/Flow collectors awaitSingle()is the right bridge from a single-valueMonointo a coroutine. Inside aFlux.collect/Flow.collectover many elements, however, the pattern often signals that the surrounding code is mixing two stream models — flag for review.
- Find
- org.openrewrite.kotlin.spring.FindMonoBlockInNonTest$KtRecipe
- Find
Mono.block()calls outside@Testmethods Mono.block()parks the calling thread until the upstream Mono completes, which is fine in a test but a footgun in production code. On Netty's small event-loop pool, oneblock()can stall every concurrent request. Bridge withawaitSingle()fromkotlinx-coroutines-reactorinside asuspend funinstead.
- Find
- org.openrewrite.kotlin.spring.FindMonoErrorInsteadOfThrow$KtRecipe
- Find
throw ...statements inside Mono/Flux operator lambdas - Reactor expects errors to be signaled through the publisher (
Mono.error(...)) rather than thrown. A rawthrowinsideflatMap/mapworks through Reactor'sExceptions.propagatefallback, but loses stack-walking guarantees and trips up the assembly-time error handling.
- Find
- org.openrewrite.kotlin.spring.FindMonoFlatMapBlock$KtRecipe
- Find
Mono.block()calls in non-test code - Outside of
@Testmethods,Mono.block()is almost always a bug: it bridges reactive code into a blocking call, defeating the purpose of WebFlux. In Kotlin, the bridge should go the other direction —awaitSingle()fromkotlinx-coroutines-reactor.
- Find
- org.openrewrite.kotlin.spring.FindMonoFlatMapReturningMonoJust$KtRecipe
- Find
Mono.flatMap \{ x -> Mono.just(f(x)) \}patterns - When a
flatMaplambda's only job is to wrap a synchronous result inMono.just, the whole step collapses tomap \{ x -> f(x) \}.mapis cheaper (no inner Mono allocation) and signals that the transform is synchronous.
- Find
- org.openrewrite.kotlin.spring.FindMonoFluxSmells$KtRecipe
- Find Mono/Flux ergonomic smells
- Reactive-pipeline shapes that read more naturally a different way:
flatMap \{ Mono.just(...) \}→map,block()/blockFirst()/blockLast()outside@Testmethods, single-argumentFlux.subscribe(missing error consumer), rawthrowinside operator lambdas (useMono.error),Mono.zip(verify independent operands), andFlux.fromIterable(listOf(...))(useFlux.just).
- org.openrewrite.kotlin.spring.FindMonoZipWithoutAllOperands$KtRecipe
- Find
Mono.zip(...)calls Mono.zipwaits for all of its sources to emit, then combines them. Useful when two requests are genuinely independent, but easy to misuse — flag for review to confirm the operands are independent and that the desired error semantics matchzip's eager-cancellation behaviour.
- Find
- org.openrewrite.kotlin.spring.FindNoArgConstructorMissing$KtRecipe
- Find
@Entity data classdeclarations (verifykotlin-jpaplugin) - A
@Entity data class X(val a: A)only works with JPA when thekotlin-jpacompiler plugin synthesizes a no-arg constructor. Without the plugin, JPA'sfindByIdfails at runtime withInstantiationException: No default constructor. Flag entity data classes so reviewers can confirm the plugin is applied.
- Find
- org.openrewrite.kotlin.spring.FindOpenClassForSpring$KtRecipe
- Find Spring stereotype classes not declared
open - Kotlin classes are
finalby default, but Spring needs a non-final target to create CGLIB proxies (which is how@Transactional,@Async, scope-proxied beans, etc. work). Thekotlin-springcompiler plugin opens them automatically, but if it isn't applied — or the class is in a module that doesn't apply it — Spring's proxy machinery fails at runtime. Flag stereotype classes that aren't explicitlyopenfor review.
- Find Spring stereotype classes not declared
- org.openrewrite.kotlin.spring.FindPathVariableWithoutName$KtRecipe
- Find
@PathVariableparameters without an explicit name @PathVariable name: Stringworks only as long as the JVM preserves parameter names, which requires the-parametersjavac flag and-java-parameterskotlinc flag. If either is missing, Spring resolves the path variable by ordinal — a footgun on rename. Set the name explicitly:@PathVariable("id") id: String.
- Find
- org.openrewrite.kotlin.spring.FindPropertySourceOnNonConfiguration$KtRecipe
- Find
@PropertySourceon classes that lack@Configuration @PropertySourceonly takes effect on a Spring@Configurationclass — when applied to a stereotype like@Componentor@Service, the property file is silently ignored. Move the annotation to a@Configurationclass or change the surrounding class accordingly.
- Find
- org.openrewrite.kotlin.spring.FindQualifierOnLateinitField$KtRecipe
- Find
@Qualifieronlateinit varfields @Qualifierannotating alateinit vardoubles down on field injection. Move both the qualifier and the dependency to a constructor parameter so callers (and tests) can see what's required.
- Find
- org.openrewrite.kotlin.spring.FindReactiveCoroutineInterop$KtRecipe
- Find reactive / coroutine interop hazards
- Bridges between Reactor and coroutines that usually point at a missed opportunity:
WebClient.bodyToMono(...).block()(useawaitBody<T>()),Mono.deferContextual \{ \}inside asuspend fun(context propagation goes throughcoroutineContext), andawaitSingle()patterns worth a review.
- org.openrewrite.kotlin.spring.FindReactiveTestWithoutStepVerifier$KtRecipe
- Find
WebTestClienttest classes that don't useStepVerifier WebTestClientmakes the call, but assertions on aMono<T>body typically needStepVerifier.create(...).expectNext(...).verifyComplete()to fully drain the publisher and assert ordering. Without it, a reactive bug can hide behind the test's premature completion.
- Find
- org.openrewrite.kotlin.spring.FindReactorContextInsideSuspendFun$KtRecipe
- Find
Mono.deferContextual \{ ... \}insidesuspend fun - Reactor's
deferContextualreads context from a reactive Subscriber. Inside asuspend fun, that subscriber isn't the active continuation — context propagation should go throughkotlin.coroutines.coroutineContextorkotlinx.coroutines.reactor.ReactorContextinstead. Flag for review.
- Find
- org.openrewrite.kotlin.spring.FindRepositoryReturnsOptional$KtRecipe
- Find Spring Data repository methods returning
Optional<T> - On the JVM,
Optional<T>is the only way to model 'maybe absent' in Java APIs. In Kotlin,T?is the language-native equivalent — Spring Data auto-detects nullable return types since 2.0. ConvertOptional<T>returns toT?.
- Find Spring Data repository methods returning
- org.openrewrite.kotlin.spring.FindRequestBodyOnPrimitive$KtRecipe
- Find
@RequestBodyon primitive parameters @RequestBody Intor@RequestBody Stringparses the entire HTTP body as a single value — a fragile contract that breaks the moment the API evolves to include a second field. Wrap the parameter in a DTO so future additions don't require client-side changes.
- Find
- org.openrewrite.kotlin.spring.FindRequestMappingMethodGetMapping$KtRecipe
- Find
@RequestMapping(method = [RequestMethod.GET])candidates for@GetMapping @RequestMappingwith an explicitmethod = [...]is the long-form spelling of@GetMapping/@PostMapping/etc. The shortcut annotations were introduced specifically to replace this pattern.
- Find
- org.openrewrite.kotlin.spring.FindRequestMappingWithoutVerb$KtRecipe
- Find
@RequestMapping(...)without an HTTP method @RequestMapping("/x")matches every HTTP verb, which is rarely the intent. The verb-specific shortcuts (@GetMapping/@PostMapping/...) are clearer at a glance and prevent accidental dual-method routes.
- Find
- org.openrewrite.kotlin.spring.FindRequiredOnSetter$KtRecipe
- Find
@Requiredannotations @Requiredwas deprecated in Spring 5.1 and removed in 6.0 — its only purpose was to mandate setter injection. The modern equivalent is mandatory constructor injection, which is enforced by Kotlin's non-null types.
- Find
- org.openrewrite.kotlin.spring.FindResponseEntityWithoutStatus$KtRecipe
- Find
ResponseEntity(body, HttpStatus.OK)constructor calls - The two-argument
ResponseEntityconstructor withHttpStatus.OKis exactly whatResponseEntity.ok(body)produces — using the factory makes the 200-OK intent explicit and removes the dependency onHttpStatus. Save the constructor form for genuinely status-varying responses.
- Find
- org.openrewrite.kotlin.spring.FindRestTemplateUsage$KtRecipe
- Find
RestTemplateallocations RestTemplatewas placed in maintenance mode in Spring 5 — Spring's docs explicitly steer new code toWebClient(reactive) orRestClient(Spring 6.1+, synchronous). EachRestTemplate()allocation is a candidate for migration.
- Find
- org.openrewrite.kotlin.spring.FindSpringAnnotationSmells$KtRecipe
- Find Spring annotation-shape smells
- Stereotype/injection annotations applied to the wrong Kotlin shape:
@Componentondata class,@Serviceonobject,@Beanwithout@Scope,@Autowiredonvar/lateinit var/ class-bodyval, and@Lazy @Autowired(a hint of circular dependencies).
- org.openrewrite.kotlin.spring.FindSpringApplicationRunJava$KtRecipe
- Find
SpringApplication.run(MyApp::class.java, ...)calls - Kotlin Spring Boot ships a reified helper
runApplication<MyApp>(*args)that drops the::class.javatoken and the explicitSpringApplicationreference. The Java-style form here works but reads as a Java port — flag for migration.
- Find
- org.openrewrite.kotlin.spring.FindSpringBeanWithoutScope$KtRecipe
- Find
@Beanmethods without@Scope @Beanwithout@Scopeproduces a singleton, which is almost always correct — but for stateful beans (@RequestScope,@SessionScope, prototype-scoped builders) the default is wrong. Flag for review when the bean's nature suggests a scope decision is in order.
- Find
- org.openrewrite.kotlin.spring.FindSpringBootstrappingSmells$KtRecipe
- Find Spring Boot bootstrapping smells
- Bootstrap code that hasn't been Kotlinized: Java-style
SpringApplication.run(MyApp::class.java, ...)calls andmainwrappers that could collapse to a one-linerunApplication<MyApp>(*args).
- org.openrewrite.kotlin.spring.FindSpringComponentOnDataClass$KtRecipe
- Find
@Component/@Service/@Repositoryondata class - Spring stereotype classes have proxy-friendly identity (Spring wires them as singletons keyed by class).
data classoverridesequals/hashCodeover the constructor properties — two beans with the same fields compare equal, which is rarely desirable for a service-shaped component. Promote to a regular class.
- Find
- org.openrewrite.kotlin.spring.FindSpringConfigurationSmells$KtRecipe
- Find Spring configuration smells
- Configuration scattered across
@Valuelateinit-var reads, untypedEnvironment.getProperty(...)calls,@ConfigurationPropertiescarriers that aren'tdata class,@Bean fun foo(): X = X()candidates for thebeans \{ \}Kotlin DSL, and misplaced@PropertySourceon non-@Configurationclasses.
- org.openrewrite.kotlin.spring.FindSpringCoroutineCandidates$KtRecipe
- Find Spring coroutine-migration candidates
- Controllers and clients that work today with
Mono/Fluxchaining but read more naturally as suspending Kotlin:Mono<T>returns from mapping methods (could besuspend fun foo(): T) andbodyToMono(X::class.java)patterns (awaitBody<X>()).
- org.openrewrite.kotlin.spring.FindSpringDataSmells$KtRecipe
- Find Spring Data smells
- Repository methods returning
Optional<T>instead ofT?,@Entityclasses that should bedata class,@Entity data classdeclarations whose JPA-friendliness depends on thekotlin-jpaplugin,CrudRepositorycandidates forJpaRepository, and@Transactionalannotations onprivatemethods orfinalclasses (Spring's proxy can't intercept them).
- org.openrewrite.kotlin.spring.FindSpringDependencyInjectionSmells$KtRecipe
- Find Spring dependency-injection smells
- Field injection (
@Autowired/@Inject/@Qualifieronlateinit var), redundant@Autowiredon single ctors, the deprecated@Requiredsetter annotation, and Spring stereotype classes that aren'topen(Kotlin'sfinaldefault breaks CGLIB proxies unlesskotlin-springis applied).
- org.openrewrite.kotlin.spring.FindSpringLegacyApiSmells$KtRecipe
- Find Spring legacy / deprecated API smells
RestTemplate(in maintenance mode — useWebClientorRestClient),@EnableWebMvcon a Boot application (disables auto-config),HttpServletRequestparameters in controllers (use binding annotations),@Controllerwhose handlers all return data (consider@RestController), and@AutowiredLogger fields (use companionLoggerFactory).
- org.openrewrite.kotlin.spring.FindSpringProxiedAnnotationSmells$KtRecipe
- Find Spring proxied-annotation smells
- Proxy-backed annotations beyond
@Transactionalthat hit the same Kotlin-default-final trap:@Asyncand@Cacheableonprivatemethods or final classes, plus@EventListenermethods that accidentally republish their return values as new events.
- org.openrewrite.kotlin.spring.FindSpringServiceOnObject$KtRecipe
- Find
@Service object Foodeclarations - A Spring
@Service/@Componentdeclared asobjectis a singleton at the language level — Spring will still register it as a bean, but autowiring into the object's properties is fragile (objectinitialization runs at class-load time, before the Spring context exists). Use a regular class so the container controls the lifecycle.
- Find
- org.openrewrite.kotlin.spring.FindSpringTestingSmells$KtRecipe
- Find Spring testing smells
@MockBean/@SpyBeanlateinit-var fields (often a plain unit test would do),MockMvcBuilders.standaloneSetup(consider@AutoConfigureMockMvc), andWebTestClienttests that don't drain the publisher withStepVerifier.
- org.openrewrite.kotlin.spring.FindSpringWebSmells$KtRecipe
- Find Spring Web / WebFlux smells
- Controller endpoints worth a closer look:
ResponseEntity<T>returns that always emit 200, verb-less@RequestMapping,@RequestMapping(method = [...])candidates for shortcut annotations,@PathVariableparameters without explicit names, primitive@RequestBodyshapes, POST endpoints missing@ResponseStatus(CREATED), and reactiveblock()calls that stall the event loop.
- org.openrewrite.kotlin.spring.FindSpyBeanOnField$KtRecipe
- Find
@SpyBeanonlateinit varfields @SpyBeancarries the same coupling to the Spring container as@MockBean, plus the extra surprise of partially mocking real implementation code. Where possible, exercise the unit under test directly withmockk<X>(relaxed = true)and verify against a spy of a single dependency.
- Find
- org.openrewrite.kotlin.spring.FindTransactionalOnFinal$KtRecipe
- Find
@Transactionalmethods on classes that aren'topen - Spring proxies a
@Transactionalbean by subclassing it (CGLIB); for the subclass to override the method, both the class and the method must be non-final. Kotlin's defaultfinaldefeats this — either apply thekotlin-springcompiler plugin or mark the class and methodopen.
- Find
- org.openrewrite.kotlin.spring.FindTransactionalOnPrivate$KtRecipe
- Find
@Transactionalonprivatefunctions - Spring's transaction proxy intercepts calls through the bean's public interface —
private(andinternal) methods are invoked directly on the target instance, bypassing the proxy entirely. The annotation is silently no-op. Make the methodpublicor move the transaction boundary up the call chain.
- Find
- org.openrewrite.kotlin.spring.FindValueAnnotationOnLateinit$KtRecipe
- Find
@Valueonlateinit varproperties - Individual
@Value("\$\{x\}")reads scatter configuration access across the codebase. Grouping related properties under a single@ConfigurationPropertiesdata class produces typed, validated, IDE-discoverable config — and works seamlessly withdata class+ non-null types in Kotlin.
- Find
- org.openrewrite.kotlin.spring.FindWebClientBlockOnResponse$KtRecipe
- Find
webClient...bodyToMono(X::class).block()chains - Chaining
block()onto aWebClient.bodyToMono(...)call defeats the reactive request entirely — the calling thread blocks for the HTTP round-trip, throwing away every concurrency benefit of WebClient. In asuspend fun,awaitBody<X>()produces the same value without blocking the event loop.
- Find
- org.openrewrite.kotlin.spring.FindWebClientCreateWithoutBuilder$KtRecipe
- Find
WebClient.create()/WebClient.create(url)calls - The static
WebClient.create(...)shortcut returns a client with default codecs, nobaseUrlchain, no filters, no exchange-strategy tuning. Production WebClients almost always need at least one of those — promote toWebClient.builder().baseUrl(...).build()so the configuration shape is visible at the call site.
- Find
- org.openrewrite.kotlin.spring.FindWebClientRestTemplateSmells$KtRecipe
- Find WebClient / RestTemplate / ResponseEntity smells
- HTTP-client and response-shape patterns:
RestTemplateallocations (maintenance mode — useWebClient/RestClient),WebClient.create()without the builder (useWebClient.builder().baseUrl(...)), andResponseEntity(body, HttpStatus.OK)(use theok(body)factory).
- org.openrewrite.kotlin.spring.FindWebClientWithoutAwait$KtRecipe
- Find
WebClient.bodyToMono(X::class.java)calls - In suspending controllers and services,
bodyToMono(X::class.java).awaitSingle()is more naturally spelled asawaitBody<X>()fromkotlinx-coroutines-reactor. The reified form removes the::class.javatoken and the.awaitSingle()chain.
- Find
- org.openrewrite.kotlin.spring.FindWebFluxBlocking$KtRecipe
- Find
Mono.block/Flux.blockFirst/Flux.blockLastcalls - Calling
block()on a reactive pipeline parks the calling thread until the upstream completes, which is exactly what the reactive runtime is built to avoid. On Netty's small event-loop pool, a singleblock()can stall every concurrent request the server is processing.
- Find
- org.openrewrite.kotlin.spring.Spring$KtRecipe
- Modernize Spring Boot Kotlin code
- Find Kotlin-idiomatic violations in Spring Boot applications: Java-style
SpringApplication.run,@Autowired/@Injectfield injection, missingopenon Spring-proxied classes, blockingMono.block()calls,@RequestMappingcandidates for@GetMapping,Mono<T>controllers that could be suspending,@ConfigurationPropertiesdata class candidates,@Entitydata class plugin reminders,@Transactional/@Async/@Cacheableon private/final methods, deprecatedRestTemplateallocations, Mono/Flux ergonomic shapes, reactive-coroutine interop hazards, Spring annotation shapes, repository access patterns, and WebClient/ResponseEntity shapes.
- org.openrewrite.kotlin.stdlib.CollectionShorthands$KtRecipe
- Apply Kotlin collection shorthands
- Replaces round-trip conversions (
asSequence().toList(),toList().toSet(),toSet().toList(), …) with the dedicated stdlib operator they're imitating.
- org.openrewrite.kotlin.stdlib.EmptyConstructorShorthands$KtRecipe
- Prefer
emptyList()/emptySet()/emptyMap()over zero-arg builders - When
listOf()/setOf()/mapOf()are called with no entries, replace them with the explicitemptyList()/emptySet()/emptyMap()factories so the empty-by-construction intent is visible at the call site.
- Prefer
- org.openrewrite.kotlin.stdlib.Stdlib$KtRecipe
- Apply Kotlin standard-library idioms
- Opinionated bundle of every Kotlin stdlib-shorthand recipe in this module: round-trip elimination, empty-factory preference, and string
isBlank/take/dropfolds. Complementary toPerformance(which focuses on chain collapses) andBestPractices(which focuses on flagging smells).
- org.openrewrite.kotlin.stdlib.StringShorthands$KtRecipe
- Apply Kotlin string shorthands
- Folds
trim().isEmpty()intoisBlank(), and preferstake/dropoversubstringindexing.
- org.openrewrite.kotlin.stdlib.UseAsSequenceToListIdentity$KtRecipe
- Use
toList()instead ofasSequence().toList() asSequence()wraps the iterable in aSequenceonly to immediately tear it back into aList. The intermediateSequenceallocation does no work.
- Use
- org.openrewrite.kotlin.stdlib.UseDistinctForToHashSetToList$KtRecipe
- Use
distinct()instead oftoHashSet().toList() - Round-tripping through a
HashSetto drop duplicates obscures intent and allocates an intermediate.distinct()says what it does and returns aListdirectly.
- Use
- org.openrewrite.kotlin.stdlib.UseDistinctForToSetToList$KtRecipe
- Use
distinct()instead oftoSet().toList() - Round-tripping through a
Setto drop duplicates obscures intent and allocates an intermediate.distinct()says what it does and returns aListdirectly.
- Use
- org.openrewrite.kotlin.stdlib.UseDistinctForToSetToMutableList$KtRecipe
- Use
distinct().toMutableList()instead oftoSet().toMutableList() - Round-tripping through a
Setto drop duplicates obscures intent.distinct()says what it does; chaintoMutableList()if you actually need a mutable result.
- Use
- org.openrewrite.kotlin.stdlib.UseEmptyListForListOfNoArgs$KtRecipe
- Use
emptyList<T>()instead oflistOf<T>() listOf()with no entries delegates toemptyList(). Call the named factory directly to make the empty-by-construction intent visible.
- Use
- org.openrewrite.kotlin.stdlib.UseEmptyMapForMapOfNoArgs$KtRecipe
- Use
emptyMap<K, V>()instead ofmapOf<K, V>() mapOf()with no entries delegates toemptyMap(). Call the named factory directly to make the empty-by-construction intent visible.
- Use
- org.openrewrite.kotlin.stdlib.UseEmptySetForSetOfNoArgs$KtRecipe
- Use
emptySet<T>()instead ofsetOf<T>() setOf()with no entries delegates toemptySet(). Call the named factory directly to make the empty-by-construction intent visible.
- Use
- org.openrewrite.kotlin.stdlib.UseSetForMutableSetToSet$KtRecipe
- Use
toSet()instead oftoMutableSet().toSet() toMutableSet()already allocates a fresh set — callingtoSet()on it copies again. Go directly totoSet().
- Use
- org.openrewrite.kotlin.stdlib.UseStringDropForSubstring$KtRecipe
- Use
drop(n)instead ofsubstring(n)on aString drop(n)is the named form for skipping the firstncharacters and returns the empty string for over-longninstead of throwing.
- Use
- org.openrewrite.kotlin.stdlib.UseStringIsBlankForTrimIsEmpty$KtRecipe
- Use
isBlank()instead oftrim().isEmpty()on aString trim().isEmpty()allocates a trimmed copy just to check whether the result has no characters.isBlank()answers the same question by scanning in place.
- Use
- org.openrewrite.kotlin.stdlib.UseStringIsNotBlankForTrimIsNotEmpty$KtRecipe
- Use
isNotBlank()instead oftrim().isNotEmpty()on aString trim().isNotEmpty()allocates a trimmed copy to check whether anything is left.isNotBlank()answers the same question by scanning in place.
- Use
- org.openrewrite.kotlin.stdlib.UseStringTakeForSubstringFromZero$KtRecipe
- Use
take(n)instead ofsubstring(0, n)on aString take(n)is the named form onCharSequenceand uniformly returns the empty string whennis larger thanlength.substring(0, n)throws on that case — the named form is both clearer and friendlier.
- Use
- org.openrewrite.kotlin.stdlib.UseTakeForSubListFromZero$KtRecipe
- Use
take(n)instead ofsubList(0, n) take(n)returns the firstnelements as a stable copy.subList(0, n)returns a live view backed by the original list — surprising aliasing if the source is mutated.
- Use
- org.openrewrite.kotlin.stdlib.UseToListForListToList$KtRecipe
- Use
toList()instead oftoMutableList().toList() toMutableList()already allocates a fresh list — wrapping it in anothertoList()copies it again. Go directly totoList().
- Use
- org.openrewrite.kotlin.stdlib.UseToSetForToListToSet$KtRecipe
- Use
toSet()instead oftoList().toSet() - Materializing a
Listfirst and then aSetallocates one collection that's thrown away.toSet()builds the deduplicating collection directly.
- Use
- org.openrewrite.kotlin.testing.FindAssertEqualsCandidateForKotest$KtRecipe
- Find
assertEquals(...)calls — Kotest migration candidate - Kotest's idiomatic form for
assertEquals(expected, actual)isactual shouldBe expected— the receiver is the subject under test, which composes naturally with chained matchers (actual shouldBe expected; actual.shouldBeOfType<T>()). Each match is a candidate when migrating to Kotest.
- Find
- org.openrewrite.kotlin.testing.FindAssertFalseCandidateForKotest$KtRecipe
- Find
assertFalse(...)calls — Kotest migration candidate - Same shape as
assertTrue: the predicate is collapsed to a boolean and the failure message loses fidelity. Kotest'sactual.shouldBeFalse()(or specialized matchers likeactual.shouldNotContain(...)) records the original expression.
- Find
- org.openrewrite.kotlin.testing.FindAssertJChainUsingExtractingThenContains$KtRecipe
- Find AssertJ
.extracting(...).contains(...)chains - AssertJ's
.extracting("name")uses reflection;.extracting \{ it.name \}(lambda form) is type-safe. Each match is a candidate for the lambda form, or for moving to a.allMatch \{ … \}predicate when the collection-level invariant is what you actually want to assert.
- Find AssertJ
- org.openrewrite.kotlin.testing.FindAssertNotNullCandidateForKotest$KtRecipe
- Find
assertNotNull(...)calls — Kotest migration candidate - Kotest's
actual.shouldNotBeNull()is a contract function: after it returns, the compiler smart-castsactualto its non-nullable type, so the chained matcher can call methods without!!. JUnit'sassertNotNulldoes not smart-cast.
- Find
- org.openrewrite.kotlin.testing.FindAssertNullCandidateForKotest$KtRecipe
- Find
assertNull(...)calls — Kotest migration candidate assertNull(actual)→actual.shouldBeNull()in Kotest. The receiver-style form keeps the subject as the focal point, which composes more cleanly into specialized matchers (actual.shouldBeNullOrEmpty()etc).
- Find
- org.openrewrite.kotlin.testing.FindAssertThrowsCandidateForKotest$KtRecipe
- Find
assertThrows<X> \{ ... \}calls — Kotest migration candidate - JUnit 5's
assertThrows<X> \{ … \}and Kotest'sshouldThrow<X> \{ … \}have the same shape. Migrating gives access to Kotest'sshouldThrowExactly<X>(rejects subclass exceptions) andshouldThrowMessage(text) \{ … \}, which are tighter than JUnit's catch-and-introspect pattern.
- Find
- org.openrewrite.kotlin.testing.FindAssertTrueCandidateForKotest$KtRecipe
- Find
assertTrue(...)calls — Kotest migration candidate assertTrue(condition)collapses the predicate into a boolean before failure formatting can capture what the value actually was. Kotest'sactual.shouldBeTrue()(and the matcher library generally —actual shouldBe true,actual.shouldStartWith(...)) carries the original expression into the failure message.
- Find
- org.openrewrite.kotlin.testing.FindAssertionLibrarySmells$KtRecipe
- Find assertion-library smells
- Search-only bundle for assertion-library specifics: Hamcrest's
assertThat(actual, is(expected))form, and AssertJ's reflective.extracting("name")followed by.contains(...).
- org.openrewrite.kotlin.testing.FindBeforeEachReinitializingFinal$KtRecipe
- Find
@BeforeEachmethods that reassignvalproperties @BeforeEachruns before every test, butvalproperty assignment only happens at construction. IfsetUplooks likevalue = ...against aval, it doesn't compile — but the related anti-pattern (reassigning alateinit varper test where the type-safe shape would be avalinitialized in the constructor) is worth surfacing.
- Find
- org.openrewrite.kotlin.testing.FindCoroutineTestRule$KtRecipe
- Find JUnit 4 coroutine-test
@Rulefields - Hand-rolled
MainCoroutineRule/CoroutineTestRulepatterns predatekotlinx-coroutines-test'sDispatchers.setMain/resetMainhelpers. WithrunTest \{ \}+Dispatchers.setMain(StandardTestDispatcher())the rule's responsibilities are spread across@BeforeEach/@AfterEachcleanly enough that the rule itself becomes redundant.
- Find JUnit 4 coroutine-test
- org.openrewrite.kotlin.testing.FindCoroutineTestSmells$KtRecipe
- Find coroutine-test patterns
- Search-only bundle for coroutine-testing primitives:
runBlockinginside@Test,runBlockingTest(deprecated),TestCoroutineDispatcher(deprecated), JUnit 4@Rulefields named after coroutines (hand-rolledMainCoroutineRule-style), anddelay(...)calls inside arunBlockingtest body.
- org.openrewrite.kotlin.testing.FindDelayInTest$KtRecipe
- Find
delay(...)calls inside test methods running on a real dispatcher delay(ms)inside a test that usesrunBlocking(notrunTest) waits the literal duration in real time — a fast suite slows to a crawl. InsiderunTest \{ \},delayadvances virtual time instantly; the call shape is identical but the runner makes the difference.
- Find
- org.openrewrite.kotlin.testing.FindDisabledTest$KtRecipe
- Find
@Disabledannotations @Disabledis the JUnit 5 skip annotation — typically used for tests that are flaky, broken, or pending an upstream fix. Each match is a tech-debt marker worth reviewing: confirm the skip is still warranted, the reason still applies, and the test isn't hiding a real regression.
- Find
- org.openrewrite.kotlin.testing.FindEmptyTestBody$KtRecipe
- Find
@Testmethods with empty bodies - An empty
@Test fun foo() \{ \}passes unconditionally. The reasons it lands in a codebase are usually disabled-during-WIP, scaffolded-then-forgotten, or a stand-in for a TODO. Each match should either gain assertions, be annotated@Disabledwith a reason, or be deleted.
- Find
- org.openrewrite.kotlin.testing.FindFunctionTestNamedWithUnderscores$KtRecipe
- Find test functions named with snake_case
- Kotlin's backtick syntax lets test names read as sentences:
fun \returns 404 when user not found`(). Names likefun test_returns_404_when_user_not_found()` predate that convention — usually the result of porting Java tests directly.
- org.openrewrite.kotlin.testing.FindHamcrestAssertThatUsage$KtRecipe
- Find
MatcherAssert.assertThat(...)(Hamcrest) calls - Hamcrest's
assertThat(actual, is(expected))was the inspiration for both AssertJ's fluent chains and Kotest's matcher library. On a Kotlin codebase both alternatives compose better with the language (AssertJ via type-safe builders, Kotest via infix and extension functions).
- Find
- org.openrewrite.kotlin.testing.FindJUnitFunctionWithPublic$KtRecipe
- Find
publicmodifier on JUnit 5 test functions - JUnit 5 dropped the JUnit 4 requirement that test methods be public — package-private (Java) or no modifier (Kotlin default) is the convention. Each
public fun test...()is a JUnit 4 holdover that can be dropped.
- Find
- org.openrewrite.kotlin.testing.FindKotestCandidates$KtRecipe
- Find Kotest migration candidates
- Search-only bundle for assertion call sites that have direct Kotest equivalents:
assertEquals(shouldBe),assertTrue/assertFalse(shouldBeTrue/shouldBeFalse),assertNull/assertNotNull(shouldBeNull/shouldNotBeNullwith smart-cast),assertThrows(shouldThrow), plus snake_case test names that Kotlin's backtick syntax can replace with sentence-style names.
- org.openrewrite.kotlin.testing.FindMockitoArgumentCaptor$KtRecipe
- Find
ArgumentCaptor.forClass(X::class.java)allocations ArgumentCaptor.forClass(X::class.java)plus a laterverify(mock).method(captor.capture())is the Mockito idiom for asserting on the actual argument passed in. mockk'sslot<X>()+every \{ mock.method(capture(slot)) \} answers \{ … \}records the value as part of the recording block.
- Find
- org.openrewrite.kotlin.testing.FindMockitoArgumentMatchersAny$KtRecipe
- Find Mockito argument-matcher
any()/eq()/isA()calls - Mockito's argument matchers (
any(),eq(value),isA(X::class.java)) only work inside awhenever/verifycall — they throw if used elsewhere. mockk's matchers (any(),eq(value),match \{ … \}) work the same way but live inevery \{ \}/verify \{ \}blocks, so the matcher and the recording context are co-located.
- Find Mockito argument-matcher
- org.openrewrite.kotlin.testing.FindMockitoInjectMocks$KtRecipe
- Find Mockito
@InjectMocksfields @InjectMocksasks Mockito to wire@Mock-annotated fields into the target's constructor / setters / fields by reflection. In Kotlin code with constructor injection, the cleaner equivalent is to declare the target inside@BeforeEach:val target = Service(mockA, mockB). mockk has no analogous annotation — the explicit constructor call is the convention.
- Find Mockito
- org.openrewrite.kotlin.testing.FindMockitoMockCall$KtRecipe
- Find
Mockito.mock(...)/mock<X>()calls - Mockito's
mock(X::class.java)(or mockito-kotlin'smock<X>()) builds a relaxed proxy that returns sensible defaults for unstubbed calls. The mockk equivalent ismockk<X>()— strict by default (unstubbed calls throw) withmockk<X>(relaxed = true)for the Mockito-style default behavior.
- Find
- org.openrewrite.kotlin.testing.FindMockitoMockField$KtRecipe
- Find Mockito
@Mockfields @Mock-annotated fields are populated byMockitoAnnotations.openMocks(this)(or theMockitoExtension). In mockk the convention is an inline assignment:private val service = mockk<Service>(relaxed = true). Each match is a candidate for that conversion.
- Find Mockito
- org.openrewrite.kotlin.testing.FindMockitoSmells$KtRecipe
- Find mockito-kotlin / Mockito patterns
- Search-only bundle covering the Mockito surface most worth reviewing when migrating to mockk:
mock/spyallocations,whenever.thenReturnchains,verify(...)calls, argument matchers,ArgumentCaptor.forClass, and@Mock/@InjectMocksfield annotations.
- org.openrewrite.kotlin.testing.FindMockitoSpyCall$KtRecipe
- Find
Mockito.spy(...)/spy(...)calls - Mockito's
spy(realInstance)wraps a real object so unstubbed methods call the real implementation. mockk usesspyk(realInstance)— same idea, different semantics aroundevery \{ \} returns ...(mockk records the call, Mockito intercepts the invocation).
- Find
- org.openrewrite.kotlin.testing.FindMockitoVerifyCall$KtRecipe
- Find Mockito
verify(mock).method(...)calls - Mockito's
verify(mock).method(arg)records a verification at the call site. mockk inverts the form:verify \{ mock.method(arg) \}— the lambda block makes the verified invocations explicit and supportsexactly = n,atLeast = n, etc., as named arguments to the outer call.
- Find Mockito
- org.openrewrite.kotlin.testing.FindMockitoWhenThenReturn$KtRecipe
- Find Mockito
whenever(...).thenReturn(...)chains - Mockito's
whenever(call).thenReturn(value)(orwhenever(call).thenAnswer \{ … \}) intercepts the method invocation as it happens. mockk records the invocation in a DSL block:every \{ mock.foo() \} returns value. The mockk form composes more naturally with property access and suspending calls.
- Find Mockito
- org.openrewrite.kotlin.testing.FindParameterizedTestWithValueSourceStrings$KtRecipe
- Find
@ValueSource(strings = [...])annotations @ValueSource(strings = [...])is the simplest@ParameterizedTestdata source. For tests where each row drives multiple parameters,@CsvSource(...)or@MethodSource(...)carry more information per case and read more like a table.
- Find
- org.openrewrite.kotlin.testing.FindRepeatedTestAnnotation$KtRecipe
- Find
@RepeatedTest(N)annotations @RepeatedTest(N)runs the same test body N times — useful for flaky-test reproduction, suspicious for asserting on randomized inputs (use@ParameterizedTest+@MethodSourcefor that). Each match is worth a glance at N and at what the repetition is meant to prove.
- Find
- org.openrewrite.kotlin.testing.FindRunBlockingInTest$KtRecipe
- Find
runBlocking \{ ... \}calls inside test methods runBlockinginside a test method ties the test's wait to real wall-clock time —delay(60_000)is a literal minute.runTest \{ … \}fromkotlinx-coroutines-testskips virtual time forward instead, so the same test finishes immediately while preserving suspend ordering.
- Find
- org.openrewrite.kotlin.testing.FindRunBlockingTestCall$KtRecipe
- Find
runBlockingTest \{ ... \}calls runBlockingTestwas deprecated inkotlinx-coroutines-test1.6 in favor ofrunTest \{ … \}, which uses aTestCoroutineSchedulerinstead of the oldDelayController. The new API has a cleaner contract around how child coroutines are awaited.
- Find
- org.openrewrite.kotlin.testing.FindTagAnnotationUsage$KtRecipe
- Find
@Tag(...)annotations @Tag("slow")is JUnit 5's mechanism for grouping tests so the build can include/exclude them by tag. Useful to flag for tag-name consistency review across modules — if every module has its own spelling of "integration", the build's tag filter doesn't catch them uniformly.
- Find
- org.openrewrite.kotlin.testing.FindTestCoroutineDispatcherUsage$KtRecipe
- Find
TestCoroutineDispatcherallocations TestCoroutineDispatcherwas deprecated alongsiderunBlockingTest. The replacements areStandardTestDispatcher(queues all coroutines to a scheduler) andUnconfinedTestDispatcher(runs them eagerly on the current thread) — pick based on whether the test wants explicit advancement of virtual time.
- Find
- org.openrewrite.kotlin.testing.FindTestFixtureSmells$KtRecipe
- Find test fixture / setup smells
- Search-only bundle for test-method shape issues: empty
@Testbodies,@Testmethods without any recognized assertion call,@Testmethods with many assertions (consider parameterized), and@BeforeEach/@Beforemethods reassigning instance state (lateinit var hint).
- org.openrewrite.kotlin.testing.FindTestFrameworkSetupSmells$KtRecipe
- Find JUnit 5 setup smells (informational)
- Search-only bundle for informational
@ParameterizedTest/@RepeatedTest/@Tag/@Disabledreview markers. None of these are anti-patterns on their own — each one is worth a once-over for parameter-source choice, repetition intent, tag spelling, or whether the disable is still warranted.
- org.openrewrite.kotlin.testing.FindTestNoAssertions$KtRecipe
- Find
@Testmethods with no recognized assertion calls - A test with no
assert*/should*/assertThatcalls relies on its setup to throw on failure — fine for some smoke tests, suspicious for most. Each match is a candidate for adding an explicit assertion that documents what the test is actually verifying.
- Find
- org.openrewrite.kotlin.testing.FindTooManyAssertions$KtRecipe
- Find
@Testmethods with many assertions - A test with more than ~7 assertions is usually testing several behaviors at once — when one fails the others go unreported, and the failure message rarely points at the right cause. Split into focused tests, or move to
@ParameterizedTestif the assertions are repeating with different inputs.
- Find
- org.openrewrite.kotlin.testing.Testing$KtRecipe
- Modernize Kotlin test code
- Find Kotlin-specific test patterns: mockito-kotlin usage where mockk would be idiomatic, deprecated
runBlocking/TestCoroutineDispatcherpatterns, Kotest assertion migration candidates, empty / assertion-less / many-assertion test bodies, snake_case test names, and Hamcrest call sites that fluent assertion libraries (AssertJ, Kotest) replace cleanly. Each match is aSearchResultfor review — nothing is rewritten automatically. For bulk JUnit 4 → JUnit 5 annotation/assertion migration, applyJUnit4to5Migrationfromrewrite-testing-frameworks.
recipes-scala
- org.openrewrite.scala.recipes.cleanup.AvoidEmptyCatchBlock
- Avoid empty catch blocks
- Finds catch blocks that contain no statements, which silently swallow exceptions.
- org.openrewrite.scala.recipes.cleanup.AvoidSystemExit
- Avoid
System.exitin library code - Finds
System.exitandsys.exitcalls which terminate the JVM. Avoid using these in library code; prefer exceptions or controlled shutdown.
- Avoid
- org.openrewrite.scala.recipes.cleanup.EncapsulateField
- Encapsulate public mutable fields
- Finds public
varfields in classes. Public mutable fields break encapsulation; consider using a private var with accessor methods.
- org.openrewrite.scala.recipes.cleanup.ExternalizeCredentials
- Externalize hardcoded credentials
- Finds variable declarations whose name contains credential-related keywords (password, secret, token, apikey, api_key) with a non-empty string literal initializer. Hardcoded credentials are a security risk.
- org.openrewrite.scala.recipes.cleanup.ExternalizeTimeout
- Externalize hardcoded timeouts
- Finds hardcoded timeout values such as
Duration(5, ...),5.seconds, orTimeout(...)with numeric literals. Consider making timeouts configurable.
- org.openrewrite.scala.recipes.cleanup.ExtractMagicNumber
- Extract magic numbers to named constants
- Finds magic numbers (literal integers other than -1, 0, 1, 2) used in expressions or method arguments. Consider extracting them to named constants.
- org.openrewrite.scala.recipes.cleanup.InventoryScalaLogging
- Inventory scala-logging usage
- Finds imports of the Typesafe scala-logging library (
com.typesafe.scalalogging). Use this recipe to inventory logging framework usage across a codebase.
- org.openrewrite.scala.recipes.cleanup.InventoryTypesafeConfig
- Inventory Typesafe Config usage
- Finds imports of the Typesafe Config library (
com.typesafe.config). Use this recipe to inventory configuration library usage across a codebase.
- org.openrewrite.scala.recipes.cleanup.KeepClassesSmall
- Keep classes small (max 30 members)
- Finds classes with more than 30 members. Large classes are harder to maintain; consider splitting into smaller classes.
- org.openrewrite.scala.recipes.cleanup.KeepMethodsShort
- Keep methods short (max 20 statements)
- Finds methods with more than 20 statements. Long methods are harder to understand and maintain; consider refactoring.
- org.openrewrite.scala.recipes.cleanup.PatchLog4j
- Ensure Log4j is patched against CVE-2021-44228
- Finds imports of Log4j 1.x (
org.apache.log4j) or Log4j 2.x (org.apache.logging.log4j). Ensure your Log4j version is patched against CVE-2021-44228.
- org.openrewrite.scala.recipes.cleanup.PreferExplicitImports
- Prefer explicit imports over wildcards
- Finds wildcard imports (
import foo._orimport foo.*). Explicit imports are generally preferred for clarity.
- org.openrewrite.scala.recipes.cleanup.PreferImmutableCollections
- Prefer immutable collections
- Replaces imports of
scala.collection.mutable.*withscala.collection.immutable.*. Idiomatic Scala prefers immutable collections.
- org.openrewrite.scala.recipes.cleanup.PreferImmutableVal
- Prefer
valovervar - Finds mutable
vardeclarations in Scala code. Idiomatic Scala prefers immutablevalover mutablevar.
- Prefer
- org.openrewrite.scala.recipes.cleanup.PreferOption
- Prefer
Optionovernull - Replaces
nullliteral withNone. Idiomatic Scala usesOptioninstead of null.
- Prefer
- org.openrewrite.scala.recipes.cleanup.PreferPatternMatch
- Prefer pattern matching over
asInstanceOfcasts - Finds
.asInstanceOf[T]type casts that should be replaced with pattern matching. Idiomatic Scala prefers pattern matching over explicit casts.
- Prefer pattern matching over
- org.openrewrite.scala.recipes.cleanup.PreferPatternMatchOverInstanceOf
- Prefer pattern matching over
isInstanceOf/asInstanceOfchains - Finds
ifstatements that checkisInstanceOfin the condition and useasInstanceOfin the then-part. Replace with pattern matching for idiomatic Scala.
- Prefer pattern matching over
- org.openrewrite.scala.recipes.cleanup.PreferScalaPropertyAccess
- Prefer Scala-style property access over Java getters
- Finds Java-style getter methods (
getName,getValue, etc.) that could be replaced with Scala-style property access.
- org.openrewrite.scala.recipes.cleanup.PreferSpecificTypes
- Prefer specific types over
Any - Finds variable declarations whose type expression contains
Any. TypeAnyis the Scala equivalent ofObjectand is usually too broad.
- Prefer specific types over
- org.openrewrite.scala.recipes.cleanup.PreferStringInterpolation
- Prefer string interpolation over concatenation
- Finds string concatenation using the
+operator. Idiomatic Scala prefers string interpolation (e.g.,s"hello $name") over concatenation with+.
- org.openrewrite.scala.recipes.cleanup.ReduceNesting
- Reduce deep nesting by extracting methods
- Finds
defmethods with deeply nested code (5+ indentation levels). Deeply nested code is hard to follow; consider extracting methods.
- org.openrewrite.scala.recipes.cleanup.ReduceParameterCount
- Reduce parameter count (max 5 parameters)
- Finds
defmethods with more than 5 parameters. Long parameter lists hurt readability; consider using a case class.
- org.openrewrite.scala.recipes.cleanup.RemoveExplicitReturn
- Remove explicit
returnstatements - Removes explicit
returnstatements in Scala code. In Scala, the last expression in a method is automatically the return value, so explicitreturnis not idiomatic.
- Remove explicit
- org.openrewrite.scala.recipes.cleanup.RemoveRedundantToString
- Remove redundant
toStringonString - Removes calls to
.toStringon expressions that are already of typeString. Such calls are redundant.
- Remove redundant
- org.openrewrite.scala.recipes.cleanup.RemoveUnitReturnType
- Remove unnecessary
: Unitreturn type - Removes the explicit
Unitreturn type annotation from Scala methods. In Scala, methods returningUnitdo not need the: Unitannotation.
- Remove unnecessary
- org.openrewrite.scala.recipes.cleanup.RemoveUnusedBinding
- Remove unused variable bindings
- Removes variable declarations whose name starts with
_(underscore-prefixed binding). This removes unused variables that represent dead code.
- org.openrewrite.scala.recipes.cleanup.ResolveTodoComment
- Resolve TODO/FIXME comments
- Finds comments containing TODO, FIXME, HACK, or XXX. These indicate incomplete work that should be tracked and resolved.
- org.openrewrite.scala.recipes.cleanup.ReviewDeprecatedApi
- Review deprecated API declarations
- Finds declarations annotated with
@deprecatedin Scala code. Deprecated APIs should be reviewed for removal or migration.
- org.openrewrite.scala.recipes.cleanup.SimplifyBooleanExpression
- Simplify boolean expression
- Simplifies redundant boolean comparisons such as
x == truetoxandx == falseto!x.
- org.openrewrite.scala.recipes.cleanup.UseCollectionConverters
- Replace
JavaConverterswithCollectionConverters scala.collection.JavaConverterswas deprecated in Scala 2.13 in favor ofscala.jdk.CollectionConverters. This recipe replaces the import automatically.
- Replace
- org.openrewrite.scala.recipes.cleanup.UseDirectToSet
- Replace unnecessary intermediate collection before
.toSet - Replaces patterns like
.toList.toSetor.toSeq.toSetwith.toSetto avoid creating an unnecessary intermediate collection.
- Replace unnecessary intermediate collection before
- org.openrewrite.scala.recipes.cleanup.UseLogger
- Use logging framework instead of
println - Finds
printlncalls in Scala code. Usingprintlndirectly is not suitable for production; use a logging framework instead.
- Use logging framework instead of
- org.openrewrite.scala.recipes.cleanup.UseLoggerForExceptions
- Use logging framework instead of
printStackTrace - Finds
.printStackTracecalls. Use a logging framework instead of writing directly toSystem.err.
- Use logging framework instead of
- org.openrewrite.scala.recipes.cleanup.UseOptionSafely
- Use
Optionsafely - Finds calls to
.getonOptionvalues. Calling.getonOptioncan throwNoSuchElementException; prefergetOrElse,map,fold, or pattern matching.
- Use
- org.openrewrite.scala.recipes.cleanup.UseOrNull
- Replace
.getOrElse(null)with.orNull - Replaces
.getOrElse(null)onOptionvalues with.orNullfor a cleaner, idiomatic alternative.
- Replace
- org.openrewrite.scala.recipes.concurrency.AvoidBlockingCalls
- Avoid blocking calls (
Await.result/Await.ready) - Finds
Await.resultandAwait.readycalls which block the current thread. Consider using non-blocking Future composition with map, flatMap, or for-comprehensions.
- Avoid blocking calls (
- org.openrewrite.scala.recipes.concurrency.AvoidThreadSleep
- Avoid
Thread.sleep - Finds
Thread.sleepcalls which block the current thread. Consider using scheduled executors or akka scheduler instead.
- Avoid
- org.openrewrite.scala.recipes.concurrency.PreferCustomExecutionContext
- Prefer custom
ExecutionContextover global - Finds imports of
scala.concurrent.ExecutionContext.Implicits.global. The global ExecutionContext may not be appropriate for blocking I/O operations; prefer a custom ExecutionContext backed by a dedicated thread pool.
- Prefer custom
- org.openrewrite.scala.recipes.concurrency.SynchronizeMutableState
- Synchronize mutable shared state
- Finds
vardeclarations at class level that lack@volatileor other synchronization annotations. Mutable shared state without synchronization is a common source of concurrency bugs.
- org.openrewrite.scala.recipes.errorhandling.PreferDirectEitherOps
- Prefer direct
Eitheroperations over projections - Finds usages of
.leftand.rightprojections onEither. Since Scala 2.13,Eitheris right-biased somap/flatMapwork directly. Useswapto operate on theLeftside instead of.left.
- Prefer direct
- org.openrewrite.scala.recipes.errorhandling.PreferFunctionalErrorHandling
- Prefer functional error handling over
throwexpressions - Finds
throwexpressions inside method bodies that should use functional error handling. Throwing exceptions breaks referential transparency; prefer returningTry,Either, orOption.
- Prefer functional error handling over
- org.openrewrite.scala.recipes.errorhandling.UseNonFatalMatcher
- Use
NonFatalmatcher for broad catch patterns - Finds catch blocks using broad patterns like
case e: Exception =>orcase _ =>that should usescala.util.control.NonFatalto catch all non-fatal exceptions while allowing fatal errors to propagate.
- Use
- org.openrewrite.scala.recipes.errorhandling.UseTrySafely
- Use
Trysafely without calling.get - Finds calls to
.getonscala.util.Tryvalues that should use safer alternatives. Calling.geton aFailurethrows the contained exception; prefergetOrElse,map, or pattern matching.
- Use
- org.openrewrite.scala.recipes.migrate.MigrateImplicitToGivenUsing
- Migrate
implicittogiven/using(Scala 3) - Finds
implicitkeyword usage on methods and parameters. In Scala 3,implicitis replaced withgiven/using.
- Migrate
- org.openrewrite.scala.recipes.migrate.MigrateProcedureSyntax
- Migrate deprecated procedure syntax
- Finds method declarations that use deprecated Scala procedure syntax (methods with a body block but no explicit return type or
=sign). Procedure syntax was deprecated in Scala 2.13 and removed in Scala 3.
- org.openrewrite.scala.recipes.migrate.RemoveAny2StringAdd
- Remove deprecated
any2stringaddusage - Finds expressions like
1 + "string"that rely on the deprecatedany2stringaddimplicit conversion. This was deprecated in Scala 2.13 and removed in Scala 3. Use string interpolation or.toStringinstead.
- Remove deprecated
- org.openrewrite.scala.recipes.migrate.RemoveExistentialTypes
- Remove existential types (removed in Scala 3)
- Finds existential types using
forSomesyntax. Existential types were removed in Scala 3 and must be rewritten.
- org.openrewrite.scala.recipes.migrate.RemoveSymbolLiterals
- Remove deprecated symbol literals
- Finds symbol literals like
'foowhich were deprecated in Scala 2.13 and removed in Scala 3. UseSymbol("foo")instead.
- org.openrewrite.scala.recipes.migrate.ReviewAbstractOverride
- Review abstract override for Scala 3
- Finds methods or fields with both
abstractandoverridemodifiers. The stackable trait pattern usingabstract overridemay need review for Scala 3.
- org.openrewrite.scala.recipes.migrate.ReviewTraitVarInit
- Review trait var initialization for Scala 3
- Finds traits that have initialized
varfields. In Scala 3, trait initialization semantics changed and these may need review.
- org.openrewrite.scala.recipes.migrate.UseQuestionMarkWildcard
- Use
?instead of_for wildcard types (Scala 3) - Finds usage of
_as a wildcard type in type parameters (e.g.,List[_]). In Scala 3, the wildcard type syntax changed from_to?.
- Use
- org.openrewrite.scala.recipes.migrate.akka.MigrateActorRefTell
- Migrate classic actor tell to typed ActorRef
- Finds classic Akka actor messaging patterns (
actorRef ! msgoractorRef.tell(msg)). Consider migrating to typedActorRefmessaging.
- org.openrewrite.scala.recipes.migrate.akka.MigrateToTypedActor
- Migrate classic Actor to Akka Typed Behavior
- Removes
akka.actor.Actorimports and marks classes extendingActororUntypedActorfrom classic Akka for migration to Akka TypedBehavior.
- org.openrewrite.scala.recipes.migrate.akka.MigrateToTypedActorSystem
- Migrate
akka.actor.ActorSystemtoakka.actor.typed.ActorSystem - Replaces the import
akka.actor.ActorSystemwithakka.actor.typed.ActorSystemto migrate from the classic untyped actor system to Akka Typed.
- Migrate
- org.openrewrite.scala.recipes.migrate.akka.RemoveDeprecatedAkkaImports
- Remove deprecated Akka imports
- Removes imports of deprecated Akka APIs such as
akka.pattern.ask(old ask pattern) andakka.actor.PoisonPill. These have no direct drop-in replacement and should be replaced with their modern Akka Typed equivalents.
- org.openrewrite.scala.recipes.migrate.database.MigrateAnorm
- Migrate Anorm to Doobie, Quill, or Skunk
- Removes imports of the Anorm SQL library (
anorm.*). Consider evaluating modern alternatives such as Doobie, Quill, or Skunk.
- org.openrewrite.scala.recipes.migrate.database.MigratePhantomDsl
- Migrate Phantom DSL to Datastax driver or quill-cassandra
- Removes imports of the Phantom DSL library (
com.outworkers.phantom.*). Consider migrating to the direct Datastax driver or quill-cassandra.
- org.openrewrite.scala.recipes.migrate.database.MigrateScalikeJdbc
- Migrate ScalikeJDBC to Doobie or Quill
- Removes imports of the ScalikeJDBC library (
scalikejdbc.*). Consider evaluating modern alternatives such as Doobie or Quill.
- org.openrewrite.scala.recipes.migrate.database.SecureSqlQueries
- Ensure parameterized SQL queries
- Finds raw SQL string patterns such as
sql"...",SQL(...), ors"SELECT...". Ensure parameterized queries are used to prevent SQL injection.
- org.openrewrite.scala.recipes.migrate.ecosystem.AvoidBlockingSlick
- Avoid blocking Slick database calls
- Finds methods that combine
Await.resultwithdb.run, indicating a blocking Slick database call. Use streaming or async patterns instead.
- org.openrewrite.scala.recipes.migrate.ecosystem.MigrateCatsEffect2To3
- Migrate Cats Effect 2 to Cats Effect 3
- Finds Cats Effect 2 imports by detecting
cats.effect.IOwithoutcats.effect.unsafe, or CE2-specific types likeContextShiftandTimer. Consider migrating to Cats Effect 3.
- org.openrewrite.scala.recipes.migrate.ecosystem.MigrateScalazToCats
- Migrate Scalaz to Cats
- Removes imports of
scalaz.packages. Scalaz is a legacy FP library; consider migrating to Cats or ZIO.
- org.openrewrite.scala.recipes.migrate.ecosystem.UseCirceDerivation
- Use circe
derivesfor Scala 3 - Finds imports of
io.circe.generic.autowhich uses Shapeless-based automatic derivation. In Scala 3, consider usingderivessyntax for codec derivation instead.
- Use circe
- org.openrewrite.scala.recipes.migrate.http.MigrateAkkaHttpToPekko
- Find Akka HTTP imports to migrate to Apache Pekko
- Finds imports starting with
akka.http. Akka HTTP should be migrated to Apache Pekko HTTP (org.apache.pekko.http), the community-maintained fork.
- org.openrewrite.scala.recipes.migrate.http.MigrateDispatch
- Migrate Dispatch to sttp or http4s-client
- Removes imports starting with
dispatch.. Dispatch is an unmaintained HTTP client library; consider using sttp, http4s-client, or requests-scala.
- org.openrewrite.scala.recipes.migrate.http.MigrateFinagle
- Migrate Finagle to http4s, tapir, or pekko-http
- Removes imports starting with
com.twitter.finagle. Finagle is a legacy RPC framework; consider evaluating http4s, tapir, or pekko-http as alternatives.
- org.openrewrite.scala.recipes.migrate.http.MigrateScalatra
- Migrate Scalatra to http4s, tapir, or Play
- Removes imports starting with
org.scalatra. Scalatra is a servlet-based framework with declining activity; consider migrating to http4s, tapir, or Play Framework.
- org.openrewrite.scala.recipes.migrate.json.MigrateJacksonScala
- Remove Jackson Scala module imports
- Removes imports of the Jackson Scala module (
com.fasterxml.jackson.module.scala.*). Jackson is a Java-centric library and its Scala module can cause issues with Scala types. Consider using a Scala-native JSON library such as circe or zio-json. Removing the imports causes the compiler to highlight all usage sites that need updating.
- org.openrewrite.scala.recipes.migrate.json.MigrateJson4s
- Remove json4s imports
- Removes imports of the json4s library (
org.json4s.*). json4s has known performance and maintenance concerns and should be replaced with a modern Scala JSON library such as circe or zio-json. Removing the imports causes the compiler to highlight all usage sites that need updating.
- org.openrewrite.scala.recipes.migrate.json.MigrateLiftJson
- Remove lift-json imports
- Removes imports of the lift-json library (
net.liftweb.json.*). lift-json is tightly coupled to the Lift framework and should be replaced with a standalone Scala JSON library such as circe or play-json. Removing the imports causes the compiler to highlight all usage sites that need updating.
- org.openrewrite.scala.recipes.migrate.json.MigrateSprayJson
- Remove spray-json imports
- Removes imports of the spray-json library (
spray.json.*). spray-json is no longer actively maintained and should be replaced with a modern Scala JSON library such as circe, play-json, or zio-json. Removing the imports causes the compiler to highlight all usage sites that need updating.
- org.openrewrite.scala.recipes.migrate.play.InjectWsClient
- Inject
WSClientinstead of using deprecatedWS - Finds imports of the deprecated
play.api.libs.ws.WSobject. In Play 2.6+,WSwas deprecated; injectWSClientinstead.
- Inject
- org.openrewrite.scala.recipes.migrate.play.MigratePlayGlobalSettings
- Migrate
GlobalSettingsto dependency injection (Play 2.6+) - Finds classes extending
GlobalSettingsand imports ofplay.api.GlobalSettings. GlobalSettings is deprecated in Play 2.6+; use dependency injection instead.
- Migrate
- org.openrewrite.scala.recipes.migrate.play.UseAsyncPlayAction
- Use
Action.asyncwithFutureinstead of blocking - Finds Play controller actions (
Action \{orAction.async \{) that containAwait.resultblocking calls. Blocking inside Play Actions can exhaust the thread pool; useAction.asyncwithFutureinstead.
- Use
- org.openrewrite.scala.recipes.migrate.play.UsePlayJsonDirectly
- Use Play JSON
JsValuedirectly - Finds imports of
play.api.libs.json.Jsonand usages ofJson.parseorJson.toJsonthat may rely on deprecated implicit conversions. Consider usingplay.api.libs.json.JsValuedirectly.
- Use Play JSON
- org.openrewrite.scala.recipes.migrate.scala3.MigrateDelayedInit
- Migrate from
DelayedInit/Appto@main - Finds classes or objects extending
DelayedInitorApp. TheDelayedInittrait was deprecated in Scala 2.13 and removed in Scala 3. Use@mainannotation instead.
- Migrate from
- org.openrewrite.scala.recipes.migrate.scala3.MigrateXmlLiterals
- Migrate XML literals to scala-xml interpolation
- Finds XML literal usage in Scala code. XML literals were removed in Scala 3; use scala-xml library string interpolation instead.
- org.openrewrite.scala.recipes.migrate.scala3.RemoveAutoTupling
- Remove auto-tupling (not available in Scala 3)
- Finds imports of
scala.language.autoTupling. Auto-tupling is not available in Scala 3 and code relying on it must be rewritten.
- org.openrewrite.scala.recipes.migrate.scala3.ReplaceDoWhileLoop
- Replace do-while loops (removed in Scala 3)
- Finds
do-whileloops which were removed in Scala 3. Rewrite using awhileloop with initial execution of the loop body.
- org.openrewrite.scala.recipes.performance.PreferVectorOrPrepend
- Prefer Vector or prepend for append-heavy workloads
- Finds usage of the
:+operator to append to a List, which is O(n). Prefer Vector for append-heavy workloads or prepend with::instead.
- org.openrewrite.scala.recipes.performance.PreferViewMapValues
- Prefer
.view.mapValuesfor Scala 2.13+ - Finds calls to
.mapValueswhich is deprecated in Scala 2.13+ and returns a lazy view instead of a strict Map. Use.view.mapValues(...).toMapinstead.
- Prefer
- org.openrewrite.scala.recipes.performance.UseCount
- Replace
filterthensizewithcount - Replaces
.filter(f).sizeor.filter(f).lengthchains with.count(f)to avoid creating an unnecessary intermediate collection.
- Replace
- org.openrewrite.scala.recipes.performance.UseFlatMap
- Replace
mapthenflattenwithflatMap - Replaces
.map(f).flattenchains with.flatMap(f)for clarity and to avoid creating an unnecessary intermediate collection.
- Replace
- org.openrewrite.scala.recipes.performance.UseHeadOption
- Replace
.headwith.headOption - Replaces
.headcalls on collections with.headOptionto avoidNoSuchElementExceptionon empty collections.
- Replace
- org.openrewrite.scala.recipes.performance.UseIsEmpty
- Use
isEmptyinstead ofsize == 0 - Replaces
collection.size == 0withcollection.isEmptyfor clarity and potential performance benefits.
- Use
- org.openrewrite.scala.recipes.performance.UseLastOption
- Replace
.lastwith.lastOption - Replaces
.lastcalls on collections with.lastOptionto avoidNoSuchElementExceptionon empty collections.
- Replace
- org.openrewrite.scala.recipes.performance.UseNonEmpty
- Use
nonEmptyinstead ofsize > 0 - Replaces
collection.size > 0withcollection.nonEmptyfor clarity and potential performance benefits.
- Use
- org.openrewrite.scala.recipes.safety.AvoidThrowInFinally
- Avoid throwing in finally blocks
- Finds
throwstatements insidefinallyblocks. Throwing in afinallyblock can mask the original exception, making debugging harder.
- org.openrewrite.scala.recipes.safety.NarrowCatchClause
- Narrow catch clauses that catch
Throwable - Finds catch blocks that catch
Throwableand should be narrowed to specific exception types. CatchingThrowablealso catches fatal errors likeOutOfMemoryErrorandStackOverflowError. Prefer catching specific exception types.
- Narrow catch clauses that catch
- org.openrewrite.scala.recipes.safety.PreferConcurrentUtils
- Prefer
java.util.concurrentoversynchronized - Finds
synchronizedblocks in Scala code. Consider usingjava.util.concurrentalternatives for better performance and composability.
- Prefer
- org.openrewrite.scala.recipes.safety.RemoveUnusedImport
- Remove potentially unused imports (heuristic)
- Removes imports where the imported simple name does not appear in the rest of the file. This is an approximate heuristic and may produce false positives.
- org.openrewrite.scala.recipes.testing.MigrateSpecs2
- Migrate specs2 to ScalaTest or MUnit
- Finds imports of
org.specs2. Consider migrating to ScalaTest or MUnit.
- org.openrewrite.scala.recipes.testing.MigrateToAnyFlatSpec
- Migrate from
FlatSpectoAnyFlatSpec - Renames
FlatSpectoAnyFlatSpecin extends clauses and updates the import fromorg.scalatest.FlatSpectoorg.scalatest.flatspec.AnyFlatSpec(ScalaTest 3.x).
- Migrate from
- org.openrewrite.scala.recipes.testing.UseNewScalaTestMatchers
- Migrate to
org.scalatest.matchers.should.Matchers - Replaces imports of
org.scalatest.Matchersororg.scalatest.ShouldMatcherswithorg.scalatest.matchers.should.Matchers.
- Migrate to
- org.openrewrite.scala.recipes.testing.UseScalaTestMatchers
- Use ScalaTest matchers instead of
assert(x == y) - Finds
assert(x == y)patterns andassertEqualscalls. Consider using ScalaTest matchers:x shouldBe y.
- Use ScalaTest matchers instead of
rewrite-ai
- io.moderne.ai.FindAgentsInUse
- Find AI agents configuration files
- Scans codebases to identify usage of AI agents by looking at the agent configuration files present in the repository.
- io.moderne.ai.FindLibrariesInUse
- Find AI libraries in use
- Scans codebases to identify usage of AI services. Detects AI libraries across Java dependencies. Useful for auditing and understanding AI integration patterns.
- io.moderne.ai.FindModelsInUse
- Find AI models in use
- Scans codebases to identify usage of Large Language Models (LLMs). Detects model references and configuration patterns across Java classes, properties files, YAML configs... Useful for identifying model usage.
rewrite-angular
- org.openrewrite.angular.UpgradeToAngular10
- Upgrade to Angular 10
- Migrates Angular 9.x applications to Angular 10. This includes removing the deprecated
es5BrowserSupportoption fromangular.json, renaming deprecatedvalidator/asyncValidatorto their plural forms, renamingbrowserslistto.browserslistrc, migrating to solution-styletsconfig.json, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular11
- Upgrade to Angular 11
- Migrates Angular 10.x applications to Angular 11. This includes replacing
ViewEncapsulation.NativewithViewEncapsulation.ShadowDom, removing the deprecatedextractCssbuild option fromangular.json, flagging deprecated string-basedloadChildrenandpreserveQueryParamsusage, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular12
- Upgrade to Angular 12
- Migrates Angular 11.x applications to Angular 12. This includes adding
defaultConfiguration: "production"to build targets inangular.json, replacingnode-sasswithsass(Dart Sass), flagging deprecatedasynctest helper and View Engine APIs, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular13
- Upgrade to Angular 13
- Migrates Angular 12.x applications to Angular 13. This includes updating
tsconfig.jsontarget toes2017, removing IE11 polyfills, removingdefaultProjectfromangular.json, adding TestBed module teardown, simplifyingComponentFactoryResolverusage, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular14
- Upgrade to Angular 14
- Migrates Angular 13.x applications to Angular 14. This includes replacing form classes with their
Untyped*equivalents for backward compatibility with typed forms, updating deprecatedinitialNavigationrouter option values, removingaotSummariesfrom TestBed calls, and flaggingpathMatchproperties that may need type narrowing.
- org.openrewrite.angular.UpgradeToAngular15
- Upgrade to Angular 15
- Migrates Angular 14.x applications to Angular 15. This includes removing the
relativeLinkResolutionoption fromRouterModule.forRoot(), removing theenableIvycompiler option fromtsconfig.json, flagging the deprecatedDATE_PIPE_DEFAULT_TIMEZONEtoken andprovidedIn: NgModule/'any'usage, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular16
- Upgrade to Angular 16
- Migrates Angular 15.x applications to Angular 16. This includes removing
entryComponentsandmoduleIdfrom decorators, replacingRouterLinkWithHrefwithRouterLink, moving theXhrFactoryimport to@angular/common, and flagging removed APIs likeReflectiveInjector,renderModuleFactory, andBrowserTransferStateModule.
- org.openrewrite.angular.UpgradeToAngular17
- Upgrade to Angular 17
- Migrates Angular 16.x applications to Angular 17. This includes updating Angular package versions, replacing legacy deep
zone.jsimports, flagging the removedwithNoDomReuseandsetupTestingRouterAPIs, and upgrading TypeScript andzone.jsdependencies.
- org.openrewrite.angular.UpgradeToAngular18
- Upgrade to Angular 18
- Migrates Angular 17.x applications to Angular 18. This includes replacing the deprecated
asynctest helper withwaitForAsync, migratingHttpClientModuletoprovideHttpClient(), moving Transfer State APIs to@angular/core, and flagging removed platform APIs.
- org.openrewrite.angular.UpgradeToAngular19
- Upgrade to Angular 19
- Migrates Angular 18.x applications to Angular 19. This includes updating Angular package versions, adjusting the standalone default, renaming
ExperimentalPendingTaskstoPendingTasks, moving theApplicationConfigimport to@angular/core, and updatingzone.js.
- org.openrewrite.angular.UpgradeToAngular20
- Upgrade to Angular 20
- Migrates Angular 19.x applications to Angular 20. This includes running the Angular 19 migration first, then updating Angular package versions, renaming experimental APIs promoted to stable, and upgrading TypeScript to 5.8.x.
- org.openrewrite.angular.UpgradeToAngular21
- Upgrade to Angular 21
- Migrates Angular 20.x applications to Angular 21. This includes running the Angular 20 migration first, flagging Karma test runner usage for Vitest migration, deprecated NgClass, zone.js-dependent test helpers, and upgrading TypeScript to 5.9.x.
- org.openrewrite.angular.UpgradeToAngular8
- Upgrade to Angular 8
- Migrates Angular 7.x applications to Angular 8. This includes adding the now-required
static: falseto@ViewChildand@ContentChilddecorators, moving theDOCUMENTimport from@angular/platform-browserto@angular/common, removingrxjs-compatand flagging any remaining RxJS 5-style imports, flagging removed@angular/httpimports, converting deprecated string-basedloadChildrento dynamic imports, and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.UpgradeToAngular9
- Upgrade to Angular 9
- Migrates Angular 8.x applications to Angular 9. This includes removing the now-default
static: falsefrom view query decorators, replacingTestBed.get()withTestBed.inject(), adding generic type parameters toModuleWithProviders, enabling AOT compilation inangular.json, updatingtsconfig.jsonmodule settings for Ivy, flagging removed View Engine APIs (Renderer,RenderComponentType,RootRenderer), and upgrading Angular, TypeScript, and related dependency versions.
- org.openrewrite.angular.migration.add-default-configuration
- Add
defaultConfigurationto build targets - Adds
"defaultConfiguration": "production"to build architect targets inangular.json. Angular 12 changedng buildto produce production bundles by default.
- Add
- org.openrewrite.angular.migration.add-localize-polyfill
- Add
@angular/localize/initpolyfill import - Adds
import '@angular/localize/init'topolyfills.ts. Angular 9 introduced the$localizeruntime API for i18n. Projects using internationalization must import this polyfill or the application will fail at runtime with$localize is not defined. The@angular/localizepackage must also be added as a dependency.
- Add
- org.openrewrite.angular.migration.add-module-with-providers-generic
- Add generic type to
ModuleWithProviders - Adds the required generic type parameter to bare
ModuleWithProvidersreturn types. Angular 10 requiresModuleWithProviders<T>whereTis the NgModule type. The module type is inferred from thengModuleproperty in the return statement.
- Add generic type to
- org.openrewrite.angular.migration.add-static-false-to-view-queries
- Add
static: falseto view queries - Adds
static: falseto@ViewChildand@ContentChilddecorators that don't have thestaticproperty. Angular 8 requires an explicitstaticflag for view query decorators. Usingstatic: falsepreserves the Angular 7 default behavior (queries resolved after change detection).
- Add
- org.openrewrite.angular.migration.add-testbed-teardown
- Add TestBed module teardown
- Adds
\{ teardown: \{ destroyAfterEach: true \} \}as the third argument toTestBed.initTestEnvironment()calls. Angular 13 changed the default teardown behavior, and this ensures explicit opt-in for module teardown after each test.
- org.openrewrite.angular.migration.enable-aot-build
- Enable AOT compilation in
angular.json - Adds
"aot": trueto build options inangular.json. Angular 9 made AOT compilation the default, and projects upgrading from Angular 8 should enable it explicitly.
- Enable AOT compilation in
- org.openrewrite.angular.migration.explicit-standalone-flag
- Make standalone flag explicit
- Adds
standalone: falseto non-standalone Angular components, directives, and pipes, and removes redundantstandalone: truesince it became the default in Angular 19.
- org.openrewrite.angular.migration.migrate-constructor-to-inject
- Migrate constructor injection to
inject() - Converts constructor parameter properties in Angular classes to field declarations using the
inject()function. For example,constructor(private svc: MyService) \{\}becomesprivate svc = inject(MyService);.
- Migrate constructor injection to
- org.openrewrite.angular.migration.migrate-input-to-signal
- Migrate
@Input()to signal-basedinput() - Converts
@Input()decorated properties in Angular classes to signal-basedinput()declarations. For example,@Input() name: stringbecomesname = input<string>(), and@Input(\{ required: true \}) name!: stringbecomesname = input.required<string>().
- Migrate
- org.openrewrite.angular.migration.migrate-output-to-signal
- Migrate
@Output()to signal-basedoutput() - Converts
@Output()decorated properties usingEventEmitterin Angular classes to signal-basedoutput()declarations. For example,@Output() clicked = new EventEmitter<void>()becomesclicked = output<void>().
- Migrate
- org.openrewrite.angular.migration.migrate-query-to-signal
- Migrate query decorators to signal-based functions
- Converts
@ViewChild(),@ViewChildren(),@ContentChild(), and@ContentChildren()decorated properties to signal-based query functions. For example,@ViewChild('ref') el: ElementRefbecomesel = viewChild<ElementRef>('ref').
- org.openrewrite.angular.migration.migrate-to-solution-style-tsconfig
- Migrate to solution-style tsconfig
- Migrates a project to use a solution-style
tsconfig.json. The originaltsconfig.jsoncontent is moved totsconfig.base.json(with project-specific fields removed), andtsconfig.jsonis replaced with a solution-style config that references the project's TypeScript configurations. Other tsconfig files that extend./tsconfig.jsonare updated to extend./tsconfig.base.json.
- org.openrewrite.angular.migration.move-document-import
- Move
DOCUMENTimport to@angular/core - Moves the
DOCUMENTimport from older Angular modules to@angular/core.
- Move
- org.openrewrite.angular.migration.remove-aot-summaries
- Remove
aotSummariesfrom TestBed - Removes the
aotSummariesproperty fromTestBed.configureTestingModule()andTestBed.initTestEnvironment()calls. TheaotSummariesparameter was removed in Angular 14 as it was only needed for the View Engine compiler.
- Remove
- org.openrewrite.angular.migration.remove-browser-module-with-server-transition
- Remove
BrowserModule.withServerTransition - Replaces
BrowserModule.withServerTransition(\{ appId: '...' \})withBrowserModuleand adds\{ provide: APP_ID, useValue: '...' \}to the NgModule providers. ThewithServerTransitionmethod was removed in Angular 19.
- Remove
- org.openrewrite.angular.migration.remove-component-factory-resolver
- Remove
ComponentFactoryResolver - Replaces
resolver.resolveComponentFactory(Component)with justComponentand removes theComponentFactoryResolverimport. Since Ivy,ViewContainerRef.createComponentaccepts the component class directly.ComponentFactoryResolverwas deprecated in Angular 13 and removed in Angular 16.
- Remove
- org.openrewrite.angular.migration.remove-default-project
- Remove
defaultProjectfromangular.json - Removes the deprecated
defaultProjectproperty fromangular.json. ThedefaultProjectoption was deprecated in Angular 13 and the CLI infers the default project from the workspace.
- Remove
- org.openrewrite.angular.migration.remove-empty-ng-on-init
- Remove empty
ngOnInitlifecycle hooks - Removes empty
ngOnInitlifecycle hook methods and OnInit interface from Angular components.
- Remove empty
- org.openrewrite.angular.migration.remove-enable-ivy
- Remove
enableIvycompiler option - Removes the
enableIvyoption fromangularCompilerOptionsintsconfig.json. Ivy is the only rendering engine since Angular 12, and the option was removed in Angular 15.
- Remove
- org.openrewrite.angular.migration.remove-entry-components
- Remove
entryComponents - Removes the
entryComponentsproperty from@NgModuleand@Componentdecorators, and removes theANALYZE_FOR_ENTRY_COMPONENTSimport. These were removed in Angular 16 as they served no purpose since Ivy.
- Remove
- org.openrewrite.angular.migration.remove-es5-browser-support
- Remove
es5BrowserSupportfromangular.json - Removes the deprecated
es5BrowserSupportoption fromangular.json.es5BrowserSupportwas deprecated in Angular 7.3 and removed in Angular 10. Differential loading is now handled automatically by the Angular CLI based on the project's browserslist configuration.
- Remove
- org.openrewrite.angular.migration.remove-extract-css
- Remove
extractCssfromangular.json - Removes the deprecated
extractCssbuild option fromangular.json. In Angular 11, CSS extraction became the default behavior for production builds and the option was deprecated.
- Remove
- org.openrewrite.angular.migration.remove-ie-polyfills
- Remove IE11 polyfills
- Removes IE11-specific polyfill imports (
core-js,classlist.js,web-animations-js) frompolyfills.tsandangular.json. Angular 13 dropped IE11 support, making these polyfills unnecessary.
- org.openrewrite.angular.migration.remove-module-id
- Remove
moduleId - Removes the
moduleIdproperty from@Componentand@Directivedecorators.moduleIdwas deprecated in Angular 16 and removed in Angular 17 as it served no purpose since Ivy.
- Remove
- org.openrewrite.angular.migration.remove-relative-link-resolution
- Remove
relativeLinkResolution - Removes the
relativeLinkResolutionoption fromRouterModule.forRoot()calls. This option was deprecated in Angular 14 and removed in Angular 15.
- Remove
- org.openrewrite.angular.migration.remove-standalone-true
- Remove redundant
standalone: true - Removes the
standalone: trueproperty from Angular component, directive, and pipe decorators since standalone is the default in Angular 19+.
- Remove redundant
- org.openrewrite.angular.migration.remove-static-false
- Remove
static: falsefrom view queries - Removes
static: falsefrom@ViewChild,@ContentChild,@ViewChildren, and@ContentChildrendecorators. In Angular 9 with Ivy,static: falsebecame the default behavior, making the explicit option unnecessary.
- Remove
- org.openrewrite.angular.migration.remove-zone-js-polyfill
- Remove zone.js polyfill from angular.json
- Removes zone.js entries from the
polyfillsarray inangular.json. Angular 20 supports zoneless change detection viaprovideZonelessChangeDetection(), making the zone.js polyfill unnecessary.
- org.openrewrite.angular.migration.rename-after-render
- Rename
afterRendertoafterEveryRender - Renames
afterRendertoafterEveryRenderin imports and usages. TheafterRenderfunction was renamed toafterEveryRenderin Angular 20, and Angular provides no migration schematic for this change.
- Rename
- org.openrewrite.angular.migration.rename-check-no-changes
- Rename
provideExperimentalCheckNoChangesForDebugtoprovideCheckNoChangesForDebug - Renames
provideExperimentalCheckNoChangesForDebugtoprovideCheckNoChangesForDebugin imports and usages. The experimental API was promoted to developer preview in Angular 20.
- Rename
- org.openrewrite.angular.migration.rename-file
- Rename file
- Renames files matching a glob pattern to a new file name, preserving the directory.
- org.openrewrite.angular.migration.rename-pending-tasks
- Rename
ExperimentalPendingTaskstoPendingTasks - Renames
ExperimentalPendingTaskstoPendingTasksin imports and usages.ExperimentalPendingTaskswas renamed in Angular 19.
- Rename
- org.openrewrite.angular.migration.rename-zoneless-provider
- Rename
provideExperimentalZonelessChangeDetectiontoprovideZonelessChangeDetection - Renames
provideExperimentalZonelessChangeDetectiontoprovideZonelessChangeDetectionin imports and usages. The experimental API was promoted to developer preview in Angular 20.
- Rename
- org.openrewrite.angular.migration.replace-async-with-wait-for-async
- Replace
asyncwithwaitForAsync - Replaces the removed
asynctest helper from@angular/core/testingwithwaitForAsync. Theasyncfunction was deprecated in Angular 11 and removed in Angular 18.
- Replace
- org.openrewrite.angular.migration.replace-deep-zone-js-imports
- Replace deep
zone.jsimports - Replaces legacy deep imports from
zone.jssuch aszone.js/dist/zoneorzone.js/bundles/zone-testing.jswith the standardzone.jsorzone.js/testingimports, in both TypeScript files andangular.jsonpolyfills. Deep imports are no longer allowed in Angular 17.
- Replace deep
- org.openrewrite.angular.migration.replace-http-client-module
- Replace
HttpClientModulewithprovideHttpClient() - Replaces deprecated
HttpClientModule,HttpClientJsonpModule,HttpClientXsrfModule, andHttpClientTestingModulewith their functional equivalents:provideHttpClient()with feature functions andprovideHttpClientTesting().
- Replace
- org.openrewrite.angular.migration.replace-initial-navigation
- Replace
initialNavigationoption values - Replaces deprecated
initialNavigationrouter option values:'legacy_enabled'andtruebecome'enabledBlocking','legacy_disabled'andfalsebecome'disabled', and'enabled'becomes'enabledNonBlocking'. The legacy values were removed in Angular 11;'enabled'was renamed in Angular 14.
- Replace
- org.openrewrite.angular.migration.replace-inject-flags
- Replace
InjectFlagswith options object - Replaces deprecated
InjectFlagsenum usage ininject()calls with the corresponding options object. For example,inject(MyService, InjectFlags.Optional)becomesinject(MyService, \{ optional: true \}).
- Replace
- org.openrewrite.angular.migration.replace-load-children-string
- Replace string-based
loadChildrenwith dynamicimport() - Converts the deprecated string-based
loadChildren: 'path#Module'syntax to dynamic imports:loadChildren: () => import('path').then(m => m.Module).
- Replace string-based
- org.openrewrite.angular.migration.replace-node-sass-with-sass
- Replace
node-sasswithsass - Replaces the deprecated
node-sasspackage withsass(Dart Sass). Angular 12 requires Dart Sass;node-sassis no longer supported.
- Replace
- org.openrewrite.angular.migration.replace-router-link-with-href
- Replace
RouterLinkWithHrefwithRouterLink - Replaces
RouterLinkWithHrefwithRouterLinkin imports and usages.RouterLinkWithHrefwas merged intoRouterLinkin Angular 16.
- Replace
- org.openrewrite.angular.migration.replace-testbed-get-with-inject
- Replace
TestBed.get()withTestBed.inject() - Replaces deprecated
TestBed.get()calls withTestBed.inject().TestBed.get()was deprecated in Angular 9 and removed in Angular 13.
- Replace
- org.openrewrite.angular.migration.replace-untyped-forms
- Replace form classes with untyped variants
- Renames
FormControl,FormGroup,FormArray, andFormBuilderto theirUntyped*equivalents in imports and usages. Angular 14 introduced strictly typed forms, requiring existing untyped usages to migrate to theUntyped*aliases. Classes used in parameterized type positions (e.g.FormGroup<T>) are left unchanged because the user already opted into typed forms.
- org.openrewrite.angular.migration.replace-validator-with-validators
- Replace
validator/asyncValidatorwith plural forms - Renames the deprecated singular
validatorandasyncValidatorproperty names tovalidatorsandasyncValidators(plural). Angular 10 deprecated the singular forms in favor ofAbstractControlOptions.
- Replace
- org.openrewrite.angular.migration.replace-view-encapsulation-native
- Replace
ViewEncapsulation.NativewithViewEncapsulation.ShadowDom - Replaces
ViewEncapsulation.NativewithViewEncapsulation.ShadowDom.ViewEncapsulation.Nativewas deprecated in Angular 6 and removed in Angular 11.
- Replace
- org.openrewrite.angular.migration.update-component-template-url
- Update component
templateUrl - Updates the
templateUrlproperty value in Angular@Componentdecorators. Useful for refactoring template file paths or standardizing path conventions.
- Update component
- org.openrewrite.angular.migration.update-tsconfig-module
- Update
tsconfig.jsonmodule settings for Ivy - Updates
compilerOptions.moduletoesnextandcompilerOptions.moduleResolutiontonodeintsconfig.json. Angular 9's Ivy compiler requires ES module format. Already-current values likees2020,node16,nodenext, orbundlerare left unchanged.
- Update
- org.openrewrite.angular.migration.update-tsconfig-target
- Update
tsconfig.jsontarget toes2017 - Updates the
compilerOptions.targetintsconfig.jsonfromes5,es2015, ores2016toes2017. Angular 13 dropped IE11 support and requires at least ES2017.
- Update
- org.openrewrite.angular.search.FindAngularComponent
- Find Angular component
- Locates usages of Angular components across the codebase including template elements and other references. If
componentNameisnull, finds all Angular components.
- org.openrewrite.angular.search.find-analyze-for-entry-components-usage
- Find deprecated
ANALYZE_FOR_ENTRY_COMPONENTSusage - Finds usages of the deprecated
ANALYZE_FOR_ENTRY_COMPONENTSinjection token from@angular/core.ANALYZE_FOR_ENTRY_COMPONENTSwas deprecated in Angular 9 and removed in Angular 13.
- Find deprecated
- org.openrewrite.angular.search.find-angular-decorator
- Find Angular decorators
- Finds all Angular decorators like @Component, @Directive, @Injectable, etc.
- org.openrewrite.angular.search.find-angular-http-usage
- Find removed
@angular/httpusage - Finds imports from the
@angular/httpmodule, which was deprecated in Angular 5 and removed in Angular 8. Use@angular/common/http(HttpClient,HttpClientModule) instead.
- Find removed
- org.openrewrite.angular.search.find-animation-driver-matches-element
- Find
AnimationDriver.matchesElementusage - Finds imports of
AnimationDriverfrom@angular/animations/browser, which had itsmatchesElementmethod removed in Angular 18.
- Find
- org.openrewrite.angular.search.find-async-test-helper-usage
- Find deprecated
asynctest helper usage - Finds usages of the deprecated
asynctest helper from@angular/core/testing. Theasyncfunction was deprecated in Angular 11 and should be replaced withwaitForAsync.
- Find deprecated
- org.openrewrite.angular.search.find-bare-module-with-providers
- Find
ModuleWithProviderswithout generic type - Finds imports of
ModuleWithProvidersfrom@angular/core. Starting in Angular 10,ModuleWithProvidersrequires a generic type parameter (e.g.ModuleWithProviders<MyModule>). Ensure all usages specify the module type.
- Find
- org.openrewrite.angular.search.find-browser-transfer-state-module-usage
- Find
BrowserTransferStateModuleusage - Finds usages of
BrowserTransferStateModulefrom@angular/platform-browserwhich was removed in Angular 16.TransferStatecan be used directly without this module.
- Find
- org.openrewrite.angular.search.find-common-module-usage
- Find
CommonModuleusage - Finds imports of
CommonModulefrom@angular/common. Since Angular 19, standalone components are the default andCommonModuleis no longer needed in componentimportsarrays. Built-in directives and pipes are available automatically.
- Find
- org.openrewrite.angular.search.find-compiler-factory-usage
- Find View Engine API usage
- Finds usages of View Engine APIs from
@angular/core(CompilerFactory,Compiler,CompilerOptions,ModuleWithComponentFactories,NgModuleFactory,NgModuleFactoryLoader) which were deprecated in Angular 13.
- org.openrewrite.angular.search.find-date-pipe-default-timezone-usage
- Find
DATE_PIPE_DEFAULT_TIMEZONEusage - Finds usages of
DATE_PIPE_DEFAULT_TIMEZONEwhich was deprecated in Angular 15. UseDATE_PIPE_DEFAULT_OPTIONSwith a\{timezone: '...'\}object value instead.
- Find
- org.openrewrite.angular.search.find-effect-timing-usage
- Find
effect()usage affected by Angular 19 timing changes - Finds
effect()calls from@angular/core. In Angular 19, effects triggered outside change detection now run as part of the change detection process instead of as a microtask, and effects triggered during change detection run earlier, before the component's template.
- Find
- org.openrewrite.angular.search.find-empty-projectable-nodes
- Find
createComponentcalls with emptyprojectableNodes - Finds
createComponent()calls that pass empty arrays inprojectableNodes. In Angular 19, passing an empty array now renders the defaultng-contentfallback content. To suppress fallback content, pass[document.createTextNode('')]instead.
- Find
- org.openrewrite.angular.search.find-fake-async-usage
- Find zone.js-dependent test helper usage
- Finds
fakeAsync(),tick(), andwaitForAsync()calls from@angular/core/testing. These zone.js-dependent test helpers are incompatible with Vitest, the default test runner in Angular 21. Migrate to native async/await patterns instead.
- org.openrewrite.angular.search.find-hammer-js-usage
- Find HammerJS usage
- Finds
HammerModuleimports and HammerJS references. Angular has deprecated HammerJS support and it will be removed in Angular 21.
- org.openrewrite.angular.search.find-i18n-usage
- Find i18n usage
- Finds i18n usage indicators: legacy i18n configuration in
angular.json(i18nLocale,i18nFile,i18nFormat,i18nMissingTranslation),$localizetagged template literals, and@angular/localizeimports. Projects with these markers need@angular/localizeinstalled andimport '@angular/localize/init'inpolyfills.tsfor Angular 9+.
- org.openrewrite.angular.search.find-karma-usage
- Find Karma test runner usage
- Finds Karma test runner configuration in package.json dependencies and angular.json test builder. Angular 21 replaces Karma with Vitest as the default test runner.
- org.openrewrite.angular.search.find-load-children-string-usage
- Find deprecated string-based
loadChildrenusage - Finds usages of the deprecated string-based
loadChildrensyntax (e.g.loadChildren: './path/to/module#ModuleName'). String-based lazy loading was deprecated in Angular 8 and removed in Angular 11. Use dynamic imports instead:loadChildren: () => import('./path/to/module').then(m => m.ModuleName).
- Find deprecated string-based
- org.openrewrite.angular.search.find-missing-injectable
- Find classes with DI dependencies but missing
@Injectable() - Finds classes that have constructor parameters (suggesting dependency injection) but lack an
@Injectable()or other Angular class-level decorator. Angular 9 with Ivy requires an explicit@Injectable()decorator for all services that use dependency injection.
- Find classes with DI dependencies but missing
- org.openrewrite.angular.search.find-ng-class-usage
- Find
NgClassusage - Finds imports of
NgClassfrom@angular/common. ThengClassdirective is soft deprecated in Angular 21 in favor of native[class.*]bindings.
- Find
- org.openrewrite.angular.search.find-ng-style-usage
- Find
NgStyleusage - Finds imports of
NgStylefrom@angular/common. ThengStyledirective is soft deprecated in Angular 21 in favor of native[style.*]bindings.
- Find
- org.openrewrite.angular.search.find-path-match-type-usage
- Find
pathMatchroute properties that may need type narrowing - Finds
pathMatchproperty assignments in route configurations. In Angular 14, thepathMatchtype was narrowed fromstringto'full' | 'prefix'. Routes defined as plain objects without explicitRouteorRoutestyping may fail type checking.
- Find
- org.openrewrite.angular.search.find-platform-dynamic-server-usage
- Find
platformDynamicServerusage - Finds usages of the removed
platformDynamicServerAPI from@angular/platform-server. In Angular 18, replace withplatformServerand addimport '@angular/compiler'.
- Find
- org.openrewrite.angular.search.find-platform-webworker-usage
- Find removed
@angular/platform-webworkerusage - Finds imports from
@angular/platform-webworkerand@angular/platform-webworker-dynamic, which were removed in Angular 8 with no direct replacement.
- Find removed
- org.openrewrite.angular.search.find-platform-worker-usage
- Find
isPlatformWorkerUiandisPlatformWorkerAppusage - Finds usages of the removed
isPlatformWorkerUiandisPlatformWorkerAppAPIs from@angular/common. These were removed in Angular 18 with no replacement, as they served no purpose since the removal of the WebWorker platform.
- Find
- org.openrewrite.angular.search.find-preserve-fragment-usage
- Find deprecated
preserveFragmentusage - Finds usages of the deprecated
preserveFragmentnavigation option.preserveFragmentwas deprecated in Angular 4 and removed in Angular 11. Fragments are now preserved by default.
- Find deprecated
- org.openrewrite.angular.search.find-preserve-query-params-usage
- Find deprecated
preserveQueryParamsusage - Finds usages of the deprecated
preserveQueryParamsnavigation option.preserveQueryParamswas deprecated in Angular 4 and removed in Angular 11. UsequeryParamsHandling: 'preserve'instead.
- Find deprecated
- org.openrewrite.angular.search.find-provided-in-deprecated-usage
- Find deprecated
providedInvalues - Finds usages of
providedIn: 'any'andprovidedIn: NgModulein@InjectableandInjectionTokendeclarations. These were deprecated in Angular 15. UseprovidedIn: 'root'or add the service toNgModule.providersinstead.
- Find deprecated
- org.openrewrite.angular.search.find-reflective-injector-usage
- Find
ReflectiveInjectorusage - Finds usages of
ReflectiveInjectorwhich was removed in Angular 16. UseInjector.createas a replacement.
- Find
- org.openrewrite.angular.search.find-render-application-usage
- Find
renderApplicationusage - Finds usages of
renderApplicationfrom@angular/platform-server. In Angular 16 the signature changed: it no longer accepts a root component as the first argument. Use a bootstrapping function that returnsPromise<ApplicationRef>instead.
- Find
- org.openrewrite.angular.search.find-render-component-type-usage
- Find deprecated
RenderComponentTypeusage - Finds imports of the deprecated
RenderComponentTypefrom@angular/core.RenderComponentTypewas part of the View Engine API, deprecated in Angular 4, and removed in Angular 9.
- Find deprecated
- org.openrewrite.angular.search.find-render-module-factory-usage
- Find
renderModuleFactoryusage - Finds usages of
renderModuleFactoryfrom@angular/platform-serverwhich was removed in Angular 16. UserenderModuleinstead.
- Find
- org.openrewrite.angular.search.find-renderer-usage
- Find deprecated
Rendererusage - Finds imports of the deprecated
Rendererfrom@angular/core.Rendererwas deprecated in Angular 4 and removed in Angular 9. Users should useRenderer2instead.
- Find deprecated
- org.openrewrite.angular.search.find-resource-cache-provider-usage
- Find
RESOURCE_CACHE_PROVIDERusage - Finds usages of the removed
RESOURCE_CACHE_PROVIDERfrom@angular/platform-browser-dynamic. This unused API was removed in Angular 18.
- Find
- org.openrewrite.angular.search.find-root-renderer-usage
- Find deprecated
RootRendererusage - Finds imports of the deprecated
RootRendererfrom@angular/core.RootRendererwas part of the View Engine API, deprecated in Angular 4, and removed in Angular 9. UseRendererFactory2instead.
- Find deprecated
- org.openrewrite.angular.search.find-rxjs-compat-usage
- Find RxJS 5-style imports requiring
rxjs-compat - Finds imports using RxJS 5-style deep import paths (e.g.
rxjs/Observable,rxjs/add/operator/map) that require therxjs-compatpackage. These should be migrated to RxJS 6+ import paths before removingrxjs-compat.
- Find RxJS 5-style imports requiring
- org.openrewrite.angular.search.find-server-transfer-state-module-usage
- Find
ServerTransferStateModuleusage - Finds usages of the removed
ServerTransferStateModulefrom@angular/platform-server. In Angular 18,TransferStateworks without providing this module.
- Find
- org.openrewrite.angular.search.find-setup-testing-router-usage
- Find
setupTestingRouterusage - Finds usages of the removed
setupTestingRouterfunction from@angular/router/testing. This function was removed in Angular 17. UseRouterModule.forRootorprovideRouterto set up the Router for tests instead.
- Find
- org.openrewrite.angular.search.find-testability-pending-request-usage
- Find removed Testability pending request methods
- Finds imports of
Testabilityfrom@angular/core, which hadincreasePendingRequestCount,decreasePendingRequestCount, andgetPendingRequestCountremoved in Angular 18. These are now tracked with zones.
- org.openrewrite.angular.search.find-undecorated-angular-class
- Find undecorated classes with Angular features
- Finds classes that use Angular member decorators (
@Input,@Output,@ViewChild, etc.) or implement lifecycle hooks (ngOnInit,ngOnDestroy, etc.) but lack a class-level Angular decorator. Angular 9 with Ivy requires all classes using Angular features to have an explicit decorator.
- org.openrewrite.angular.search.find-with-no-dom-reuse-usage
- Find
withNoDomReuseusage - Finds usages of the removed
withNoDomReusefunction from@angular/platform-browser. This function was removed in Angular 17. To disable hydration, remove theprovideClientHydration()call from your providers or use thengSkipHydrationattribute on specific components.
- Find
- org.openrewrite.angular.search.find-wrapped-value-usage
- Find deprecated
WrappedValueusage - Finds usages of the deprecated
WrappedValuefrom@angular/core.WrappedValuewas deprecated in Angular 11 and removed in Angular 13.
- Find deprecated
- org.openrewrite.angular.search.find-zone-js-usage
- Find zone.js usage
- Finds zone.js imports and NgZone references. Angular 20 supports zoneless change detection via
provideZonelessChangeDetection(), making zone.js optional.
- org.openrewrite.primeng.AddPrimengProvider
- Add
providePrimeNGwith a detected theme preset to the root NgModule - Wires the v18 styled mode into an NgModule-based app by adding
providePrimeNG(\{ theme: \{ preset: <Preset> \} \})to the root@NgModule's providers array (detected by the presence of abootstrap:field). The preset is chosen by scanningangular.jsonfor aprimeng/resources/themes/<themeName>/theme.cssentry:lara-*maps to Lara,md-*/mdc-*to Material,nora/nanoto Nora, and any other v17 theme (mira, nova, saga, vela, soho, fluent, viva, rhea, tailwind, bootstrap4, arya, luna, ...) falls back to Aura. The matching imports forprovidePrimeNGand the chosen preset are added automatically. Also deletes the now-defunctprimeng/resourcesstyle entries fromangular.jsonso the build doesn't try to load missing files. Idempotent: skips files that already callprovidePrimeNG.
- Add
- org.openrewrite.primeng.MarkDeprecatedPrimengComponents
- Mark deprecated PrimeNG components with TODO comments
- For every TS file that imports a component / module deprecated in PrimeNG 18 (
TabMenu,Steps,InlineMessage,TabView,pDefer), prepends a TODO comment to the import describing the recommended v18 replacement and writes a row to theManualMigrationStepsdata table. The import itself is left intact — these modules still exist in v18 but their replacements have different APIs that require manual migration.
- org.openrewrite.primeng.MarkDeprecatedPrimengCssClasses
- Mark deprecated PrimeNG CSS classes with TODO comments
- For every HTML template that references a CSS class removed in PrimeNG 18 (
.p-link,.p-highlight,.p-fluid), inserts a<!-- TODO: ... -->comment immediately before the offending element and writes a row to theManualMigrationStepsdata table. The class itself is left in place — the replacements are context-dependent (component-specific selectors, the newfluidinput, etc.) and need a human or AI agent to apply.
- org.openrewrite.primeng.MarkDrawerSize
- Mark
<p-drawer>/<p-sidebar>sizeusages with TODO comments - Inserts an HTML
<!-- TODO: ... -->comment before any<p-drawer>or<p-sidebar>element that binds the removedsizeinput, and records the site in theManualMigrationStepsdata table. Both[size]="..."andsize="..."attribute forms are matched. The attribute is left untouched — the v18 replacement (responsive CSS via[style]/styleClass) depends on the desired layout and needs manual review.
- Mark
- org.openrewrite.primeng.MarkRemovedPrimengModules
- Mark imports of removed PrimeNG modules with TODO stubs
- For each
importof a PrimeNG module that no longer exists in v18 (primeng/chips,primeng/tristatecheckbox,primeng/messages,primeng/dataviewlayoutoptions), replaces the broken import statement with aconst <Name>: any = null;stub annotated by a TODO comment that describes the v18 replacement. Also strips the corresponding entries from@NgModuleimports,declarations, andexportsarrays since Angular's compiler rejectsnullvalues there. Each flagged site is also recorded in theManualMigrationStepsdata table so downstream tooling can enumerate the remaining work.
- org.openrewrite.primeng.MigrateMessagesToMessageLoop
- Migrate
<p-messages>to<p-message>with@forloop - Rewrites
<p-messages [value]="expr">…</p-messages>to@for (msg of expr; track msg) \{ <p-message [severity]="msg.severity" [text]="msg.detail"></p-message> \}. TheMessagescomponent was removed in PrimeNG 18 in favor of looping over the newMessagecomponent. Each rewritten site is recorded in theManualMigrationStepsdata table for follow-up review.
- Migrate
- org.openrewrite.primeng.MigratePFluidToWrapper
- Migrate
.p-fluidto<p-fluid>wrapper - Rewrites
<div class="…p-fluid…">…</div>to<p-fluid class="…">…</p-fluid>and adds aFluidModuleimport fromprimeng/fluidto the corresponding component file. PrimeNG 18 removed the.p-fluidCSS class; the<p-fluid>wrapper component is its replacement.
- Migrate
- org.openrewrite.primeng.MigratePrimeNGSignalAssignments
- Migrate
PrimeNGconfig field assignments to.set() - In PrimeNG 18, fields on the
PrimeNGconfig service likeripple,inputStyle,inputVariant, andcspareWritableSignal<T>rather than plain fields. Direct assignment (service.ripple = true) no longer compiles. This recipe rewrites such assignments to use the signal'sset()method (service.ripple.set(true)) when the file importsPrimeNGfromprimeng/config.
- Migrate
- org.openrewrite.primeng.MigratePrimeNgConfigToPrimeNG
- Migrate
PrimeNGConfigtoPrimeNG - Renames the
PrimeNGConfigimport fromprimeng/apitoPrimeNGfromprimeng/config, renames all identifier usages, and flags injection sites that should be migrated toprovidePrimeNG()in application providers.
- Migrate
- org.openrewrite.primeng.RenameCalendarToDatePicker
- Rename
CalendartoDatePicker - Renames
CalendarandCalendarModuleimports fromprimeng/calendartoDatePickerandDatePickerModulefromprimeng/datepicker, and updates all identifier usages. The old names are deprecated in PrimeNG 18.
- Rename
- org.openrewrite.primeng.RenameDropdownToSelect
- Rename
DropdowntoSelect - Renames
DropdownandDropdownModuleimports fromprimeng/dropdowntoSelectandSelectModulefromprimeng/select, and updates all identifier usages. The old names are deprecated in PrimeNG 18.
- Rename
- org.openrewrite.primeng.RenameInputSwitchToToggleSwitch
- Rename
InputSwitchtoToggleSwitch - Renames
InputSwitchandInputSwitchModuleimports fromprimeng/inputswitchtoToggleSwitchandToggleSwitchModulefromprimeng/toggleswitch, and updates all identifier usages. The old names are deprecated in PrimeNG 18.
- Rename
- org.openrewrite.primeng.RenameMessageInterface
- Rename
Messageinterface toToastMessageOptions - Renames the
Messageinterface import fromprimeng/apitoToastMessageOptionsand updates all identifier usages. TheMessageinterface was renamed in PrimeNG 18 due to name collision with theMessagecomponent.
- Rename
- org.openrewrite.primeng.RenameOverlayPanelToPopover
- Rename
OverlayPaneltoPopover - Renames
OverlayPanelandOverlayPanelModuleimports fromprimeng/overlaypaneltoPopoverandPopoverModulefromprimeng/popover, and updates all identifier usages. The old names are deprecated in PrimeNG 18.
- Rename
- org.openrewrite.primeng.RenameSidebarToDrawer
- Rename
SidebartoDrawer - Renames
SidebarandSidebarModuleimports fromprimeng/sidebartoDrawerandDrawerModulefromprimeng/drawer, and updates all identifier usages. The old names are deprecated in PrimeNG 18.
- Rename
- org.openrewrite.primeng.RenameTemplateSelectors
- Rename PrimeNG selectors in HTML templates to their v18 equivalents
- Renames v17 PrimeNG component selectors in
.htmltemplates to their v18 names:<p-calendar>→<p-datepicker>,<p-dropdown>→<p-select>,<p-inputSwitch>→<p-toggleSwitch>,<p-overlayPanel>→<p-popover>,<p-sidebar>→<p-drawer>. Both opening and closing tags are rewritten.
- org.openrewrite.primeng.UpgradeComponentsTo18
- Upgrade PrimeNG components to 18
- Handles component renames, deprecations, and removals for PrimeNG 18. Renames Calendar to DatePicker, Dropdown to Select, InputSwitch to ToggleSwitch, OverlayPanel to Popover, and Sidebar to Drawer (TS imports + identifier usages + HTML selectors). Migrates the
Messagestemplate usage to the<p-message>+@forloop. Marks removed modules (Chips, TriStateCheckbox, Messages, DataViewLayoutOptions, pAnimate) with TODO stubs, marks deprecated components (TabMenu, Steps, InlineMessage, TabView, pDefer) with TODO comments on their imports, and marks deprecated CSS classes (.p-link,.p-highlight,.p-fluid) and<p-drawer>/<p-sidebar>sizeusages with HTML TODO comments. All marked sites are written to theManualMigrationStepsdata table.
- org.openrewrite.primeng.UpgradeTo18
- Upgrade to PrimeNG 18
- Migrates PrimeNG 17.x applications to PrimeNG 18. Renames components, migrates
PrimeNGConfigtoPrimeNG(with signal-backed setters), comments out the obsoleteprimeng/resourcesstyle entries inangular.json, wiresprovidePrimeNG(\{ theme: \{ preset: Aura \} \})into the root NgModule and adds@primeng/themestopackage.json. Anything that can't be deterministically migrated (removed-and-no-direct-replacement components, deprecated CSS classes, structural template changes) gets a TODO comment in source plus a row in theManualMigrationStepsdata table for an agent or human to finish.
rewrite-cryptography
- io.moderne.cryptography.FindCryptoVulnerabilitiesPipeline
- Find cryptographic vulnerability chains
- Detects cryptographic vulnerabilities that span multiple operations, tracking flow from hardcoded algorithms through key material to encryption operations.
- io.moderne.cryptography.FindDirectSSLConfigurationEditing
- Find direct SSL configuration editing
- Detects direct configuration of protocols or cipher suites on SSL objects like SSLSocket, SSLServerSocket, or SSLEngine. This pattern makes SSL/TLS configuration scattered throughout the codebase and prevents centralized security policy management, hindering crypto-agility.
- io.moderne.cryptography.FindHardcodedAlgorithmChoice
- Find hardcoded algorithm choices
- Detects hardcoded algorithm choices in cryptographic operations. Hardcoded algorithms prevent easy migration to stronger or quantum-resistant algorithms when needed. This is a critical crypto-agility issue that makes systems vulnerable to future attacks.
- io.moderne.cryptography.FindHardcodedAlgorithmParameters
- Find hardcoded algorithm-specific parameters
- Detects hardcoded algorithm-specific parameters like RSA public exponents or EC curve parameters. These hardcoded values prevent algorithm agility and may use weak or non-standard parameters that compromise security.
- io.moderne.cryptography.FindHardcodedCertificate
- Find hardcoded certificates
- Detects hardcoded certificates in the code, including certificates that are hardcoded as strings and used to generate X509Certificate instances via CertificateFactory. Hardcoded certificates can lead to security issues when they expire or need to be revoked.
- io.moderne.cryptography.FindHardcodedCiphersuiteChoice
- Find hardcoded cipher suite choices
- Detects hardcoded cipher suite choices used in SSL/TLS configurations. Hardcoded cipher suites prevent easy updates when cipher suites become weak or need to be changed for compliance reasons.
- io.moderne.cryptography.FindHardcodedKeyLength
- Find hardcoded cryptographic key lengths
- Detects hardcoded key lengths used in cryptographic operations like KeyGenerator.init(), KeyPairGenerator.initialize(), RSAKeyGenParameterSpec, and PBEKeySpec. Hardcoded key lengths reduce flexibility and may not meet changing security requirements.
- io.moderne.cryptography.FindHardcodedPrivateKey
- Find hardcoded private keys
- Detects hardcoded private keys in the code, including PEM-encoded keys that flow into KeyFactory.generatePrivate() calls. Hardcoded private keys are a severe security vulnerability as they compromise the entire cryptographic system.
- io.moderne.cryptography.FindHardcodedProtocolChoice
- Find hardcoded SSL/TLS protocol choices
- Detects hardcoded SSL/TLS protocol choices like 'TLSv1.2', 'SSLv3' used in SSLContext.getInstance() and setProtocols() calls. Hardcoded protocols prevent easy updates when protocols become obsolete or insecure.
- io.moderne.cryptography.FindHardcodedProviderName
- Find hardcoded cryptographic provider names
- Detects hardcoded cryptographic provider names (like 'BC', 'SunJCE') used in getInstance() calls. Hardcoding provider names reduces portability and can cause issues when the provider is not available on different systems.
- io.moderne.cryptography.FindProgrammaticProviderEditing
- Find programmatic security provider editing
- Detects programmatic modifications to the Java Security Provider list through Security.addProvider(), insertProviderAt(), or removeProvider() calls. Modifying providers at runtime makes the security configuration unpredictable and prevents crypto-agility by hardcoding provider dependencies.
- io.moderne.cryptography.FindRSAKeyGenParameters
- Find RSA key generation parameters
- Finds RSAKeyGenParameterSpec instantiations and extracts their parameter values into a data table.
- io.moderne.cryptography.FindSSLContextSetDefault
- Find SSLContext.setDefault() usage
- Detects calls to SSLContext.setDefault() which sets the system-wide default SSL context. This is problematic because it affects all SSL/TLS connections in the JVM, potentially overriding security configurations set by other parts of the application or libraries. It also prevents crypto-agility as the configuration becomes global.
- io.moderne.cryptography.FindSSLSocketParameters
- Find SSL socket configuration parameters
- Finds SSLSocket setter method invocations and extracts their parameter values into a data table.
- io.moderne.cryptography.FindSecurityModifications
- Find Security class modifications
- Finds invocations of java.security.Security methods that modify security configuration such as removeProvider, addProvider, insertProviderAt, setProperty, and removeProperty.
- io.moderne.cryptography.FindSecuritySetProperties
- Find
Security.setProperty(..)calls for certain properties - There is a defined set of properties that should not be set using
Security.setProperty(..)as they can lead to security vulnerabilities.
- Find
- io.moderne.cryptography.PostQuantumCryptography
- Post quantum cryptography
- This recipe searches for instances in code that may be impacted by post quantum cryptography. Applications may need to support larger key sizes, different algorithms, or use crypto agility to handle the migration. The recipe includes detection of hardcoded values that affect behavior in a post-quantum world, programmatic configuration that may prevent algorithm changes, and general cryptographic usage patterns that should be reviewed.
rewrite-devcenter
- io.moderne.devcenter.AngularVersionUpgrade
- Move to a later Angular version
- Determine the current state of a repository relative to a desired Angular version upgrade.
- io.moderne.devcenter.ApacheDevCenter
- DevCenter for Apache
- A DevCenter that tracks the latest Apache Maven parent POM versions and applies best practices.
- io.moderne.devcenter.ApacheMavenBestPractices
- Apache Maven best practices
- A collection of recipes that apply best practices to Maven POMs. Some of these recipes affect build stability, so they are reported as security issues in the DevCenter card.
- io.moderne.devcenter.ApacheMavenDevCenter
- DevCenter for Apache Maven
- A DevCenter that tracks the latest Apache Maven parent POM versions and applies best practices. This DevCenter includes recipes to upgrade the parent POMs of Apache Maven, as well as a collection of best practices for Maven POMs.
- io.moderne.devcenter.BucketedMetricCard
- DevCenter card from a data table column
- Read rows from a previously emitted data table, aggregate a numeric column across all rows for this repository, and bucket the result into ordinal DevCenter measures.
- io.moderne.devcenter.BuildToolCard
- Build tool
- Track build tool versions across repositories.
- io.moderne.devcenter.BuildToolStarter
- DevCenter for Gradle and Maven
- Track and automate upgrades for Gradle, Maven, and Java versions.
- io.moderne.devcenter.CSharpVersionUpgrade
- Move to a later .NET version
- Determine the current state of a repository relative to a desired .NET version upgrade.
- io.moderne.devcenter.ClassCohesionDevCenter
- Class cohesion DevCenter
- A DevCenter that finds class quality metrics for repositories and buckets the average LCOM4 (Lack of Cohesion of Methods, version 4) into HIGH / MEDIUM / LOW cohesion categories.
- io.moderne.devcenter.DependencyVulnerabilityCheck
- Vulnerabilities status
- Determine the current state of a repository relative to its vulnerabilities.
- io.moderne.devcenter.DevCenterAngularStarter
- DevCenter for Angular
- A default DevCenter configuration for Angular repositories. Track Angular version adoption across your organization.
- io.moderne.devcenter.DevCenterCSharpStarter
- DevCenter for C#
- A default DevCenter configuration for C# repositories. Track .NET version adoption across your organization.
- io.moderne.devcenter.DevCenterKotlin
- DevCenter Kotlin
- This is a DevCenter helping you to track general Kotlin Modernisations.
- io.moderne.devcenter.DevCenterNodeStarter
- DevCenter for Node.js
- A default DevCenter configuration for Node.js repositories. Track Node.js version adoption across your organization.
- io.moderne.devcenter.DevCenterPythonStarter
- DevCenter for Python
- A default DevCenter configuration for Python repositories. Track Python version adoption across your organization.
- io.moderne.devcenter.DevCenterStarter
- DevCenter
- This is a default DevCenter configuration that can be used as a starting point for your own DevCenter configuration. It includes a combination of upgrades, migrations, and security fixes. You can customize this configuration to suit your needs. For more information on how to customize your DevCenter configuration, see the DevCenter documentation.
- io.moderne.devcenter.FindOrganizationStatistics
- Find organization statistics
- Counts lines of code per repository for organization-level statistics.
- io.moderne.devcenter.GroovyVersionUpgrade
- Move to a later Groovy version
- Determine the current state of a repository relative to a desired Groovy version upgrade.
- io.moderne.devcenter.JUnitJupiterUpgrade
- Move to JUnit 6
- Move to JUnit Jupiter.
- io.moderne.devcenter.JavaVersionUpgrade
- Move to a later Java version
- Determine the current state of a repository relative to a desired Java version upgrade.
- io.moderne.devcenter.KotlinVersionUpgrade
- Move to a later Kotlin version
- Determine the current state of a repository relative to a desired Kotlin version upgrade.
- io.moderne.devcenter.LibraryUpgrade
- Library upgrade
- Determine the current state of a repository relative to a desired library upgrade.
- io.moderne.devcenter.NodeVersionUpgrade
- Move to a later Node.js version
- Determine the current state of a repository relative to a desired Node.js version upgrade.
- io.moderne.devcenter.ParentPomUpgrade
- Parent POM upgrade
- Determine the current state of a repository relative to a desired parent POM upgrade.
- io.moderne.devcenter.PythonVersionUpgrade
- Move to a later Python version
- Determine the current state of a repository relative to a desired Python version upgrade.
- io.moderne.devcenter.QuarkusDevCenter
- DevCenter for Quarkus
- A DevCenter that tracks the latest Quarkus framework versions and applies best practices. This DevCenter includes recipes to upgrade Quarkus versions, migrate from deprecated APIs, and ensure compatibility with the latest Java versions and testing frameworks.
- io.moderne.devcenter.ReportAsSecurityIssues
- Report as security issues
- Look for results produced by recipes in the same recipe list that this recipe is part of, and report them as security issues in DevCenter.
- io.moderne.devcenter.ScalaVersionUpgrade
- Move to a later Scala version
- Determine the current state of a repository relative to a desired Scala version upgrade.
- io.moderne.devcenter.SecurityStarter
- OWASP top ten
- This recipe is a starter card to reveal common OWASP Top 10 issues in your source code. You can customize this configuration to suit your needs. For more information on how to customize your DevCenter configuration, see the DevCenter documentation.
- io.moderne.devcenter.UpgradeApacheParent
- Upgrade Apache Parent POM
- Upgrades the Apache parent POM to the latest version.
- io.moderne.devcenter.UpgradeMavenParent
- Upgrade Apache Maven Parent
- Upgrades the Apache Maven parent POM to the latest version.
- io.moderne.devcenter.UpgradeMavenPluginsParent
- Upgrade Maven Plugins Parent
- Upgrades the Apache Maven parent POM to the latest version.
- io.moderne.devcenter.UpgradeMavenSharedParent
- Upgrade Maven Shared Parent
- Upgrades the Apache Maven parent POM to the latest version.
- io.moderne.devcenter.UpgradeQuarkus3_x
- Upgrade to Quarkus 3.26
- Upgrades Quarkus dependencies to version 3.26.x, including core, extensions, and tooling.
- io.moderne.devcenter.UpgradeQuarkusUniverseBom
- Upgrade Quarkus Universe BOM
- Upgrades the Quarkus Universe BOM parent to the latest version.
- io.moderne.devcenter.VulnerabilitiesDevCenter
- DevCenter for Vulnerability Management
- Recipes to analyze and manage dependency vulnerabilities using Moderne DevCenter.
rewrite-dropwizard
- io.moderne.java.dropwizard.MigrateToDropwizard5
- Migrate to Dropwizard 5.0.x from 4.x
- Apply changes required to upgrade a Dropwizard 4.x application to 5.0.x. This includes upgrading dependencies, removing deprecated configuration options, and migrating Jetty handler implementations. Includes required migrations to Java 17, Jakarta EE 10, JUnit 5, Jackson 2.x, and Hibernate 6.6. See the upgrade guide.
- io.moderne.java.dropwizard.boot.MigrateApplicationRunMethod
- Migrate Dropwizard Application.run() to SpringApplication.run()
- Replaces the
new MyApp().run(args)pattern in the main method withSpringApplication.run(MyApp.class, args).
- io.moderne.java.dropwizard.boot.MigrateDropwizardToSpringBoot3
- Migrate Dropwizard to Spring Boot 3
- Migrate a Dropwizard application to Spring Boot 3. First applies the Dropwizard to Spring Boot 2.7 migration, then adds managed lifecycle and health check migrations on top.
- io.moderne.java.dropwizard.boot.annotation.AddClassAnnotationIfAnnotationExists
- Add annotation if target annotation exists
- Adds an annotation to a class if it already has a specified target annotation.
- io.moderne.java.dropwizard.boot.annotation.AddClassAnnotationIfSuperTypeExists
- Add annotation if target supertype exists
- Adds an annotation to a class if it extends or implements a specified target type.
- io.moderne.java.dropwizard.boot.datasource.RemoveDataSourceFactoryBuildChain
- Replace DataSourceFactory build chain with @Autowired DataSource
- Replaces
DataSourceFactory.build(MetricRegistry, String)variable declarations with@Autowired DataSourcefields. Spring Boot auto-configures the DataSource fromspring.datasource.*properties. Note: connection pool metrics previously wired viaMetricRegistryrequirespring-boot-starter-actuatorfor equivalent observability.
- io.moderne.java.dropwizard.boot.datasource.RemoveLifecycleManageCalls
- Remove Dropwizard lifecycle.manage() calls
- Removes
environment.lifecycle().manage()calls. Spring Boot manages bean lifecycle automatically through its IoC container.
- io.moderne.java.dropwizard.boot.general.RemoveMethodsByPackage
- Remove methods referencing specified package
- Removes any method that has a return type or parameter type from the specified package.
- io.moderne.java.dropwizard.boot.general.RemoveVariablesByPackage
- Remove class variables matching package filter
- Removes variable declarations whose type belongs to the specified package.
- io.moderne.java.dropwizard.boot.health.MigrateHealthCheckMethod
- Migrate Dropwizard health check Result calls and wrap exceptions
- Transforms
Result.healthy()/Result.unhealthy()calls toHealth.up().build()/Health.down().build()and wraps throwingcheck()methods in try-catch.
- io.moderne.java.dropwizard.boot.jackson.ReplaceJacksonNewObjectMapper
- Replace
Jackson.newObjectMapper()withnew ObjectMapper().findAndRegisterModules() - Replaces Dropwizard's
Jackson.newObjectMapper()withnew ObjectMapper().findAndRegisterModules(), which provides equivalent module auto-discovery using the standard Jackson SPI mechanism.
- Replace
- io.moderne.java.dropwizard.boot.lifecycle.MigrateManagedLifecycle
- Add lifecycle annotations to Dropwizard Managed methods
- Adds
@PostConstructtostart()and@PreDestroytostop()on classes implementingio.dropwizard.lifecycle.Managed.
- io.moderne.java.dropwizard.boot.method.ChangeSuperType
- Change supertype
- Changes the supertype of a class, optionally converting from extends to implements.
- io.moderne.java.dropwizard.boot.method.RemoveSuperTypeByType
- Remove supertype by fully qualified name
- Removes a specified type from class extends or implements clauses.
- io.moderne.java.dropwizard.boot.method.RemoveUnnecessaryOverride
- Remove unnecessary
@Overrideannotations - Removes
@Overrideannotations from methods that don't actually override or implement any method. This helps maintain clean code by removing incorrect annotations that could be misleading.
- Remove unnecessary
- io.moderne.java.dropwizard.boot.method.RemoveUnnecessarySuperCalls
- Remove
supercalls when the class does not extend another class - Removes calls to
super(...)orsuper.someMethod(...)if the class does not have a real superclass besidesjava.lang.Object.
- Remove
- io.moderne.java.dropwizard.boot.test.AddSpringBootTestForDropwizardAppExtension
- Add
@SpringBootTestto classes usingDropwizardAppExtension - Adds
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)to test classes that contain aDropwizardAppExtensionfield, when no Spring test annotation is already present.
- Add
- io.moderne.java.dropwizard.boot.test.DropwizardRulesJUnit4ToSpringBoot
- Replace Dropwizard rules with Spring Boot test configuration
- Remove Dropwizard JUnit4 rules and add Spring Boot test annotations and extensions.
- io.moderne.java.dropwizard.boot.test.MethodLambdaExtractor
- Inline lambda body from matched method invocations
- Extracts the body of lambda expressions passed to matched method invocations and inlines them into the surrounding code.
- io.moderne.java.dropwizard.boot.test.MockitoVariableToMockBean
- Convert Mockito mock() to @MockBean
- Converts static final Mockito mock fields to Spring Boot @MockBean fields.
- io.moderne.java.dropwizard.boot.test.ReplaceDropwizardApplicationWithAutowired
- Replace
DropwizardAppExtension.getApplication()with@Autowiredapplication field - Replaces calls to
DropwizardAppExtension.getApplication()with a reference to a new@Autowired <AppType> applicationfield on the enclosing class. The application type is extracted from the constructor's first argument (new DropwizardAppExtension<>(TestApp.class, ...)); skips the rewrite if not resolvable. The application class must be a top-level class.
- Replace
- io.moderne.java.dropwizard.boot.test.ReplaceDropwizardConfigurationWithAutowired
- Replace
DropwizardAppExtension.getConfiguration()with@Autowiredconfiguration field - Replaces calls to
DropwizardAppExtension.getConfiguration()with a reference to a new@Autowired <ConfigType> configurationfield on the enclosing class. The configuration type is extracted fromDropwizardAppExtension<ConfigType>generic parameter; skips the rewrite if the type is raw, wildcard, or otherwise unresolvable. The configuration class must be a top-level class.
- Replace
- io.moderne.java.dropwizard.boot.test.ReplaceMethodInvocationWithAnnotatedField
- Replace a method invocation with a reference to an annotated field
- For each class containing an invocation matching the configured method pattern, introduces an annotated field of the requested type and rewrites every matching invocation in that class to reference the new field. If a field with the same annotation and type already exists, its name is reused.
- io.moderne.java.dropwizard.boot.test.TransformDropwizardRuleInvocations
- Convert Dropwizard test rule calls to RestTemplate
- Transforms Dropwizard AppRule and ResourceTestRule testing calls to their equivalent RestTemplate calls.
- io.moderne.java.dropwizard.dw5.MigrateJettyHandlerSignature
- Migrate Jetty
AbstractHandlerto Jetty 12Handler.Abstract - Migrates custom Jetty handler implementations from Jetty 11's
AbstractHandler(used in Dropwizard 4.x) to Jetty 12'sHandler.Abstract(used in Dropwizard 5.x). This changes thehandlemethod signature and updatesbaseRequest.setHandled(true)to useCallbackand returntrue.
- Migrate Jetty
rewrite-elastic
- io.moderne.elastic.elastic9.ChangeApiNumericFieldType
- Change numeric field type with conversion
- Adds conversion methods with null checks for numeric type changes in Elasticsearch 9 API.
- io.moderne.elastic.elastic9.ChangeApiNumericFieldTypes
- Change numeric field types for Elasticsearch 9
- Handles changes between different numeric types (
LongtoInteger,inttoLong...) in Elasticsearch 9 API responses by adding appropriate conversion methods with null checks.
- io.moderne.elastic.elastic9.MigrateDenseVectorElementType
- Migrate DenseVectorProperty.elementType from String to DenseVectorElementType enum
- In Elasticsearch 9,
DenseVectorProperty.elementType()returnsDenseVectorElementTypeenum instead ofString, and the builder methodelementType(String)now accepts the enum type. This recipe handles both builder calls and getter calls.
- io.moderne.elastic.elastic9.MigrateDenseVectorSimilarity
- Migrate DenseVectorProperty.similarity from String to DenseVectorSimilarity enum
- In Elasticsearch 9,
DenseVectorProperty.similarity()returnsDenseVectorSimilarityenum instead ofString, and the builder methodsimilarity(String)now accepts the enum type. This recipe handles both builder calls and getter calls.
- io.moderne.elastic.elastic9.MigrateMatchedQueries
- Migrate
matchedQueriesfrom List to Map - In Elasticsearch Java Client 9.0,
Hit.matchedQueries()changed from returningList<String>toMap<String, Double>. This recipe migrates the usage by adding.keySet()for iterations and usingnew ArrayList<>(result.keySet())for assignments.
- Migrate
- io.moderne.elastic.elastic9.MigrateScriptSource
- Migrate script source from String to Script/ScriptSource
- Migrates
Script.source(String)calls to useScriptSource.scriptString(String)wrapper in Elasticsearch Java client 9.x.
- io.moderne.elastic.elastic9.MigrateSpanTermQueryValue
- Migrate
SpanTermQuery.value()from String to FieldValue - In Elasticsearch 9,
SpanTermQuery.value()returns aFieldValueinstead ofString. This recipe updates calls to handle the new return type by checking if it's a string and extracting the string value.
- Migrate
- io.moderne.elastic.elastic9.MigrateToElasticsearch9
- Migrate from Elasticsearch 8 to 9
- This recipe performs a comprehensive migration from Elasticsearch 8 to Elasticsearch 9, addressing breaking changes, API removals, deprecations, and required code modifications.
- io.moderne.elastic.elastic9.RenameApiField
- Rename
Elasticsearch valueBody()methods - In Elasticsearch Java Client 9.0, the generic
valueBody()method andvalueBody(...)builder methods have been replaced with specific getter and setter methods that better reflect the type of data being returned. Similarly, forGetRepositoryResponse, theresultfield also got altered torepositories.
- Rename
- io.moderne.elastic.elastic9.RenameApiFields
- Rename API fields for Elasticsearch 9
- Renames various API response fields from
valueBodyto align with Elasticsearch 9 specifications.
- io.moderne.elastic.elastic9.UseNamedValueParameters
- Use NamedValue parameters instead of Map
- Migrates
indicesBoostanddynamicTemplatesparameters fromMaptoNamedValuein Elasticsearch Java client 9.x.
rewrite-hibernate
- io.moderne.hibernate.MigrateToHibernate40
- Migrate to Hibernate 4.0.x
- This recipe will apply changes commonly needed when migrating from Hibernate 3.x to 4.0.x, including migration of collection annotations to their JPA 2.0 equivalents.
- io.moderne.hibernate.MigrateToHibernate60
- Migrate to Hibernate 6.0.x (Moderne Edition)
- This recipe will apply changes commonly needed when migrating to Hibernate 6.0.x.
- io.moderne.hibernate.MigrateToHibernate66
- Migrate to Hibernate 6.6.x (Moderne Edition)
- This recipe will apply changes commonly needed when migrating to Hibernate 6.6.x.
- io.moderne.hibernate.MigrateToHibernate70
- Migrate to Hibernate 7.0.x (Moderne Edition)
- This recipe will apply changes commonly needed when migrating to Hibernate 7.0.x.
- io.moderne.hibernate.MigrateToHibernate71
- Migrate to Hibernate 7.1.x (Moderne Edition)
- This recipe will apply changes commonly needed when migrating to Hibernate 7.0.x.
- io.moderne.hibernate.MigrateToHibernate72
- Migrate to Hibernate 7.2.x
- This recipe will apply changes commonly needed when migrating to Hibernate 7.2.x.
- io.moderne.hibernate.search.FindJPQLDefinitions
- Find JPQL definitions
- Find Java Persistence Query Language definitions in the codebase.
- io.moderne.hibernate.update40.IndexHqlAnnotationPositionalParameters
- Index HQL/JPQL positional parameters in annotations
- Replaces unindexed
?positional parameters with indexed?1,?2, etc. in an HQL/JPQL query string held in an annotation attribute matching the given pattern.
- io.moderne.hibernate.update40.IndexHqlMethodPositionalParameters
- Index HQL/JPQL positional parameters in method calls
- Replaces unindexed
?positional parameters with indexed?1,?2, etc. in an HQL/JPQL query string passed as the first argument of a method matching the given pattern.
- io.moderne.hibernate.update40.MigrateJoinTableToCollectionTable
- Migrate
@JoinTableto@CollectionTablefor element collections - Replaces
@JoinTablewith@CollectionTablewhen used alongside@CollectionOfElementsor@ElementCollection.@CollectionTableis the JPA 2.0 standard for defining the table that stores element collections. WheninverseJoinColumnsis present, its column name is preserved as a@Columnannotation.
- Migrate
- io.moderne.hibernate.update60.MigrateHibernateCriteriaToJpaCriteria
- Migrate Hibernate Criteria API to JPA Criteria API
- Migrates code using the legacy Hibernate Criteria API (org.hibernate.Criteria, org.hibernate.criterion.) to the JPA Criteria API (jakarta.persistence.criteria.). Handles common patterns including Restrictions (with and/or), Order, Projections, list(), and uniqueResult().
- io.moderne.hibernate.update60.MigrateRemovedUuidTypes
- Migrate removed Hibernate UUID
@Typeto@JdbcTypeCode - Hibernate 6.x removed
UUIDCharType,UUIDBinaryTypeandPostgresUUIDType. Replace@Typeannotations referencing these with@JdbcTypeCodeand the correspondingSqlTypesconstant.
- Migrate removed Hibernate UUID
- io.moderne.hibernate.update66.FixConflictingClassTypeAnnotations
- Fix conflicting class type annotation Hibernate 6.6
- Since Hibernate 6.6 a mapped class can have either
@MappedSuperclassor@Embeddable, or@Entity. This recipe removes@Entityfrom classes annotated with@MappedSuperclassor@Embeddable. For the moment die combination of@MappedSuperclassor@Embeddableis advised to migrate to Single Table Inheritance but still accepted and therefore stays.
- io.moderne.hibernate.update66.MigrateCascadeTypes
- Migrate Hibernate CascadeType constants
- Moving away from deprecated Hibernate CascadeType constants. CascadeType.SAVE_UPDATE -> CascadeType.PERSIST and/or CascadeType.MERGE, CascadeType.DELETE -> CascadeType.REMOVE.
- io.moderne.hibernate.update66.RemoveTableFromInheritedEntity
- Remove table from single table inherited entity
- For Single Table Inherited Entities Hibernate ignores the
@Tableannotation on child entities. From Version 6.6 it is considered an error.
- io.moderne.hibernate.update70.AddCascadePersistToIdMappedAssociations
- Migrate implicit cascade=PERSIST for @Id and @MapsId associations
- Hibernate used to automatically enable cascade=PERSIST for association fields annotated @Id or @MapsId. This was undocumented and unexpected behavior, and no longer supported in Hibernate 7. Existing code which relies on this behavior will be modified by addition of explicit cascade=PERSIST to the association fields.
- io.moderne.hibernate.update70.CompositeUserTypeSessionFactoryImplementor
- Remove leaking of SessionFactoryImplementor from
org.hibernate.usertype.CompositeUserTypeinvocations and implementations - Remove leaking of SessionFactoryImplementor from
org.hibernate.usertype.CompositeUserTypeinvocations and implementations.
- Remove leaking of SessionFactoryImplementor from
- io.moderne.hibernate.update70.FindNativeQueryRawEnumParameters
- Find native queries with enum parameters requiring SpEL conversion
- When using
@NativeQueryor@Query(nativeQuery = true), enum parameters are not automatically converted by JPA. This recipe finds native queries with raw enum bind parameters that need SpEL expressions like:#\{#status.name()\}or:#\{#status.ordinal()\}depending on how the enum is persisted.
- io.moderne.hibernate.update70.MigrateConfigurableToGeneratorCreationContext
- Migrate
Configurable.configure()to useGeneratorCreationContext - In Hibernate 7.0,
Configurable.configure()now takes aGeneratorCreationContextparameter instead ofServiceRegistry. This recipe migrates method signatures and call sites.
- Migrate
- io.moderne.hibernate.update70.MigrateIntegratorMethod
- Migrate Hibernate
Integrator#integratemethod - Migrate Hibernate
Integrator#integratemethod from deprecated signature to Hibernate 7 compatible signature. Changesintegrate(Metadata, SessionFactoryImplementor, SessionFactoryServiceRegistry)tointegrate(Metadata, BootstrapContext, SessionFactoryImplementor).
- Migrate Hibernate
- io.moderne.hibernate.update70.MigrateJdbcTypeToJdbcTypeCode
- Migrate
@JdbcTypeand legacy@Typeto@JdbcTypeCode - In Hibernate 7.0, various JDBC types were moved to internal packages. Use
@JdbcTypeCodewithSqlTypesconstants instead of@JdbcTypewith specific classes. Also rewrites@Type(LegacyType.class)references to deprecated Hibernate basic types (e.g.MaterializedBlobType,ImageType) into the equivalent@JdbcTypeCode(SqlTypes.X).
- Migrate
- io.moderne.hibernate.update70.MigrateJpqlTruncToDateCast
- Migrate JPQL
trunc()tocast(... as date) - Hibernate 7 maps the JPQL
trunc()function to numeric truncation only (SQL standard). For date truncation, single-argumenttrunc(expr)must be replaced withcast(expr as date).
- Migrate JPQL
- io.moderne.hibernate.update70.MigrateLockOptionsToDirectParameters
- Migrate LockOptions to direct parameters
- Migrates deprecated
LockOptionsusage to direct parameters in method calls. As of JPA 3.2 and Hibernate 7,LockMode,Timeout, andPessimisticLockScopeare passed directly tofind(),refresh(), andlock()methods instead of being wrapped in aLockOptionsobject.
- io.moderne.hibernate.update70.MigrateMetamodelImplementor
- Migrate
MetamodelImplementorto Hibernate 7.0 - In Hibernate 7.0,
MetamodelImplementorhas been split intoMappingMetamodelfor ORM-specific operations andJpaMetamodelfor JPA-standard operations. This recipe migrates the usage based on which methods are called.
- Migrate
- io.moderne.hibernate.update70.MigrateNaturalIdLoadAccess
- Migrate NaturalIdLoadAccess method calls
- Migrates NaturalIdLoadAccess#using(Object...) to using(Map.of(...)) variants for Hibernate 7.0.
- io.moderne.hibernate.update70.MigrateNaturalIdMultiLoadAccess
- Migrate NaturalIdMultiLoadAccess method calls
- Migrates NaturalIdMultiLoadAccess#compoundValue(Object...) to Map.of(...) variants for Hibernate 7.0.
- io.moderne.hibernate.update70.MigrateQueryToNativeQuery
- Migrate @Query to @NativeQuery for unsupported JPQL
- Converts Spring Data
@Queryannotations to@NativeQuerywhen the JPQL query contains patterns unsupported by Hibernate 7's stricter JPQL parser, such as multi-argumenttrunc(date, 'format').
- io.moderne.hibernate.update70.MigrateSessionInterface
- Migrate Session interface method calls
- Migrates code using deprecated Session interface methods to their Hibernate 7.0 replacements.
- io.moderne.hibernate.update70.MigrateSessionToDeferToJPA
- Migrate Session save/update/delete method calls
- Migrates code using deprecated Session load/get/refresh/save/update/delete methods to their Hibernate 7.0 replacements.
- io.moderne.hibernate.update70.MigrateSetFlushModeToSetQueryFlushMode
- Migrate
setFlushMode()tosetQueryFlushMode() - In Hibernate 7.0,
CommonQueryContract.setFlushMode(FlushModeType)has been replaced withsetQueryFlushMode(QueryFlushMode). This recipe migrates the method call and convertsFlushModeTypeparameters to theirQueryFlushModeequivalents.
- Migrate
- io.moderne.hibernate.update70.MigrateToHibernate7JFR
- Migrate to Hibernate 7 JFR APIs
- Migrates deprecated JFR integration APIs to their Hibernate 7 replacements.
EventManagerbecomesEventMonitorandHibernateMonitoringEventbecomesDiagnosticEvent.
- io.moderne.hibernate.update70.MigrateToTargetEmbeddable
- Migrate to @TargetEmbeddable
- Migrates code using removed @Target to to Hibernate 7.0's @TargetEmbeddable equivalent. Removes misused @Target annotations.
- io.moderne.hibernate.update70.RemoveUnnecessaryCastToSession
- Remove unnecessary cast to
SessionforSessionFactory.createEntityManager() - In Hibernate 7.0,
SessionFactory.createEntityManager()explicitly returns Session, making casts to Session unnecessary.
- Remove unnecessary cast to
- io.moderne.hibernate.update70.ReplaceHibernateWithJakartaAnnotations
- Replace hibernate annotations with Jakarta variants
- Tries to replaces annotations that have been removed in Hibernate 7.0 with its Jakarta equivalent, such as Table, @Where, @OrderBy, etc. If a annotation is used with arguments that do not have a direct replacement, the annotation is not replaced at all.
- io.moderne.hibernate.update70.ReplaceSessionLockRequest
- Replace Session.buildLockRequest with LockOptions
- Migrates Session.buildLockRequest(LockOptions.X) calls to use session.lock(entity, new LockOptions(LockMode.X)) in Hibernate 7.0.
- io.moderne.hibernate.update70.UnboxingTransactionTimeout
- Null safe Transaction#getTimeout()
- JPA 3.2 adds
#getTimeoutbut usesIntegerwhereas Hibernate has historically usedint. Note that this raises the possibility of aNullPointerExceptionduring migration if, e.g., performing direct comparisons on the timeout value against an in (auto unboxing). This recipe adds ternary operators whereTransaction#getTimeout()is used and a negative value will be used if thegetTimeout()resulted in a null value.
- io.moderne.hibernate.update70.UserTypeNullSafeGetSharedSessionContractImplementorRecipe
- Remove leaking of SharedSessionContractImplementor from
org.hibernate.usertype.UserTypeinvocations - Remove leaking of SharedSessionContractImplementor from
org.hibernate.usertype.UserTypeinvocations.
- Remove leaking of SharedSessionContractImplementor from
- io.moderne.hibernate.update70.UserTypeSharedSessionContractImplementor
- Remove leaking of SharedSessionContractImplementor from
org.hibernate.usertype.UserTypeimplementations - Remove leaking of SharedSessionContractImplementor from
org.hibernate.usertype.UserTypeimplementations.
- Remove leaking of SharedSessionContractImplementor from
rewrite-jasperreports
- io.moderne.jasperreports.MigrateExporterConfigToJasper6
- Update JasperReports exporter configuration
- Updates deprecated exporter parameter imports to the new configuration classes introduced in JasperReports 6. This includes migrating from parameter classes to configuration classes for PDF, HTML, CSV, and other exporters.
- io.moderne.jasperreports.MigrateXlsToXlsxExporter
- Migrate JRXlsExporter to JRXlsxExporter
- Migrates the deprecated
JRXlsExporterto the newJRXlsxExporterclass in JasperReports 6. Also updates related configuration classes from XLS to XLSX variants.
- io.moderne.jasperreports.UpgradeToJasperReports5
- Migrate to JasperReports 5.6.x
- Migrates JasperReports from 4.6.0 to 5.6.x. This recipe includes minimal breaking changes, allowing teams to test and validate the migration before proceeding to version 6.
- io.moderne.jasperreports.UpgradeToJasperReports6
- Migrate to JasperReports 6
- Migrates JasperReports from 5.x to 6.x with the new exporter API, XLS to XLSX move, and removal of Spring JasperReports views.
- io.moderne.jasperreports.v5.MigrateExporterSetParameter
- Migrate JasperReports exporter setParameter to new API
- Migrates deprecated
setParametercalls on JasperReports exporters to the new API usingsetExporterInputandsetExporterOutput.
- io.moderne.jasperreports.v5.MigratePrintServiceExporterConfiguration
- Migrate JRPrintServiceExporterParameter to SimplePrintServiceExporterConfiguration
- Migrates
JRPrintServiceExporterParametersetParameter calls to useSimplePrintServiceExporterConfiguration.
rewrite-java-application-server
- io.moderne.java.server.jboss.ConfigureGradleApplicationPlugin
- Configure Gradle
applicationplugin main class - Adds or updates
application \{ mainClass = '...' \}in a Gradle build script. Supports both Groovy DSL (build.gradle) and Kotlin DSL (build.gradle.kts).
- Configure Gradle
- io.moderne.java.server.jboss.ConfigureGradleFatJar
- Configure Gradle
jartask for fat JAR - Configures the Gradle
jartask to produce a self-contained fat JAR with all runtime dependencies bundled. Supports both Groovy DSL (build.gradle) and Kotlin DSL (build.gradle.kts).
- Configure Gradle
- io.moderne.java.server.jboss.ModuleHasJBossDescriptor
- Module has JBoss descriptor
- Searches for modules containing JBoss descriptor files (
jboss-web.xml,jboss-deployment-structure.xml). Places aSearchResultmarker on all source files within a module with a JBoss descriptor. This recipe is intended to be used as a precondition for other recipes.
- io.moderne.java.server.jboss.MoveWebXml
- Move
web.xmlto resources - Moves
src/main/webapp/WEB-INF/web.xmltosrc/main/resources/web.xml.
- Move
- io.moderne.java.server.jboss.PlanJBossMigration
- Plan JBoss migration
- Analyzes the repository to plan a JBoss migration, identifying JBoss descriptor files (jboss-web.xml, jboss-deployment-structure.xml) and recording them in a data table.
- io.moderne.java.server.jboss.jetty.CreateJettyEnvXml
- Create Jetty environment XML
- Creates a
jetty-env.xmlfile for projects containing JBoss descriptor files.
- io.moderne.java.server.jboss.jetty.CreateJettyFilesInPath
- Migrate JBoss to Jetty
- Comprehensive migration from JBoss to Jetty.
- io.moderne.java.server.jboss.jetty.CreateJettySourceFile
- Create Jetty server source file
- Creates a
JettyServer.javasource file for projects containing JBoss descriptor files.
- io.moderne.java.server.jboss.jetty.MigrateJBossToJetty
- Migrate JBoss to Jetty
- Comprehensive migration from JBoss to Jetty.
- io.moderne.java.server.jboss.jetty.devcenter.JBossToJettyMigrationCard
- JBoss to Jetty migration
- Measures the progress of migrating applications from JBoss to Jetty. Analyzes the presence of JBoss descriptor files (jboss-web.xml, jboss-deployment-structure.xml) and Jetty jetty-env.xml configuration files to determine migration state.
- io.moderne.java.server.jboss.jetty.devcenter.JBossToJettyMigrationCard$Scanner
- JBoss to Jetty migration scanner
- Scans for JBoss and Jetty configuration files.
- io.moderne.java.server.jboss.tomcat.CreateTomcatContextXml
- Create Tomcat context XML
- Creates a
context.xmlfile for projects containing JBoss descriptor files.
- io.moderne.java.server.jboss.tomcat.CreateTomcatFilesInPath
- Migrate JBoss to Tomcat
- Comprehensive migration from JBoss to Tomcat.
- io.moderne.java.server.jboss.tomcat.CreateTomcatSourceFile
- Create Tomcat server source file
- Creates a
TomcatServer.javasource file for projects containing JBoss descriptor files.
- io.moderne.java.server.jboss.tomcat.MigrateJBossToTomcat
- Migrate JBoss to Tomcat
- Comprehensive migration from JBoss to embedded Tomcat.
- io.moderne.java.server.jboss.tomcat.devcenter.JBossToTomcatMigrationCard
- JBoss to Tomcat migration
- Measures the progress of migrating applications from JBoss to Tomcat. Analyzes the presence of JBoss descriptor files (jboss-web.xml, jboss-deployment-structure.xml) and Tomcat context.xml configuration files to determine migration state.
- io.moderne.java.server.jboss.tomcat.devcenter.JBossToTomcatMigrationCard$Scanner
- JBoss to Tomcat migration scanner
- Scans for JBoss and Tomcat configuration files.
rewrite-kafka
- io.moderne.kafka.MigrateAdminListConsumerGroups
- Migrate
Admin.listConsumerGroups()tolistGroups() - Migrates the deprecated
Admin.listConsumerGroups()method tolistGroups()and updates related types for Kafka 4.1 compatibility.
- Migrate
- io.moderne.kafka.MigrateAlterConfigsToIncrementalAlterConfigs
- Migrate
AdminClient.alterConfigs()toincrementalAlterConfigs() - Migrates the removed
AdminClient.alterConfigs()method toincrementalAlterConfigs()for Kafka 4.0 compatibility.
- Migrate
- io.moderne.kafka.MigrateConsumerCommittedToSet
- Migrate
KafkaConsumer.committed(TopicPartition)tocommitted(Set<TopicPartition>) - Migrates from the removed
KafkaConsumer.committed(TopicPartition)tocommitted(Set<TopicPartition>)for Kafka 4.0 compatibility. Converts singleTopicPartitionarguments toCollections.singleton()calls.
- Migrate
- io.moderne.kafka.MigrateConsumerGroupStateToGroupState
- Migrate
ConsumerGroupStatetoGroupState - Migrates from the deprecated
ConsumerGroupStatetoGroupStatefor Kafka 4.0 compatibility.ConsumerGroupStatewas deprecated in favor ofGroupStatewhich supports both consumer groups and share groups.
- Migrate
- io.moderne.kafka.MigrateConsumerPollToDuration
- Migrate
KafkaConsumer.poll(long)topoll(Duration) - Migrates from the deprecated
KafkaConsumer.poll(long)topoll(Duration)for Kafka 4.0 compatibility. Converts millisecond timeout values toDuration.ofMillis()calls.
- Migrate
- io.moderne.kafka.MigrateSendOffsetsToTransaction
- Migrate deprecated
sendOffsetsToTransactionto useConsumerGroupMetadata - Migrates from the deprecated
KafkaProducer.sendOffsetsToTransaction(Map, String)tosendOffsetsToTransaction(Map, ConsumerGroupMetadata)for Kafka 4.0 compatibility. This recipe uses a conservative approach withnew ConsumerGroupMetadata(groupId).
- Migrate deprecated
- io.moderne.kafka.MigrateToKafka23
- Migrate to Kafka 2.3
- Migrate applications to the latest Kafka 2.3 release.
- io.moderne.kafka.MigrateToKafka24
- Migrate to Kafka 2.4
- Migrate applications to the latest Kafka 2.4 release.
- io.moderne.kafka.MigrateToKafka25
- Migrate to Kafka 2.5
- Migrate applications to the latest Kafka 2.5 release.
- io.moderne.kafka.MigrateToKafka26
- Migrate to Kafka 2.6
- Migrate applications to the latest Kafka 2.6 release.
- io.moderne.kafka.MigrateToKafka27
- Migrate to Kafka 2.7
- Migrate applications to the latest Kafka 2.7 release.
- io.moderne.kafka.MigrateToKafka28
- Migrate to Kafka 2.8
- Migrate applications to the latest Kafka 2.8 release.
- io.moderne.kafka.MigrateToKafka30
- Migrate to Kafka 3.0
- Migrate applications to the latest Kafka 3.0 release.
- io.moderne.kafka.MigrateToKafka31
- Migrate to Kafka 3.1
- Migrate applications to the latest Kafka 3.1 release.
- io.moderne.kafka.MigrateToKafka32
- Migrate to Kafka 3.2
- Migrate applications to the latest Kafka 3.2 release.
- io.moderne.kafka.MigrateToKafka33
- Migrate to Kafka 3.3
- Migrate applications to the latest Kafka 3.3 release.
- io.moderne.kafka.MigrateToKafka40
- Migrate to Kafka 4.0
- Migrate applications to the latest Kafka 4.0 release. This includes updating dependencies to 4.0.x, ensuring Java 11+ for clients and Java 17+ for brokers/tools, and handling changes.
- io.moderne.kafka.MigrateToKafka41
- Migrate to Kafka 4.1
- Migrate applications to the latest Kafka 4.1 release. This includes updating dependencies to 4.1.x, migrating deprecated Admin API methods, updating Streams configuration properties, and removing deprecated broker properties.
- io.moderne.kafka.RemoveDeprecatedKafkaProperties
- Remove deprecated Kafka property
- Removes a specific Kafka property that is no longer supported in Kafka 4.0.
- io.moderne.kafka.UpgradeJavaForKafkaBroker
- Upgrade Java to 17+ for Kafka broker/tools
- Ensures Java 17 or higher is used when Kafka broker or tools dependencies are present.
- io.moderne.kafka.UpgradeJavaForKafkaClients
- Upgrade Java to 11+ for Kafka clients
- Ensures Java 11 or higher is used when Kafka client libraries are present.
- io.moderne.kafka.streams.MigrateJoinedNameMethod
- Migrate
Joined.named()toJoined.as() - In Kafka Streams 2.3,
Joined.named()was deprecated in favor ofJoined.as(). Additionally, thename()method was deprecated for removal and should not be used.
- Migrate
- io.moderne.kafka.streams.MigrateKStreamToTable
- Migrate KStream to KTable conversion to use
toTable()method - In Kafka Streams 2.5, a new
toTable()method was added to simplify converting a KStream to a KTable. This recipe replaces the manual aggregation pattern.groupByKey().reduce((oldVal, newVal) -> newVal)with the more concise.toTable()method.
- Migrate KStream to KTable conversion to use
- io.moderne.kafka.streams.MigrateKafkaStreamsStoreMethod
- Migrate deprecated
KafkaStreams#storemethod - In Kafka Streams 2.5, the method
KafkaStreams#store(String storeName, QueryableStoreType<T> storeType)was deprecated. It only allowed querying active stores and did not support any additional query options. Use the newStoreQueryParametersAPI instead.
- Migrate deprecated
- io.moderne.kafka.streams.MigrateRetryConfiguration
- Migrate deprecated retry configuration to task timeout
- In Kafka 2.7,
RETRIES_CONFIGandRETRY_BACKOFF_MS_CONFIGwere deprecated in favor ofTASK_TIMEOUT_MS_CONFIG. This recipe migrates the old retry configuration to the new task timeout configuration, attempting to preserve the retry budget by multiplying retries × backoff time. If only one config is present, it falls back to 60000ms (1 minute).
- io.moderne.kafka.streams.MigrateStreamsUncaughtExceptionHandler
- Migrate to StreamsUncaughtExceptionHandler API
- Migrates from the JVM-level Thread.UncaughtExceptionHandler to Kafka Streams' StreamsUncaughtExceptionHandler API introduced in version 2.8. This new API provides explicit control over how the Streams client should respond to uncaught exceptions (REPLACE_THREAD, SHUTDOWN_CLIENT, or SHUTDOWN_APPLICATION).
- io.moderne.kafka.streams.MigrateTaskAndThreadMetadata
- Migrate TaskMetadata and ThreadMetadata
- Migrates TaskMetadata and ThreadMetadata from org.apache.kafka.streams.processor package to org.apache.kafka.streams package, and updates TaskMetadata.taskId() calls to include .toString() for String compatibility.
- io.moderne.kafka.streams.MigrateTaskMetadataTaskId
- Migrate
TaskMetadata.taskId()to returnTaskId - In Kafka Streams 3.0,
TaskMetadata.taskId()changed its return type fromStringtoTaskId. This recipe adds.toString()calls where necessary to maintain String compatibility.
- Migrate
- io.moderne.kafka.streams.MigrateWindowStorePutMethod
- Migrate
WindowStore.put()to include timestamp - In Kafka Streams 2.4,
WindowStore.put()requires a timestamp parameter. This recipe addscontext.timestamp()as the third parameter.
- Migrate
- io.moderne.kafka.streams.ProcessingGuaranteeExactlyOnceToBeta
- Migrate
exactly_oncetoexactly_once_beta - Kafka Streams 2.6 introduces the exactly-once semantics v2, which is a more efficient implementation with improved internal handling. Though it is beta, it’s fully backward-compatible from the API standpoint, but internally it uses a different transaction/commit protocol. Starting from 3.0, it becomes the default "exactly_once_v2".
- Migrate
- io.moderne.kafka.streams.ProcessingGuaranteeExactlyOnceToV2
- Migrate
exactly_onceandexactly_once_betatoexactly_once_v2 - Kafka Streams 2.6 introduces the exactly-once semantics v2, which is a more efficient implementation with improved internal handling. Starting from 3.0, it becomes the default "exactly_once_v2".
- Migrate
- io.moderne.kafka.streams.RemovePartitionGrouperConfiguration
- Remove
PartitionGrouperconfiguration - Starting with Kafka Streams 2.4, the
PartitionGrouperAPI was deprecated and partition grouping is now fully handled internally by the library. This recipe removes the deprecatedPARTITION_GROUPER_CLASS_CONFIGconfiguration.
- Remove
rewrite-prethink
- io.moderne.prethink.ComprehendCode
- Comprehend code with AI
- Use an LLM to generate descriptions for classes and methods in the codebase. Descriptions are cached based on source code checksums to avoid regenerating descriptions for unchanged code.
- io.moderne.prethink.ComprehendCodeTokenCounter
- Estimate comprehension token usage
- Estimate the input token counts that would be sent to an LLM for method comprehension, without actually calling a model. Uses OpenAI's tokenizer locally. Outputs to the MethodDescriptions table with blank descriptions.
- io.moderne.prethink.ExtractCodingConventions
- Extract coding conventions
- Analyze the codebase to extract coding conventions including naming patterns, import organization, and documentation patterns.
- io.moderne.prethink.ExtractDependencyUsage
- Extract dependency usage patterns
- Analyze the codebase to extract dependency usage patterns by examining which types from external libraries are actually used in the code.
- io.moderne.prethink.ExtractErrorPatterns
- Extract error handling patterns
- Analyze the codebase to extract error handling patterns including exception types, handling strategies, and logging frameworks used.
- io.moderne.prethink.ExtractGoDependencies
- Extract Go dependencies and usage
- Scan go.mod and Go source imports to produce a DependencyUsage entry per actually-imported module, including file-count and sample imports.
- io.moderne.prethink.FindGoCodingConventions
- Find Go coding conventions
- Detect Go naming patterns (package names, exported vs unexported, interface -er suffix, error variable prefix, test prefix).
- io.moderne.prethink.FindGoErrorPatterns
- Find Go error handling patterns
- Detect Go error-handling idioms: error returns, fmt.Errorf %w wrapping, errors.Is/As, panic/recover, and sentinel error variables.
- io.moderne.prethink.UpdatePrethinkContextNoAiStarter
- Update Prethink context (no AI)
- Generate Moderne Prethink context files with architectural discovery, test coverage mapping, dependency inventory, and FINOS CALM architecture diagrams. This recipe does not require an LLM provider - use UpdatePrethinkContextStarter if you want AI-generated code comprehension and test summaries.
- io.moderne.prethink.UpdatePrethinkContextStarter
- Update Prethink context (with AI)
- Generate Moderne Prethink context files with AI-generated code comprehension, test coverage mapping, dependency inventory, and FINOS CALM architecture diagrams. Maps tests to implementation methods and optionally generates AI summaries of what each test verifies when LLM provider is configured.
- io.moderne.prethink.calm.FindAspNetCoreEndpoints
- Find ASP.NET Core endpoints
- Identify HTTP endpoints declared via ASP.NET Core controllers ([ApiController], [Route], [HttpGet/Post/...]) and Minimal APIs (app.MapGet/MapPost/MapPut/MapDelete/MapPatch).
- io.moderne.prethink.calm.FindCalmRelationships
- Find CALM relationships
- Discover method call relationships within the repository for building interaction diagrams. Captures all method-to-method calls between in-repo classes. Entity IDs are resolved by GenerateCalmArchitecture when building CALM relationships.
- io.moderne.prethink.calm.FindDataAssets
- Find data assets
- Identify data assets including JPA entities, MongoDB documents, Java records, and DTOs in the application.
- io.moderne.prethink.calm.FindDatabaseConnections
- Find database connections
- Identify database connections and data access patterns in the application. Detects JPA entities, Spring Data repositories, JDBC templates, MyBatis mappers, and Quarkus Panache.
- io.moderne.prethink.calm.FindDeploymentArtifacts
- Find deployment artifacts
- Identify deployment artifacts including Dockerfiles, docker-compose files, and Kubernetes manifests.
- io.moderne.prethink.calm.FindDjangoEndpoints
- Find Django endpoints
- Identify REST/HTTP endpoints in Django and Django REST Framework applications. Detects class-based views, function-based views with @api_view, and regular Django views with @require_http_methods decorators.
- io.moderne.prethink.calm.FindDotnetDataAssets
- Find .NET data assets
- Detect C# DTOs, records, and entity types based on property/method ratio, [DataContract] / [Table] attributes, and
recordkeyword.
- io.moderne.prethink.calm.FindDotnetDtoFieldSchemas
- Find .NET DTO field schemas
- Per-property schema rows for C# DTOs: serialized name (JsonPropertyName/JsonProperty), OpenAPI format, required flag (DataAnnotations.RequiredAttribute / non-nullable value types), and a validations JSON map.
- io.moderne.prethink.calm.FindDotnetEndpointContracts
- Find .NET endpoint contracts
- Extract request body, response body (unwrapping ActionResult<T>/Task<T>), and per-parameter binding source ([FromBody/Query/Route/Header/Form]) for ASP.NET Core controller endpoints.
- io.moderne.prethink.calm.FindDotnetEndpointSecurity
- Find .NET endpoint security
- Per-endpoint security requirements derived from ASP.NET Core [Authorize] (Policy/Roles/AuthenticationSchemes) and [AllowAnonymous].
- io.moderne.prethink.calm.FindDotnetExceptionHandlers
- Find .NET exception handlers
- Detect IExceptionFilter / IAsyncExceptionFilter / IExceptionHandler implementations and ExceptionFilterAttribute-derived classes in ASP.NET Core projects.
- io.moderne.prethink.calm.FindDotnetGraphQLEndpoints
- Find .NET GraphQL endpoints
- Detect HotChocolate query/mutation/subscription types and GraphQL.NET schema types in .NET projects.
- io.moderne.prethink.calm.FindDotnetGrpcServices
- Find .NET gRPC services
- Detect gRPC service implementations (classes deriving from generated *Base types under Grpc.Core / Grpc.AspNetCore) and ASP.NET Core gRPC endpoint registrations via MapGrpcService<T>().
- io.moderne.prethink.calm.FindDotnetHttpClients
- Find .NET HTTP clients
- Detect outbound HTTP client usage via HttpClient, IHttpClientFactory.CreateClient, Refit interfaces, RestSharp, and Flurl.
- io.moderne.prethink.calm.FindDotnetMessagingConnections
- Find .NET messaging connections
- Detect MassTransit IConsumer<T>, NServiceBus IHandleMessages<T>, MediatR IRequestHandler/INotificationHandler, Confluent.Kafka producers/consumers, Azure Service Bus, and RabbitMQ.Client usage.
- io.moderne.prethink.calm.FindDotnetProjectMetadata
- Find .NET project metadata
- Extract project metadata (SDK, target framework(s), package list) from MSBuild project files. Reads the MSBuildProject marker which captures values resolved across the project file, Directory.Build.props, Directory.Packages.props, global.json and nuget.config.
- io.moderne.prethink.calm.FindDotnetScheduledTasks
- Find .NET scheduled tasks
- Detect Hangfire RecurringJob.AddOrUpdate, Quartz.IJob implementations, BackgroundService/IHostedService classes, and Azure Functions TimerTrigger methods.
- io.moderne.prethink.calm.FindDotnetSecurityConfiguration
- Find .NET security configuration
- Detect ASP.NET Core authentication (JwtBearer/OpenIdConnect/Cookie), authorization, CORS, HSTS, and HTTPS redirection middleware registrations.
- io.moderne.prethink.calm.FindDotnetServerConfiguration
- Find .NET server configuration
- Read appsettings*.json and launchSettings.json for Kestrel Urls/ApplicationUrl entries and emit ServerConfiguration rows (port, sslEnabled, contextPath, protocol).
- io.moderne.prethink.calm.FindDotnetServiceComponents
- Find .NET service components
- Detect IServiceCollection.AddSingleton/AddScoped/AddTransient/AddHttpClient registrations and emit one row per registered service.
- io.moderne.prethink.calm.FindDotnetTestCoverage
- Find .NET test coverage
- Identify xUnit ([Fact]/[Theory]), NUnit ([Test]/[TestCase]) and MSTest ([TestMethod]/[DataTestMethod]) test methods in C# source and record them in the test mapping table for downstream coverage linking.
- io.moderne.prethink.calm.FindDtoFieldSchemas
- Find DTO field schemas
- Emit per-field rows for request/response DTO classes: wire name, type, required flag, OpenAPI format, validation constraints, and @Schema(example = ...) values. Supports OpenAPI 3.0.3 generation by providing the full field schema for each DTO an endpoint references.
- io.moderne.prethink.calm.FindEndpointContracts
- Find endpoint contracts
- Extract per-endpoint request body, response body (per status code), and parameter details from Spring/JAX-RS/Micronaut handlers to support OpenAPI 3.0.3 spec generation and consumer/provider contract-test generation. Walks interface inheritance for OpenAPI-codegen-first projects.
- io.moderne.prethink.calm.FindEndpointSecurity
- Find endpoint security
- Per-endpoint security requirements (roles, scopes, raw expressions) extracted from @PreAuthorize/@Secured/@RolesAllowed/@PermitAll annotations at method or class level. Joins to service-endpoints.csv via endpointId.
- io.moderne.prethink.calm.FindEntityFrameworkConnections
- Find Entity Framework / Dapper / ADO.NET database access
- Detect Entity Framework Core DbContext subclasses, DbSet<T> properties, [Table]/[Column]/[Key] annotated entity classes, Dapper Query/Execute calls, and raw SqlConnection usage.
- io.moderne.prethink.calm.FindExceptionHandlers
- Find exception handlers
- Capture @ControllerAdvice and controller-local @ExceptionHandler methods so that OpenAPI 3.0.3 specs include non-2xx response branches. Emits one row per (scope, exception type, status) triple.
- io.moderne.prethink.calm.FindExpressEndpoints
- Find Express endpoints
- Identify REST/HTTP endpoints in Express and Fastify applications. Detects app.get(), router.post(), and similar route definition patterns.
- io.moderne.prethink.calm.FindExternalServiceCalls
- Find external service calls
- Identify outbound HTTP calls to external services. Detects RestTemplate, WebClient, Feign clients, MicroProfile REST Client, Apache HttpClient, OkHttp, and JAX-RS clients.
- io.moderne.prethink.calm.FindFastAPIEndpoints
- Find FastAPI endpoints
- Identify REST/HTTP endpoints in FastAPI applications. Detects @app.get(), @router.post(), and similar route decorator patterns.
- io.moderne.prethink.calm.FindFieldExamplesFromFixtures
- Find field examples from JSON fixtures
- Walk JSON and YAML fixture files under src/test/resources and emit raw (fixturePath, jsonPath, value, valueType) rows so that an LLM can mine realistic example values for OpenAPI specs and contract tests.
- io.moderne.prethink.calm.FindFlaskEndpoints
- Find Flask endpoints
- Identify REST/HTTP endpoints in Flask applications. Detects @app.route(), @blueprint.route(), and Flask 2.0+ shortcut decorators like @app.get() and @app.post().
- io.moderne.prethink.calm.FindGoDatabaseConnections
- Find Go database connections
- Detect database/sql, GORM, sqlx, pgx, and ent usage in Go source.
- io.moderne.prethink.calm.FindGoGrpcServices
- Find Go gRPC services
- Detect gRPC service registrations via grpc-go RegisterXxxServer calls.
- io.moderne.prethink.calm.FindGoHttpClients
- Find Go HTTP clients
- Detect outbound HTTP calls made through net/http, resty, go-retryablehttp, or imroc/req.
- io.moderne.prethink.calm.FindGoMessagingConnections
- Find Go messaging connections
- Detect Kafka, NATS, RabbitMQ/AMQP client usage in Go source.
- io.moderne.prethink.calm.FindGoProjectMetadata
- Find Go project metadata
- Extract project metadata (module path, go version) from Go go.mod files.
- io.moderne.prethink.calm.FindGoServiceEndpoints
- Find Go service endpoints
- Detect HTTP endpoints registered via net/http, gin, echo, chi, gorilla/mux, and fiber routers.
- io.moderne.prethink.calm.FindGoTestCoverage
- Find Go test coverage
- Identify Go test/benchmark/fuzz functions in *_test.go files and record them in the test mapping table.
- io.moderne.prethink.calm.FindGraphQLEndpoints
- Find GraphQL endpoints
- Identify GraphQL endpoints exposed by the application. Supports Spring GraphQL, Netflix DGS, and GraphQL Java (graphql-java-tools).
- io.moderne.prethink.calm.FindGrpcServices
- Find gRPC services
- Identify gRPC service implementations in the application. Detects classes extending generated ImplBase classes and @GrpcService annotations.
- io.moderne.prethink.calm.FindMessagingConnections
- Find messaging connections
- Identify message queue producers and consumers. Detects Kafka, RabbitMQ, JMS, Spring Cloud Stream, AWS SQS, and SmallRye Reactive Messaging.
- io.moderne.prethink.calm.FindMongooseSchemas
- Find Mongoose schemas
- Identify Mongoose models and schemas in Node.js applications. Detects mongoose.model() calls and populates the DatabaseConnections table.
- io.moderne.prethink.calm.FindNestJSEndpoints
- Find NestJS endpoints
- Identify REST/HTTP endpoints in NestJS controllers. Detects @Controller, @Get, @Post, @Put, @Delete, and @Patch decorators and populates the ServiceEndpoints data table.
- io.moderne.prethink.calm.FindNodeErrorPatterns
- Find Node.js error patterns
- Identify error handling patterns in Node.js applications. Detects try/catch blocks and identifies logging frameworks used.
- io.moderne.prethink.calm.FindNodeHttpClients
- Find Node.js HTTP clients
- Identify HTTP client usage in Node.js applications. Detects axios, fetch, got, and superagent call patterns.
- io.moderne.prethink.calm.FindNodeMessaging
- Find Node.js messaging
- Identify messaging patterns in Node.js applications. Detects KafkaJS, amqplib, and Bull/BullMQ usage.
- io.moderne.prethink.calm.FindNodeProjectMetadata
- Find Node.js project metadata
- Extract project metadata (name, version, description) from Node.js package.json files.
- io.moderne.prethink.calm.FindNodeSecurityConfig
- Find Node.js security configuration
- Identify security middleware in Node.js applications. Detects cors, helmet, passport, and JWT middleware usage.
- io.moderne.prethink.calm.FindNodeTestCoverage
- Find Node.js test coverage
- Identify test methods in Jest, Mocha, and Vitest test files. Detects describe(), it(), and test() blocks and populates the TestMapping table.
- io.moderne.prethink.calm.FindPrismaUsage
- Find Prisma usage
- Identify Prisma ORM usage in Node.js applications. Detects prisma.model.findMany() and similar Prisma Client query patterns.
- io.moderne.prethink.calm.FindProjectMetadata
- Find project metadata
- Extract project metadata (artifact ID, group ID, name, description) from Maven pom.xml files.
- io.moderne.prethink.calm.FindPythonProjectMetadata
- Find Python project metadata
- Extract project metadata (name, version, description) from Python pyproject.toml files.
- io.moderne.prethink.calm.FindPythonTestCoverage
- Find Python test coverage
- Identify test methods in Python test files. Detects pytest test functions/classes and unittest.TestCase subclasses, and populates the TestMapping table.
- io.moderne.prethink.calm.FindSQLAlchemyModels
- Find SQLAlchemy and Django ORM models
- Identify ORM model classes in Python applications. Detects SQLAlchemy models with DeclarativeBase inheritance, Flask-SQLAlchemy models with db.Model, and Django ORM models extending models.Model.
- io.moderne.prethink.calm.FindScheduledTasks
- Find scheduled tasks
- Identify scheduled tasks and background jobs in the application. Supports Spring @Scheduled, Quarkus @Scheduled, Quartz Job, Jakarta/Javax EJB Timer, and JobRunr @Recurring annotations.
- io.moderne.prethink.calm.FindSecurityConfiguration
- Find security configuration
- Identify security configurations including Spring Security, OAuth2, CORS, Jakarta Security (@RolesAllowed, @PermitAll, @DenyAll), and Quarkus Security settings.
- io.moderne.prethink.calm.FindServerConfiguration
- Find server configuration
- Extract server configuration (port, SSL, context path) from application.properties and application.yml files.
- io.moderne.prethink.calm.FindServiceComponents
- Find service components
- Identify service layer components (@Service, @Component, @Named) in the application. Excludes controllers and repositories which are handled by dedicated recipes.
- io.moderne.prethink.calm.FindServiceEndpoints
- Find service endpoints
- Identify all REST/HTTP service endpoints exposed by the application. Supports Spring MVC, JAX-RS, Micronaut, and Quarkus REST endpoints. Also walks interface inheritance to detect endpoints in OpenAPI-codegen-first projects where @GetMapping etc. live on the interface methods.
- io.moderne.prethink.calm.FindSignalRHubs
- Find ASP.NET Core SignalR hubs
- Detect SignalR Hub subclasses, their methods (with optional [HubMethodName]), and MapHub<T> registrations.
- io.moderne.prethink.calm.FindTypeORMEntities
- Find TypeORM entities
- Identify TypeORM entities in Node.js applications. Detects @Entity() decorator on classes and populates the DatabaseConnections table.
- io.moderne.prethink.calm.FindWebSocketEndpoints
- Find WebSocket endpoints
- Identify WebSocket endpoints in the application. Supports Spring WebSocket, Spring STOMP messaging, and Jakarta/Javax WebSocket.
- io.moderne.prethink.calm.GenerateCalmMermaidDiagram
- Generate architecture mermaid diagram
- Generate a markdown file with a mermaid architecture diagram from discovered service endpoints, database connections, external service calls, and messaging connections.
- io.moderne.prethink.quality.FindClassMetrics
- Find class quality metrics
- Compute per-class code quality metrics including WMC, LCOM4, TCC, CBO, and maintainability index.
- io.moderne.prethink.quality.FindCodeSmells
- Find code smells
- Detect code smells including God Class, Feature Envy, and Data Class using composite metric thresholds with severity ratings.
- io.moderne.prethink.quality.FindDotnetErrorPatterns
- Find .NET error patterns
- Detect .NET logging frameworks (Microsoft.Extensions.Logging, Serilog, NLog, log4net) and catch-block strategies (swallow, rethrow, log, wrap).
- io.moderne.prethink.quality.FindGoCodeSmells
- Find Go code smells
- Detect God Struct, Feature Envy, Large Interface, and Long Function code smells in Go. Data Class is intentionally excluded (idiomatic in Go).
- io.moderne.prethink.quality.FindGoPackageMetrics
- Find Go package quality metrics
- Per-package architectural metrics for Go: afferent/efferent coupling, instability, abstractness (interface ratio), distance from main sequence, and cycle detection.
- io.moderne.prethink.quality.FindGoTypeMetrics
- Find Go type quality metrics
- Compute per-struct code quality metrics for Go including WMC, LCOM4, TCC, CBO, and maintainability index. Aggregates methods with the same receiver type across files.
- io.moderne.prethink.quality.FindMethodComplexity
- Find method complexity
- Compute per-method code quality metrics including cyclomatic complexity, cognitive complexity, max nesting depth, line count, parameter count, ABC metric, and Halstead measures.
- io.moderne.prethink.quality.FindPackageMetrics
- Find package quality metrics
- Compute per-package architectural quality metrics including afferent/efferent coupling, instability, abstractness, distance from the main sequence, and dependency cycle detection using Tarjan's strongly connected components algorithm.
- io.moderne.prethink.testing.coverage.FindTestCoverage
- Find test coverage mapping
- Map test methods to their corresponding implementation methods. Uses JavaType.Method matching to determine coverage relationships. Optionally generates AI summaries of what each test is verifying when LLM provider is configured.
- io.moderne.prethink.testing.coverage.FindTestGaps
- Find test coverage gaps
- Identify public non-trivial methods that lack test coverage. Reports gaps with cyclomatic complexity and risk scores to help prioritize where to add tests.
- io.moderne.prethink.testing.quality.FindDotnetFlakyTestPatterns
- Find .NET flaky test patterns
- Detect Thread.Sleep, Task.Delay (without CancellationToken), and .Result/.Wait() on Task in .NET tests — patterns that cause flakiness or deadlocks.
- io.moderne.prethink.testing.quality.FindDotnetFragileTestData
- Find .NET fragile test data
- Detect hardcoded dates/paths/ports, DateTime.Now usage, and Guid.NewGuid/ Random in .NET tests — sources of timing- or environment-dependent flakiness.
- io.moderne.prethink.testing.quality.FindDotnetGhostTests
- Find .NET ghost tests
- Detect empty test bodies and suppressed tests ([Ignore], [Fact(Skip=...)]) in .NET tests.
- io.moderne.prethink.testing.quality.FindDotnetOverlyBroadMocks
- Find overly broad mocks in .NET tests
- Detect It.IsAny<T> (Moq), Arg.Any<T> (NSubstitute) and A<T>.Ignored (FakeItEasy) matcher overuse in .NET tests.
- io.moderne.prethink.testing.quality.FindDotnetSilentTestFailures
- Find .NET silent test failures
- Detect .NET test methods with no assertions, and swallowed exceptions inside tests.
- io.moderne.prethink.testing.quality.FindDotnetTestCodeSmells
- Find .NET test code smells
- Detect poor test names, magic numbers in assertions, generic catch in tests, and Debug.Assert misuse in .NET tests.
- io.moderne.prethink.testing.quality.FindDotnetUnmockedExternalCalls
- Find unmocked external calls in .NET tests
- Detect direct HttpClient/SqlConnection/EF DbContext/File/Socket usage inside .NET unit tests that should typically be mocked.
- io.moderne.prethink.testing.quality.FindFlakyTestPatterns
- Find flaky test patterns
- Detect patterns that commonly cause flaky tests in Java and Python code, including static waits (Thread.sleep, TimeUnit.sleep) and shared mutable state (static non-final fields in test classes).
- io.moderne.prethink.testing.quality.FindFragileTestData
- Find fragile test data
- Detect hardcoded dates, timing-dependent assertions, and hardcoded ports/paths in test code that may cause flaky or environment-dependent test failures.
- io.moderne.prethink.testing.quality.FindGhostTests
- Find ghost tests
- Detect methods that look like tests but will not be executed by the test runner, and tests skipped without a documented reason.
- io.moderne.prethink.testing.quality.FindGoFlakyTestPatterns
- Find Go flaky test patterns
- Detect time.Sleep and non-deterministic randomness in Go *_test.go files.
- io.moderne.prethink.testing.quality.FindGoFragileTestData
- Find Go fragile test data
- Detect hardcoded dates, absolute paths, and hardcoded ports in Go tests.
- io.moderne.prethink.testing.quality.FindGoGhostTests
- Find Go ghost tests
- Detect empty test bodies and unexplained skips in Go tests.
- io.moderne.prethink.testing.quality.FindGoOverlyBroadMocks
- Find Go overly broad mocks
- Detect testify mock.Anything / mock.AnythingOfType usage in Go tests.
- io.moderne.prethink.testing.quality.FindGoSilentTestFailures
- Find Go silent test failures
- Detect discarded error returns and assertion-less test bodies in Go tests.
- io.moderne.prethink.testing.quality.FindGoTestCodeSmells
- Find Go test code smells
- Detect magic numbers, over-long test names, and over-grown table-driven tests.
- io.moderne.prethink.testing.quality.FindGoUnmockedExternalCalls
- Find Go unmocked external calls
- Detect net/http, os.Open, net.Dial, sql.Open calls directly in Go tests.
- io.moderne.prethink.testing.quality.FindNodeFlakyTestPatterns
- Find Node.js flaky test patterns
- Detect patterns that commonly cause flaky tests in JavaScript and TypeScript code, including static waits (setTimeout, setInterval), prototype mutation, and shared mutable state (module-scope let/var declarations).
- io.moderne.prethink.testing.quality.FindNodeFragileTestData
- Find Node.js fragile test data
- Detect hardcoded dates, timing-dependent assertions, and hardcoded ports in JavaScript and TypeScript test files.
- io.moderne.prethink.testing.quality.FindNodeGhostTests
- Find Node.js ghost tests
- Detect skipped tests in JavaScript and TypeScript test files. Flags xtest(), xit(), test.skip(), it.skip(), and describe.skip() calls that lack a documented reason in their description.
- io.moderne.prethink.testing.quality.FindNodeSilentTestFailures
- Find Node.js silent test failures
- Detect silent test failures in JavaScript and TypeScript test files including empty .catch() handlers and test functions missing expect() calls.
- io.moderne.prethink.testing.quality.FindNodeTestCodeSmells
- Find Node.js test code smells
- Detect code smells in JavaScript and TypeScript test files including empty catch blocks and magic numbers.
- io.moderne.prethink.testing.quality.FindNodeUnmockedExternalCalls
- Find unmocked external calls in Node.js tests
- Detect direct HTTP, database, and network calls in JavaScript/TypeScript test files that are not mocked. Integration and e2e test files are excluded.
- io.moderne.prethink.testing.quality.FindOverlyBroadMocks
- Find overly broad mocks
- Detect Mockito stubbing or verification calls that use 3 or more any() matchers, which can hide incorrect arguments and reduce test effectiveness.
- io.moderne.prethink.testing.quality.FindSilentTestFailures
- Find silent test failures
- Detect silent test failures including Java assert keyword usage, swallowed exceptions in try/catch blocks, and test methods missing assertions.
- io.moderne.prethink.testing.quality.FindTestCodeSmells
- Find test code smells
- Detect code smells in test files including empty catch blocks, deprecated test APIs, magic numbers, and poorly named test methods.
- io.moderne.prethink.testing.quality.FindUnmockedExternalCalls
- Find unmocked external calls in tests
- Detect direct HTTP, database, and network calls in unit tests that are not mocked. These cause flaky and slow tests. Integration tests (annotated with @SpringBootTest, @Testcontainers, etc.) are excluded.
rewrite-program-analysis
- io.moderne.recipe.rewrite-program-analysis.InlineDeprecatedMethods
- Inline deprecated delegating methods
- Automatically generated recipes to inline deprecated method calls that delegate to other methods in the same class.
- org.openrewrite.analysis.java.FindNullPointerIssues
- Find null pointer issues
- Detects potential null pointer dereferences using path-sensitive analysis to distinguish between definite NPEs, possible NPEs, and safe dereferences.
- org.openrewrite.analysis.java.controlflow.FindUnusedDefinitions
- Find unused variable definitions
- Identifies variable assignments whose values are never used before being overwritten.
- org.openrewrite.analysis.java.controlflow.search.FindCyclomaticComplexity
- Find cyclomatic complexity
- Calculates the cyclomatic complexity of methods and produces a data table containing the class name, method name, argument types, complexity value, and complexity threshold.
- org.openrewrite.analysis.java.controlflow.search.FindUnreachableCode
- Find unreachable code
- Uses control flow analysis to identify statements that can never be executed.
- org.openrewrite.analysis.java.dataflow.FindDeadStores
- Find dead stores
- Identifies variable assignments whose values are never used before being overwritten or going out of scope.
- org.openrewrite.analysis.java.dataflow.FindUnclosedResources
- Find unclosed resources (S2095)
- Identifies resources implementing AutoCloseable/Closeable that are opened but not properly closed on all execution paths. Unclosed resources can lead to resource leaks that degrade application performance and stability.
- org.openrewrite.analysis.java.datalineage.TrackDataLineage
- Track data lineage
- Tracks the flow of data from database sources to API sinks to understand data dependencies and support compliance requirements. ## Prerequisites for detecting a data flow All of the following conditions must be met for the recipe to report a flow: 1. The source code must contain at least one method call matching a recognized source (see below). 2. The source code must contain at least one method call matching a recognized sink (see below). 3. The tainted data must propagate from the source to the sink through variable assignments within the same method or via fields across methods in the same compilation unit. 4. No flow breaker (see below) may appear on the path between source and sink. 5. The relevant library types (e.g.,
java.sql.ResultSet,javax.ws.rs.core.Response) must be on the classpath so that OpenRewrite can resolve types. If types are unresolved, method matchers will not trigger and no flows will be detected. ## Recognized sources (database reads) | Category | Classes | | --- | --- | | JDBC |java.sql.ResultSet| | JPA (javax) |javax.persistence.EntityManager,Query,TypedQuery| | JPA (jakarta) |jakarta.persistence.EntityManager,Query,TypedQuery| | Hibernate |org.hibernate.Session,org.hibernate.query.Query| | Spring Data |org.springframework.data.repository.CrudRepository| | Spring JDBC |org.springframework.jdbc.core.JdbcTemplate| | MyBatis |org.apache.ibatis.session.SqlSession,org.mybatis.spring.SqlSessionTemplate| | MongoDB |com.mongodb.client.MongoCollection,org.springframework.data.mongodb.core.MongoTemplate| | Redis |redis.clients.jedis.Jedis,org.springframework.data.redis.core.RedisTemplate,ValueOperations,HashOperations| | Cassandra |com.datastax.driver.core.Session,org.springframework.data.cassandra.core.CassandraTemplate| | Elasticsearch |org.elasticsearch.client.RestHighLevelClient,org.springframework.data.elasticsearch.core.ElasticsearchTemplate| | Heuristic | Any class withRepository,Dao, orMapperin its name calling methods starting with find, get, query, search, load, fetch, or select | ## Recognized sinks (API responses) | Category | Classes | | --- | --- | | JAX-RS (javax) |javax.ws.rs.core.Response,Response.ResponseBuilder| | JAX-RS (jakarta) |jakarta.ws.rs.core.Response,Response.ResponseBuilder| | Spring MVC |org.springframework.http.ResponseEntity,ResponseEntity.BodyBuilder| | Servlet (javax) |javax.servlet.http.HttpServletResponse,javax.servlet.ServletOutputStream| | Servlet (jakarta) |jakarta.servlet.http.HttpServletResponse,jakarta.servlet.ServletOutputStream| | Java I/O |java.io.PrintWriter,java.io.Writer,java.io.OutputStream| | Jackson |com.fasterxml.jackson.databind.ObjectMapper,com.fasterxml.jackson.core.JsonGenerator| | Gson |com.google.gson.Gson,com.google.gson.JsonWriter| | GraphQL |graphql.schema.DataFetcher,graphql.schema.PropertyDataFetcher| | Spring WebFlux |ServerResponse,reactor.core.publisher.Mono,reactor.core.publisher.Flux| | gRPC |io.grpc.stub.StreamObserver| | WebSocket |javax.websocket.Session,RemoteEndpoint.Basic,jakarta.websocket.*,org.springframework.web.socket.WebSocketSession| ## Flow breakers Flows are broken by methods matching common sanitization patterns (anonymize, redact, mask, encrypt, hash, sanitize, etc.) or authorization checks (isAuthorized, hasPermission, hasRole, etc.).
- org.openrewrite.analysis.java.privacy.FindPiiExposure
- Find PII exposure in logs and external APIs
- Detects when Personally Identifiable Information (PII) is exposed through logging statements or sent to external APIs without proper sanitization. This helps prevent data leaks and ensures compliance with privacy regulations like GDPR and CCPA.
- org.openrewrite.analysis.java.security.FindArrayIndexInjection
- Find improper validation of array index
- Detects when user-controlled input flows into array or collection index expressions without proper bounds validation, which could allow out-of-bounds access or denial of service (CWE-129).
- org.openrewrite.analysis.java.security.FindCommandInjection
- Find command injection vulnerabilities
- Detects when user-controlled input flows into system command execution methods like Runtime.exec() or ProcessBuilder, which could allow attackers to execute arbitrary commands.
- org.openrewrite.analysis.java.security.FindInsecureCryptoComparison
- Find non-constant-time comparison of cryptographic digests
- Detects when the output of
MessageDigest.digest(..)orMac.doFinal(..)flows intoArrays.equals(byte[], byte[]), a non-constant-time comparison that is vulnerable to timing attacks (CWE-208). UseMessageDigest.isEqual(byte[], byte[])for security-sensitive byte-array comparisons.
- org.openrewrite.analysis.java.security.FindJndiInjection
- Find JNDI injection vulnerabilities
- Detects when user-controlled input flows into JNDI lookup operations without proper validation, which could allow an attacker to connect to malicious naming/directory services (CWE-99).
- org.openrewrite.analysis.java.security.FindLdapInjection
- Find LDAP injection vulnerabilities
- Finds LDAP injection vulnerabilities by tracking tainted data flow from user input to LDAP queries.
- org.openrewrite.analysis.java.security.FindLogInjection
- Find log injection vulnerabilities
- Detects when user-controlled input flows into logging methods without sanitization, which could allow attackers to forge log entries by injecting newline characters.
- org.openrewrite.analysis.java.security.FindPathTraversal
- Find path traversal vulnerabilities
- Detects potential path traversal vulnerabilities where user input flows to file system operations without proper validation.
- org.openrewrite.analysis.java.security.FindProcessControlInjection
- Find process control vulnerabilities
- Detects when user-controlled input flows into native library loading methods without proper validation, which could allow an attacker to load arbitrary native code (CWE-114).
- org.openrewrite.analysis.java.security.FindSecurityVulnerabilities
- Find security vulnerabilities using taint analysis
- Identifies potential security vulnerabilities where untrusted data from sources flows to sensitive sinks without proper sanitization.
- org.openrewrite.analysis.java.security.FindSqlInjection
- Find SQL injection vulnerabilities
- Detects potential SQL injection vulnerabilities where user input flows to SQL execution methods without proper sanitization.
- org.openrewrite.analysis.java.security.FindUnencryptedPiiStorage
- Find unencrypted PII storage
- Identifies when personally identifiable information (PII) is stored in databases, files, or other persistent storage without encryption.
- org.openrewrite.analysis.java.security.FindUnsafeReflectionInjection
- Find unsafe reflection vulnerabilities
- Detects when user-controlled input flows into reflection-based class loading or instantiation without proper validation, which could allow an attacker to instantiate arbitrary classes (CWE-470).
- org.openrewrite.analysis.java.security.FindXssVulnerability
- Find XSS vulnerabilities
- Detects potential cross-site scripting vulnerabilities where user input flows to output methods without proper sanitization.
- org.openrewrite.analysis.java.security.FindXxeVulnerability
- Find XXE vulnerabilities
- Locates XML parsers that are not configured to prevent XML External Entity (XXE) attacks.
- org.openrewrite.analysis.java.security.SanitizeLogInjection
- Sanitize log injection vulnerabilities
- Sanitizes user-controlled input before it flows into logging methods by stripping newline, carriage return, and tab characters that could enable log forging.
rewrite-react
- org.openrewrite.javascript.cleanup.simplify-object-pattern-property
- Simplify object pattern properties
- Simplifies object destructuring patterns where the property name and variable name are the same (e.g.,
\{ x: x \}becomes\{ x \}).
- org.openrewrite.react.16.error-boundaries
- Rename
unstable_handleErrortocomponentDidCatch - Renames the unstable error boundary method to the official
componentDidCatchAPI introduced in React 16.
- Rename
- org.openrewrite.react.16.find-dom-node
- Replace
getDOMNode()withReact.findDOMNode() - Migrates deprecated
getDOMNode()calls toReact.findDOMNode().
- Replace
- org.openrewrite.react.16.react-dom-factories
- Replace
React.DOMfactories withcreateElement - Converts deprecated
React.DOM.xxx()factory calls toReact.createElement('xxx', ...).
- Replace
- org.openrewrite.react.16.react-prop-types
- Move
React.PropTypestoprop-typespackage - Extracts PropTypes usage from the React namespace to the separate
prop-typespackage introduced in React 15.5.
- Move
- org.openrewrite.react.16.react-to-react-dom
- Split
ReactDOM methods toReactDOM - Moves DOM-specific methods like
React.render()andReact.findDOMNode()toReactDOMfrom thereact-dompackage.
- Split
- org.openrewrite.react.16.replace-create-factory
- Replace
React.createFactorywithReact.createElement - Replaces
React.createFactory(type)(props, children)withReact.createElement(type, props, children). React.createFactory was deprecated in React 15.6 and removed in React 16.
- Replace
- org.openrewrite.react.17.remove-event-persist
- Remove
event.persist()calls - Removes
event.persist()calls. React 17 removed event pooling, making persist() unnecessary.
- Remove
- org.openrewrite.react.17.rename-unsafe-lifecycles
- Add
UNSAFE_prefix to deprecated lifecycle methods - Renames
componentWillMount,componentWillReceiveProps, andcomponentWillUpdateto their UNSAFE_ prefixed versions.
- Add
- org.openrewrite.react.17.update-react-imports
- Remove unnecessary React imports
- Removes the default
import React from 'react'when React is only used for JSX, which is no longer necessary with the new JSX transform in React 17+.
- org.openrewrite.react.18.remove-unstable-batched-updates
- Remove
unstable_batchedUpdates - Removes
unstable_batchedUpdateswrappers fromreact-dom. React 18 automatically batches all state updates, making this function unnecessary.
- Remove
- org.openrewrite.react.18.replace-reactdom-render
- Replace
ReactDOM.renderwithcreateRoot - Migrates from the legacy
ReactDOM.render()API to thecreateRoot()API fromreact-dom/clientintroduced in React 18.
- Replace
- org.openrewrite.react.18.replace-render-callback
- Remove
ReactDOM.rendercallback argument - Removes the third callback argument from
ReactDOM.render(element, container, callback)calls. Callbacks are not supported in React 18'screateRootAPI.
- Remove
- org.openrewrite.react.18.replace-unmount-component-at-node
- Replace
unmountComponentAtNodewithcreateRoot().unmount() - Replaces
ReactDOM.unmountComponentAtNode(container)withcreateRoot(container).unmount()fromreact-dom/client.
- Replace
- org.openrewrite.react.19.deprecated-react-types
- Replace deprecated React types
- Replaces deprecated React TypeScript types (
SFC,StatelessComponent,VFC,VoidFunctionComponent) with their modern equivalents.
- org.openrewrite.react.19.find-context-consumer
- Find
Context.Consumerusage - Finds usage of the deprecated
<Context.Consumer>pattern. In React 19, use theuse()hook instead.
- Find
- org.openrewrite.react.19.find-deprecated-reactdom-apis
- Find deprecated ReactDOM APIs
- Finds usage of deprecated or removed ReactDOM APIs (
findDOMNode,unmountComponentAtNode,createFactory,renderToNodeStream) that were removed in React 19.
- org.openrewrite.react.19.find-element-ref
- Find
element.refaccess - Finds direct access of
element.refon React elements. In React 19,element.refis deprecated; useelement.props.refinstead.
- Find
- org.openrewrite.react.19.find-legacy-context-api
- Find legacy Context API usage
- Finds usage of the legacy Context API (
contextTypes,childContextTypes,getChildContext) that was removed in React 19. These must be migrated toReact.createContext().
- org.openrewrite.react.19.no-implicit-ref-callback-return
- Remove implicit ref callback returns
- In React 19, ref callbacks can return cleanup functions. Arrow functions with expression bodies implicitly return values, which React would interpret as cleanup functions. This recipe wraps them in block bodies.
- org.openrewrite.react.19.remove-context-provider
- Remove
Context.Providerwrapper - In React 19,
<Context.Provider>is deprecated. Render<Context>directly as a provider instead.
- Remove
- org.openrewrite.react.19.remove-forward-ref
- Remove
React.forwardRefwrapper React.forwardRefis deprecated for Function Components in React 19. This recipe removes theforwardRefwrapper and converts ref to a regular prop.
- Remove
- org.openrewrite.react.19.remove-prop-types
- Remove
propTypesassignments - Removes
Component.propTypes = \{...\}assignments. PropTypes are silently ignored in React 19.
- Remove
- org.openrewrite.react.19.remove-react-fc
- Remove
React.FCtype annotation - Removes
React.FCandFCtype annotations from functional components, moving the props type to the function parameter instead.
- Remove
- org.openrewrite.react.19.replace-act-import
- Replace
actimport from react-dom/test-utils - In React 19,
acthas been moved fromreact-dom/test-utilstoreact. This recipe updates the import statement.
- Replace
- org.openrewrite.react.19.replace-default-props
- Replace
defaultPropswith default parameter values - Converts
Component.defaultProps = \{...\}to ES6 default parameter values in function components.defaultPropsfor function components is deprecated in React 19.
- Replace
- org.openrewrite.react.19.replace-react-shallow-renderer
- Replace
react-test-renderer/shallowimport - Changes import of shallow renderer from
react-test-renderer/shallowto the standalonereact-shallow-rendererpackage, as it was removed from React 19.
- Replace
- org.openrewrite.react.19.replace-reactdom-hydrate
- Replace
ReactDOM.hydratewithhydrateRoot - Migrates from the legacy
ReactDOM.hydrate()API to thehydrateRoot()API fromreact-dom/client.
- Replace
- org.openrewrite.react.19.replace-string-ref
- Replace string refs with callback refs
- String refs are removed in React 19. This recipe converts them to callback refs.
- org.openrewrite.react.19.replace-use-form-state
- Replace
useFormStatewithuseActionState - In React 19,
useFormStatefromreact-domhas been renamed touseActionStateand moved toreact.
- Replace
- org.openrewrite.react.19.use-context-hook
- Replace
useContextwithuse - In React 19,
useContextis replaced by theuseAPI. This recipe updates both direct and namespace imports.
- Replace
- org.openrewrite.react.19.use-ref-required-initial
- Add initial value to
useRef()calls - Adds
undefinedas initial argument touseRef()calls with no arguments. Required by@types/react19.
- Add initial value to
- org.openrewrite.react.migrate.upgrade-to-react-16
- Upgrade to React 16
- Migrate deprecated APIs for React 16 compatibility. Includes PropTypes extraction, ReactDOM split, DOM factory replacement, createFactory replacement, and error boundary API updates.
- org.openrewrite.react.migrate.upgrade-to-react-17
- Upgrade to React 17
- Migrate deprecated APIs for React 17 compatibility. Includes all React 16 migrations plus lifecycle method prefixing, import cleanup, and event.persist() removal.
- org.openrewrite.react.migrate.upgrade-to-react-18
- Upgrade to React 18
- Migrate deprecated APIs for React 18 compatibility. Includes all React 16 and 17 migrations plus the createRoot API migration, removal of unstable_batchedUpdates, unmountComponentAtNode replacement, and render callback removal.
- org.openrewrite.react.migrate.upgrade-to-react-19
- Upgrade to React 19
- Migrate deprecated and removed APIs for React 19 compatibility. This includes removing forwardRef, updating Context.Provider usage, replacing useContext with use, and other breaking changes.
- org.openrewrite.react.migration.change-component-prop-value
- Change React component prop value
- Changes literal prop values on React components. Useful for library upgrades where prop values were renamed (e.g., Material-UI, Ant Design).
- org.openrewrite.react.native.view-prop-types
- Replace
View.propTypeswithViewPropTypes - Migrates deprecated
View.propTypesreferences toViewPropTypesfromdeprecated-react-native-prop-types.
- Replace
- org.openrewrite.react.refactoring.class-to-functional
- Convert class components to functional components
- Converts simple render-only class components to functional components.
- org.openrewrite.react.refactoring.create-class-to-es6
- Convert
createClassto ES6 class - Converts
React.createClass()andcreateReactClass()calls to ES6 class syntax.
- Convert
- org.openrewrite.react.refactoring.create-element-to-jsx
- Convert
createElementto JSX - Converts
React.createElement()calls to JSX syntax for improved readability.
- Convert
- org.openrewrite.react.refactoring.manual-bind-to-arrow
- Convert manual
.bind(this)to arrow functions - Converts
this.method = this.method.bind(this)in constructors to class field arrow function syntax.
- Convert manual
- org.openrewrite.react.refactoring.pure-render-mixin
- Remove
PureRenderMixin - Removes
PureRenderMixinfromReact.createClassmixins and adds an explicitshouldComponentUpdatemethod.
- Remove
- org.openrewrite.react.refactoring.sort-comp
- Sort React component methods
- Reorders React component methods to follow the recommended lifecycle ordering convention.
- org.openrewrite.react.search.FindPropUsage
- Find React prop usage
- Locates usages of a specific prop of a React component.
- org.openrewrite.react.search.FindReactComponent
- Find React component
- Locates usages of React components across the codebase including JSX elements and other references. If
componentNameisnull, finds all React components.
- org.openrewrite.react.search.find-hook-usage
- Find React hook usage
- Finds all React hook usages including built-in and custom hooks, and detects Rules of Hooks violations.
- org.openrewrite.react.search.find-prop-usage
- Find React prop usage
- Finds all prop usages on React JSX elements, with optional filtering by component and prop name.
- org.openrewrite.react.search.find-react-component
- Find React component
- Finds all usages of a specific React component including imports, JSX elements, and exports.
- org.openrewrite.react.search.find-server-rendering-usage
- Find server-side rendering API usage
- Finds usage of React server-side rendering APIs from
react-dom/serverincludingrenderToString,renderToStaticMarkup,renderToNodeStream, andrenderToStaticNodeStreamto help plan SSR migration.
- org.openrewrite.react.simplify-react-imports
- Simplify
React.xxxto direct imports - Converts
React.useState,React.useEffect, and other React namespace accesses to direct named imports.
- Simplify
rewrite-release-metromap
- io.moderne.recipe.releasemetro.FindGradleParentRelationships
- Find Gradle root project to subproject relationships
- Gradle has no parent-project concept like Maven. The closest analog is the root project of a multi-project build, so this recipe records the GAV coordinates of each subproject paired with the root project.
- io.moderne.recipe.releasemetro.FindGradleProjectIDs
- Find Gradle project IDs
- Find Gradle project IDs in build.gradle files to determine the project ID.
- io.moderne.recipe.releasemetro.FindMavenParentRelationships
- Find Maven parent relationships
- Find Maven parent POM relationships to understand project hierarchies in multi-module builds.
- io.moderne.recipe.releasemetro.FindMavenProjectIDs
- Find maven project IDs
- Find Maven group Id and artifactId in pom.xml files to determine the project ID.
- io.moderne.recipe.releasemetro.FindPotentiallyUnusedDependencies
- Find potentially unused dependencies
- Collects import information to help identify potentially unused dependencies.
- io.moderne.recipe.releasemetro.ReleaseMetroPlan
- Analyse Organization's Release Train Metro Plan
- Gathers the basic information to create and understand the organizations release train metro plan.
rewrite-spring
- io.moderne.java.jsf.MigrateToJsf_2_3
- Migrate to JSF 2.3
- Complete migration to JSF 2.3, including associated technologies like RichFaces. Updates dependencies, transforms XHTML views, and migrates Java APIs.
- io.moderne.java.jsf.richfaces.ConvertExtendedDataTableHeightToStyle
- Convert height/width attributes to
extendedDataTablestyle - Converts height and width attributes to inline style attribute for RichFaces
extendedDataTablecomponents.
- Convert height/width attributes to
- io.moderne.java.jsf.richfaces.MigrateRichFaces_4_5
- Migrate RichFaces 3.x to 4.5
- Complete RichFaces 3.x to 4.5 migration including tag renames, attribute migrations, and Java API updates.
- io.moderne.java.jsf.richfaces.update45.UpdateXHTMLTags
- Migrate RichFaces tags in
xhtmlfiles - Migrate RichFaces tags in
xhtmlfiles to RichFaces 4.
- Migrate RichFaces tags in
- io.moderne.java.spring.boot.AddSpringBootApplication
- Add
@SpringBootApplicationclass - Adds a
@SpringBootApplicationclass containing a main method to bootify your Spring Framework application.
- Add
- io.moderne.java.spring.boot.FieldToConstructorInjection
- Convert field injection to constructor injection
- Converts
@Autowiredfield injection to constructor injection pattern. For non-final classes, adds both a no-args constructor and the autowired constructor to maintain compatibility with extending classes. Moves@Qualifierannotations to constructor parameters.
- io.moderne.java.spring.boot.IsLikelyNotSpringBoot
- Is likely not a Spring Boot project
- Marks the project if it's likely not a Spring Boot project.
- io.moderne.java.spring.boot.IsLikelySpringBoot
- Is likely a Spring Boot project
- Marks the project if it's likely a Spring Boot project.
- io.moderne.java.spring.boot.MarkEmbeddedServerProvidedForWar
- Mark embedded server as provided for WAR projects
- For WAR-packaged projects migrating to Spring Boot, add the embedded Tomcat starter with provided scope to prevent conflicts with the external servlet container.
- io.moderne.java.spring.boot.MigrateSpringFrameworkDependenciesToSpringBoot
- Migrate Spring Framework dependencies to Spring Boot
- Migrate Spring Framework dependencies to Spring Boot.
- io.moderne.java.spring.boot.ReplaceSpringFrameworkDepsWithBootStarters
- Replace Spring Framework dependencies with Spring Boot starters
- Replace common Spring Framework dependencies with their Spring Boot starter equivalents. This recipe handles the direct dependency replacement; any remaining Spring Framework dependencies that become transitively available through starters are cleaned up separately by RemoveRedundantDependencies.
- io.moderne.java.spring.boot.SpringToSpringBoot
- Migrate Spring Framework to Spring Boot
- Migrate non Spring Boot applications to the latest compatible Spring Boot release. This recipe will modify an application's build files introducing Maven dependency management for Spring Boot, or adding the Gradle Spring Boot build plugin.
- io.moderne.java.spring.boot3.AddValidToConfigurationPropertiesFields
- Add
@Validannotation to fields - In Spring Boot 3.4, validation of
@ConfigurationPropertiesclasses annotated with@Validatednow follows the Bean Validation specification, only cascading to nested properties if the corresponding field is annotated with@Valid. The recipe will add a@Validannotation to each field which has a type that has a field which is annotated with ajakarta.validation.constraints.*annotation.
- Add
- io.moderne.java.spring.boot3.CommentDeprecations
- Comment deprecated methods in Spring 3.4
- Spring Boot 3.4 deprecates methods that are not commonly used or need manual interaction.
- io.moderne.java.spring.boot3.CommentOnMockAndSpyBeansInConfigSpring34
- Comment on
@MockitoSpyBeanand@MockitoBeanin@Configuration - Deprecated: use
io.moderne.java.spring.boot3.ReplaceMockitoBeanWithBeanMethodinstead, which rewrites the field into a working@Beanmethod rather than adding a TODO comment. As stated in Spring Docs@MockitoSpyBeanand@MockitoBeanwill only work in tests, explicitly not in@Configurationannotated classes.
- Comment on
- io.moderne.java.spring.boot3.ConditionalOnAvailableEndpointMigrationSpring34
- Migrate
ConditionalOnAvailableEndpointfor Spring Boot 3.4 - Migrate
@ConditionalOnAvailableEndpoint(EndpointExposure.CLOUD_FOUNDRY)to@ConditionalOnAvailableEndpoint(EndpointExposure.WEB)for Spring Boot 3.4.
- Migrate
- io.moderne.java.spring.boot3.MigrateAbstractDiscoveredEndpointConstructor
- Migrate
AbstractDiscoveredEndpointdeprecated constructor - The boolean-parameter constructor of
AbstractDiscoveredEndpointhas been deprecated in Spring Boot 3.4. This recipe transforms it to use the new constructor with anAccessparameter.
- Migrate
- io.moderne.java.spring.boot3.MigrateAbstractExposableEndpointConstructor
- Migrate
AbstractExposableEndpointdeprecated constructor - The boolean-parameter constructor of
AbstractExposableEndpointhas been deprecated in Spring Boot 3.4. This recipe transforms it to use the new constructor with anAccessparameter instead of booleanenableByDefault.
- Migrate
- io.moderne.java.spring.boot3.MigrateEndpointAnnotationAccessValueSpring34
- Migrate
@EndpointsdefaultAccessvalue - Since Spring Boot 3.4 the
@Endpointaccess configuration values are no longertrue|falsebutnone|read-only|unrestricted.
- Migrate
- io.moderne.java.spring.boot3.MigrateEndpointDiscovererConstructor
- Migrate
EndpointDiscovererdeprecated constructor - The 4-parameter constructor of
EndpointDiscovererhas been deprecated in Spring Boot 3.4. This recipe transforms it to use the new 5-parameter constructor with an additional Collection parameter.
- Migrate
- io.moderne.java.spring.boot3.MigrateEntityManagerFactoryBuilderConstructor
- Migrate
EntityManagerFactoryBuilderdeprecated constructor - The constructors of
EntityManagerFactoryBuilderhave been deprecated in Spring Boot 3.4. This recipe transforms them to use the new constructor with a Function parameter for property mapping.
- Migrate
- io.moderne.java.spring.boot3.MigrateJmxEndpointDiscovererConstructor
- Migrate
JmxEndpointDiscovererdeprecated constructor - The 4-parameter constructor of
JmxEndpointDiscovererhas been deprecated in Spring Boot 3.4. This recipe transforms it to use the new 5-parameter constructor with an additional Collection parameter.
- Migrate
- io.moderne.java.spring.boot3.MigrateRestTemplateToRestClient
- Migrate
RestTemplatetoRestClient - Migrates Spring's
RestTemplateto the modernRestClientAPI introduced in Spring Framework 6.1.RestClientprovides a fluent, synchronous API that is the recommended approach for new development. This recipe converts constructor calls, type declarations, and common method invocations (getForObject,getForEntity,postForObject,postForEntity,patchForObject,put,delete,headForHeaders,postForLocation,optionsForAllow,exchange) to theirRestClientequivalents.
- Migrate
- io.moderne.java.spring.boot3.MigrateWebEndpointDiscovererConstructor
- Migrate WebEndpointDiscoverer 6-parameter constructor to 8-parameter
- The 6-parameter constructor of
WebEndpointDiscovererhas been deprecated in Spring Boot 3.3. This recipe adds two new parameters (AdditionalPathsMapperandOperationFilter<WebOperation>) to the constructor and updates the Bean method signature to inject them asObjectProvidertypes.
- io.moderne.java.spring.boot3.RemoveDeprecatedConditions
- Remove Spring Boot 3.5 deprecated conditions
- Replace Spring Boot 3.5 deprecated condition classes with their corresponding conditional annotations.
- io.moderne.java.spring.boot3.RemoveReplaceNoneFromAutoConfigureTestDatabase
- Remove
Replace.NONEfrom@AutoConfigureTestDatabase Replace.NONEis the default value for@AutoConfigureTestDatabasesince Spring Boot 3.4.
- Remove
- io.moderne.java.spring.boot3.RemoveTestRestTemplateEnableRedirectsOptionRecipe
- Remove
TestRestTemplate.HttpClientOption.ENABLE_REDIRECTSoption - The
TestRestTemplatenow uses the same follow redirects settings as the regular RestTemplate. TheHttpOption.ENABLE_REDIRECTSoption has also been deprecated. This recipe removes the option from theTestRestTemplateconstructor arguments.
- Remove
- io.moderne.java.spring.boot3.ReplaceConditionalOutcomeInverse
- Replace ConditionOutcome.inverse() with constructor
- Replace deprecated
ConditionOutcome.inverse(ConditionOutcome outcome)calls withnew ConditionOutcome(!outcome.isMatch(), outcome.getConditionMessage()).
- io.moderne.java.spring.boot3.ReplaceDeprecatedKafkaConnectionDetailsBootstrapServerGetters
- Replace deprecated
KafkaConnectionDetailsbootstrap server methods - Replace deprecated
KafkaConnectionDetailsbootstrap server methods with chained calls. For example,getProducerBootstrapServers()becomesgetProducer().getBootstrapServers().
- Replace deprecated
- io.moderne.java.spring.boot3.ReplaceDeprecatedThreadPoolTaskSchedulerConstructor
- Replace deprecated ThreadPoolTaskSchedulerBuilder 5-argument constructor
- The 5-parameter constructor of
ThreadPoolTaskSchedulerBuilderhas been deprecated in Spring Boot 3.5. This recipe transforms it to use the builder pattern instead, omitting null values and defaults.
- io.moderne.java.spring.boot3.ReplaceKafkaTransactionManagerSetter
- Use
kafkaAwareTransactionManagersetter - Replace deprecated
ContainerProperties#setTransactionManager(org.springframework.transaction.PlatformTransactionManager)method withContainerProperties#setKafkaAwareTransactionManager(org.springframework.kafka.transaction.KafkaAwareTransactionManager). The method will be replaced only if its argument has the typeKafkaAwareTransactionManager.
- Use
- io.moderne.java.spring.boot3.ReplaceMockitoBeanWithBeanMethod
- Replace
@MockitoBeanand@MockitoSpyBeanwith@Beanmethods in@Configurationclasses @MockitoBeanand@MockitoSpyBeanonly work in test classes, not in@Configurationclasses. This recipe converts annotated fields into@Beanmethods usingMockito.mock()orMockito.spy().
- Replace
- io.moderne.java.spring.boot3.ReplaceTaskExecutorNameByApplicationTaskExecutorName
- Use bean name
applicationTaskExecutorinstead oftaskExecutor - Spring Boot 3.5 removed the bean name
taskExecutor. Where this bean name is used, the recipe replaces the bean name toapplicationTaskExecutor. This also includes instances where the developer provided their own bean namedtaskExecutor. This also includes scenarios where JSR-250's@Resourceannotation is used.
- Use bean name
- io.moderne.java.spring.boot3.ResolveDeprecationsSpringBoot_3_3
- Resolve Deprecations in Spring Boot 3.3
- Migrates Deprecations in the Spring Boot 3.3 Release. Contains the removal of
DefaultJmsListenerContainerFactoryConfigurer.setObservationRegistryand adds new parameter ofWebEndpointDiscovererconstructor.
- io.moderne.java.spring.boot3.ResolveTaskExecutorFromContext
- Replace
taskExecutorwithapplicationTaskExecutor - Use bean name
applicationTaskExecutorinstead oftaskExecutorwhen resolvingTaskExecutorBean from application context.
- Replace
- io.moderne.java.spring.boot3.SpringBoot34Deprecations
- Migrate Spring Boot 3.4 deprecated classes and methods
- Migrate deprecated classes and methods that have been marked for removal in Spring Boot 4.0. This includes constructor changes for
EntityManagerFactoryBuilder,HikariCheckpointRestoreLifecycle, and various actuator endpoint discovery classes.
- io.moderne.java.spring.boot3.SpringBoot35Deprecations
- Migrate Spring Boot 3.5 deprecated classes and methods
- Migrate deprecated classes and methods that have been marked for removal in Spring Boot 3.5.
- io.moderne.java.spring.boot3.SpringBoot3BestPractices
- Spring Boot 3.5 best practices
- Applies best practices to Spring Boot 3.5+ applications.
- io.moderne.java.spring.boot3.SpringBootProperties_3_4
- Migrate
@EndpointSecurity properties to 3.4 (Moderne Edition) - Migrate the settings for Spring Boot Management Endpoint Security from
true|falsetoread-only|none.
- Migrate
- io.moderne.java.spring.boot3.UpdateOpenTelemetryResourceAttributes
- Update OpenTelemetry resource attributes
- The
service.groupresource attribute has been deprecated for OpenTelemetry in Spring Boot 3.5. Consider using alternative attributes or remove the deprecated attribute.
- io.moderne.java.spring.boot3.UpgradeGradle7Spring34
- Upgrade Gradle to 7.6.4+ for Spring Boot 3.4
- Spring Boot 3.4 requires Gradle 7.6.4.
- io.moderne.java.spring.boot3.UpgradeGradle8Spring34
- Upgrade Gradle 8 to 8.4+ for Spring Boot 3.4
- Spring Boot 3.4 requires Gradle 8.4+.
- io.moderne.java.spring.boot3.UpgradeMyBatisToSpringBoot_3_4
- Upgrade MyBatis to Spring Boot 3.4
- Upgrade MyBatis Spring modules to a version corresponding to Spring Boot 3.4.
- io.moderne.java.spring.boot3.UpgradeMyBatisToSpringBoot_3_5
- Upgrade MyBatis to Spring Boot 3.5
- Upgrade MyBatis Spring modules to a version corresponding to Spring Boot 3.5.
- io.moderne.java.spring.boot3.UpgradeSpringBoot_3_4
- Migrate to Spring Boot 3.4 (Moderne Edition)
- Migrate applications to the latest Spring Boot 3.4 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions. This recipe will also chain additional framework migrations (Spring Framework, Spring Data, etc) that are required as part of the migration to Spring Boot 3.4.
- io.moderne.java.spring.boot3.UpgradeSpringBoot_3_5
- Migrate to Spring Boot 3.5 (Moderne Edition)
- Migrate applications to the latest Spring Boot 3.5 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions. This recipe will also chain additional framework migrations (Spring Framework, Spring Data, etc) that are required as part of the migration to Spring Boot 3.5.
- io.moderne.java.spring.boot3.UpgradeSpringCloudAWSToSpringBoot_3_4
- Upgrade Spring Cloud AWS to Spring Boot 3.4 compatible version
- Upgrade the Spring Cloud AWS dependency to a version compatible with Spring Boot 3.4.
- io.moderne.java.spring.boot3.UpgradeSpringKafka_3_3
- Migrate to Spring Kafka 3.3
- Migrate applications to the latest Spring Kafka 3.3 release.
- io.moderne.java.spring.boot4.AddAutoConfigureMockMvc
- Add
@AutoConfigureMockMvcto@SpringBootTestclasses usingMockMvc - Adds
@AutoConfigureMockMvcannotation to classes annotated with@SpringBootTestthat useMockMvc.
- Add
- io.moderne.java.spring.boot4.AddFlywayStarters
- Add Flyway starters
- Adds spring-boot-starter-flyway and spring-boot-starter-flyway-test dependencies when Flyway usage is detected in the module.
- io.moderne.java.spring.boot4.AddJackson2ForJerseyJson
- Add Jackson2 for Jersey using JSON
- Check whether a module uses Jersey on combination with JSON and adds the needed
spring-boot-jacksondependency and conditionallyspring-boot-jackson2dependency.
- io.moderne.java.spring.boot4.AddLenientMockitoSettings
- Add
@MockitoSettings(strictness = Strictness.LENIENT)for@MockitoBeantests - When migrating from
@MockBeanto@MockitoBean, the implicit LENIENT Mockito strictness from Spring Boot'sMockitoPostProcessoris lost. If@ExtendWith(MockitoExtension.class)is present, Mockito enforces STRICT_STUBS by default, causingUnnecessaryStubbingExceptionfor tests with unused stubs. This recipe adds@MockitoSettings(strictness = Strictness.LENIENT)to preserve the original behavior.
- Add
- io.moderne.java.spring.boot4.AddLiquibaseStarters
- Add Liquibase starters
- Adds spring-boot-starter-liquibase and spring-boot-starter-liquibase-test dependencies when Liquibase usage is detected in the module.
- io.moderne.java.spring.boot4.AddModularStarters
- Add Spring Boot 4.0 modular starters
- Add Spring Boot 4.0 starter dependencies based on package usage. Note: Higher-level starters (like data-jpa) include lower-level ones (like jdbc) transitively, so only the highest-level detected starter is added for each technology.
- io.moderne.java.spring.boot4.AddMongoDbRepresentationProperties
- Add MongoDB representation properties for UUID and BigDecimal
- Adds the 'spring.mongodb.representation.uuid' property with value 'standard' and the 'spring.data.mongodb.representation.big-decimal' property with the value 'decimal128' to Spring configuration files when a MongoDB dependency is detected.
- io.moderne.java.spring.boot4.AddMssqlKerberosJaasConfig
- Add
useDefaultJaasConfig=trueto MSSQL Kerberos JDBC URLs - For MSSQL JDBC connections using Kerberos authentication (
authenticationScheme=JavaKerberosorintegratedSecurity=true), addsuseDefaultJaasConfig=trueto the connection string. This is required for compatibility with Keycloak 26.4+ which changes JAAS configuration handling.
- Add
- io.moderne.java.spring.boot4.AddValidationStarterDependency
- Add
spring-boot-starter-validationdependency - In Spring Boot 4, validation is no longer auto-included from the web starter. This recipe adds the
spring-boot-starter-validationdependency when Jakarta Validation annotations are used in the project.
- Add
- io.moderne.java.spring.boot4.AddWithHttpClientDefaultsToReactorBuilders
- Preserve system-proxy defaults on Reactor HTTP client builders
- Spring Boot 4.1 no longer applies
proxyWithSystemProperties()by default onReactorClientHttpRequestFactoryBuilderandReactorClientHttpConnectorBuilder. This recipe appends.withHttpClientDefaults()to chains starting atClientHttpRequestFactoryBuilder.reactor()orClientHttpConnectorBuilder.reactor()to restore the previous behavior. Chains that already callwithHttpClientDefaults(..)orproxyWithSystemProperties(..)are left untouched.
- io.moderne.java.spring.boot4.AdoptJackson3
- Adopt Jackson 3
- Adopt Jackson 3 which is supported by Spring Boot 4 and Jackson 2 support is deprecated.
- io.moderne.java.spring.boot4.FlagDeprecatedReactorNettyHttpClientMapper
- Flag deprecated ReactorNettyHttpClientMapper for migration
- Adds a TODO comment to classes implementing the deprecated
ReactorNettyHttpClientMapperinterface. Migration toClientHttpConnectorBuilderCustomizer<ReactorClientHttpConnectorBuilder>requires wrapping the HttpClient configuration inbuilder.withHttpClientCustomizer(...).
- io.moderne.java.spring.boot4.InsertPropertyMapperAlwaysMethodInvocation
- Preserve
PropertyMappernull-passing behavior - Spring Boot 4.0 changes the
PropertyMapperbehavior so thatfrom()no longer callsto()when the source value isnull. This recipe inserts.always()before terminal mapping methods to preserve the previous behavior. Chains that already contain.whenNonNull()or.alwaysApplyingWhenNonNull()are skipped, as they explicitly opted into null-skipping behavior which is now the default.
- Preserve
- io.moderne.java.spring.boot4.MigrateAutoConfigureMockMvcHtmlUnit
- Migrate
@AutoConfigureMockMvcHtmlUnit attributes to nested@HtmlUnit - Spring Boot 4 moved
webClientEnabledandwebDriverEnabledon@AutoConfigureMockMvcunder a nested@HtmlUnitannotation aswebClientandwebDriver, and relocated the annotation toorg.springframework.boot.webmvc.test.autoconfigure. This recipe rewrites the attribute syntax and relocates the annotation in one step, so it must run before any package-relocation recipe touches@AutoConfigureMockMvc.
- Migrate
- io.moderne.java.spring.boot4.MigrateHazelcastSpringSession
- Migrate Spring Session Hazelcast to Hazelcast Spring Session
- Spring Boot 4.0 removed direct support for Spring Session Hazelcast. The Hazelcast team now maintains their own Spring Session integration. This recipe changes the dependency from
org.springframework.session:spring-session-hazelcasttocom.hazelcast.spring:hazelcast-spring-sessionand updates the package fromorg.springframework.session.hazelcasttocom.hazelcast.spring.session.
- io.moderne.java.spring.boot4.MigrateJsonFactoryDecorator
- Migrate
JsonFactoryDecoratortoTokenStreamFactoryBuilderDecorator - Migrates classes that implement
net.logstash.logback.decorate.JsonFactoryDecorator(removed in logstash-logback-encoder 9.0) to implementTokenStreamFactoryBuilderDecorator<JsonFactory, JsonFactoryBuilder>. Thedecorate(JsonFactory)method is rewritten to take and return aJsonFactoryBuilder, and mutator calls inside the body (e.g.setCharacterEscapes) are folded into the equivalent builder calls (e.g.characterEscapes) where a mapping is known. Unmapped mutators are kept by name with aTODOcomment for manual review.
- Migrate
- io.moderne.java.spring.boot4.MigrateLayertoolsToTools_4_1
- Migrate
layertoolsjarmode totools - The
layertoolsjar mode was deprecated in Spring Boot 3.3 and removed in Spring Boot 4.1. Replace-Djarmode=layertoolsinvocations (commonly found in Dockerfiles and shell scripts) with-Djarmode=tools, which provides equivalent and expanded functionality.
- Migrate
- io.moderne.java.spring.boot4.MigrateMockMvcToAssertJ
- Migrate MockMvc to AssertJ assertions
- Migrates Spring MockMvc tests from Hamcrest-style
andExpect()assertions to AssertJ-style fluent assertions. ChangesMockMvctoMockMvcTesterand converts assertion chains.
- io.moderne.java.spring.boot4.MigratePropertyMapper
- Migrate
PropertyMapperAPI for Spring Boot 4.0 - Migrates
PropertyMapperusage to accommodate Spring Boot 4.0 behavioral changes. In Boot 4.0,PropertyMapper.from()no longer callsto()when the source value isnull. This recipe first inserts.always()on bare chains to preserve null-passing behavior, then removes the now-redundant.whenNonNull()and.alwaysApplyingWhenNonNull()calls. Guarded by a Spring Boot < 4.0 precondition so that on subsequent recipe cycles (after the version is bumped by the parent migration recipe), this recipe becomes a no-op — preventing it from incorrectly adding.always()to chains that just had.whenNonNull()stripped.
- Migrate
- io.moderne.java.spring.boot4.MigrateRestAssured
- Add explicit version for REST Assured
- REST Assured is no longer managed by Spring Boot 4.0. This recipe adds an explicit version to REST Assured dependencies.
- io.moderne.java.spring.boot4.MigrateSpringRetry
- Migrate Spring Retry to Spring Resilience
- Handle spring-retry no longer managed by Spring Boot and the possible migration to Spring Core Resilience.
- io.moderne.java.spring.boot4.MigrateSpringRetryToSpringFramework7
- Migrate
spring-retryto Spring Framework resilience - Migrate
spring-retrys@Retryableand@Backoffannotation to Spring Framework 7 Resilience annotations.
- Migrate
- io.moderne.java.spring.boot4.MigrateToModularStarters
- Migrate to Spring Boot 4.0 modular starters (Moderne Edition)
- Adds Spring Boot 4.0 modular starter dependencies based on package usage and rewrites the classic starters to the minimal
spring-boot-starter/spring-boot-starter-test. The minimal starter is retained so that modules whose code only references core Spring annotations (e.g.@SpringBootApplication,@Configuration,@Component) still compile after migration.
- io.moderne.java.spring.boot4.MigrateToModularStarters_4_1
- Migrate to Spring Boot 4.1 modular starters
- Add Spring Boot 4.1 starter dependencies for modules introduced in 4.1 (gRPC server, gRPC client, and Spring Batch with MongoDB support). This recipe complements
MigrateToModularStartersfrom 4.0 and only adds the new starters; it does not rewrite or remove anything else.
- io.moderne.java.spring.boot4.MockMvcAssertionsToAssertJ
- Migrate MockMvc
andExpect()chains to AssertJ assertions - Converts MockMvc Hamcrest-style
andExpect()assertion chains to AssertJ-style fluent assertions usingassertThat(). Handles status, content, JSON path, header, redirect, and forward assertions.
- Migrate MockMvc
- io.moderne.java.spring.boot4.MockMvcRequestBuildersToMockMvcTester
- Migrate
MockMvcRequestBuilderstoMockMvcTesterrequest methods - Converts
mockMvcTester.perform(get("/api").param("k","v"))tomockMvcTester.get().uri("/api").param("k","v"), removing theperform()wrapper andMockMvcRequestBuildersstatic method calls.
- Migrate
- io.moderne.java.spring.boot4.MockMvcToMockMvcTester
- Migrate
MockMvctoMockMvcTester - Converts
MockMvcfields and initialization toMockMvcTester. Changes field types, renames fields frommockMvctomockMvcTester, and convertsMockMvcBuilders.standaloneSetup().build()toMockMvcTester.of()andMockMvcBuilders.webAppContextSetup().build()toMockMvcTester.from().
- Migrate
- io.moderne.java.spring.boot4.ModuleHasMonolithicStarter
- Module has monolithic Spring Boot starter
- Precondition that matches modules with the monolithic Spring Boot starters that need to be migrated to modular starters. Matches the production monolithic spring-boot-starter and spring-boot-starter-classic, but not specific modular starters like spring-boot-starter-test or spring-boot-starter-ldap.
- io.moderne.java.spring.boot4.ModuleStarterRelocations
- Spring Boot 4.0 Module Starter Relocations
- Relocate types and packages for Spring Boot 4.0 modular starters.
- io.moderne.java.spring.boot4.ModuleUsesFlyway
- Module uses Flyway
- Precondition that marks all files in a module if Flyway usage is detected. Detection is based on having a Flyway dependency, using Flyway types, or having migration files.
- io.moderne.java.spring.boot4.ModuleUsesLiquibase
- Module uses Liquibase
- Precondition that marks all files in a module if Liquibase usage is detected. Detection is based on having a Liquibase dependency, using Liquibase types, or having changelog files.
- io.moderne.java.spring.boot4.RemoveContentNegotiationFavorPathExtension
- Remove
ContentNegotiationConfigurer.favorPathExtension()calls - Spring Framework 7 removed
favorPathExtension()fromContentNegotiationConfigurer. Path extension content negotiation is no longer supported. This recipe removes calls tofavorPathExtension().
- Remove
- io.moderne.java.spring.boot4.RemoveDevtoolsLiveReloadProperties_4_1
- Comment out deprecated DevTools LiveReload properties
- Spring Boot 4.1.0-M3 deprecated the LiveReload feature in DevTools with no replacement. The feature still functions in 4.1, so this recipe comments out
spring.devtools.livereload.*properties (rather than deleting them) to flag the deprecation while leaving the values recoverable.
- io.moderne.java.spring.boot4.RemoveGradleUberJarLoaderImplementationConfig
- Remove
loaderImplementationfrom Gradle - Removes the Spring Boot Uber-Jar
loaderImplementationconfiguration from Gradle build files.
- Remove
- io.moderne.java.spring.boot4.RemoveHttpMessageConvertersAutoConfigurationReferences
- Remove
HttpMessageConvertersAutoConfigurationreferences - Removes references to the deprecated
HttpMessageConvertersAutoConfigurationclass which was removed in Spring Boot 4.0. For@AutoConfigureAfterand@AutoConfigureBeforeannotations, the reference is removed. For@Importannotations, a TODO comment is added since manual migration may be required.
- Remove
- io.moderne.java.spring.boot4.RemoveKafkaPropertiesSslBundlesParameter
- Remove
SslBundlesparameter fromKafkaPropertiesbuild methods - In Spring Boot 4.0, the
SslBundlesparameter was removed fromKafkaProperties.buildProducerProperties,buildConsumerProperties,buildAdminProperties, andbuildStreamsProperties. This recipe removes the argument from method calls.
- Remove
- io.moderne.java.spring.boot4.RemoveSpringPulsarReactive
- Remove Spring Pulsar Reactive support
- Spring Boot 4.0 removed support for Spring Pulsar Reactive as it is no longer maintained. This recipe removes the Spring Pulsar Reactive dependencies.
- io.moderne.java.spring.boot4.RemoveZipkinAutoConfigurationExclude
- Remove
ZipkinAutoConfiguration - Zipkin is no longer auto-configured by default in Spring Boot 4.0; remove references to it from exclusions on annotations.
- Remove
- io.moderne.java.spring.boot4.ReplaceDeprecatedAutoconfigureMongoApi
- Replace deprecated
org.springframework.boot.autoconfigure.mongoAPI - Replace deprecated
org.springframework.boot.autoconfigure.mongoAPI.
- Replace deprecated
- io.moderne.java.spring.boot4.ReplaceDeprecatedDockerApi
- Replace deprecated
DockerApi - Replaces deprecated
DockerApiconstructors and configuration methods with their modern equivalents.
- Replace deprecated
- io.moderne.java.spring.boot4.ReplaceDeprecatedRequestMatcherProvider
- Replace deprecated RequestMatcherProvider with new API
- Replaces the deprecated
org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProviderwithorg.springframework.boot.security.autoconfigure.actuate.web.servlet.RequestMatcherProvider. The new interface adds anHttpMethodparameter to thegetRequestMatchermethod.
- io.moderne.java.spring.boot4.ReplaceDeprecatedThreadPoolTaskSchedulerBuilderApi
- Replace deprecated
ThreadPoolTaskSchedulerBuilderconstructor - Replaces the deprecated 5-argument constructor of
ThreadPoolTaskSchedulerBuilderwith the builder pattern.
- Replace deprecated
- io.moderne.java.spring.boot4.SimplifyOptionalConfigurationPropertiesNullChecks
- Simplify null checks on
Optional@ConfigurationPropertiesparameters - Spring Boot 4.1 changes constructor-bound
@ConfigurationPropertiesso thatOptional<T>parameters bind toOptional.empty()rather thannull. This recipe replaces== null/!= nullchecks against such parameters (or same-named fields in the binding constructor's class) with the constant they will always evaluate to, then runsSimplifyConstantIfBranchExecutionto remove the dead branches.
- Simplify null checks on
- io.moderne.java.spring.boot4.SpringBoot4BestPractices
- Spring Boot 4.0 best practices
- Applies best practices to Spring Boot 4.+ applications.
- io.moderne.java.spring.boot4.SpringBootProperties_4_1
- Migrate Spring Boot properties to 4.1
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.boot4.UpgradeMyBatisToSpringBoot_4_0
- Upgrade MyBatis to Spring Boot 4.0
- Upgrade MyBatis Spring modules to a version corresponding to Spring Boot 4.0.
- io.moderne.java.spring.boot4.UpgradeSpringBoot_4_0
- Migrate to Spring Boot 4.0 (Moderne Edition)
- Migrate applications to the latest Spring Boot 4.0 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions. This recipe will also chain additional framework migrations (Spring Framework, Spring Data, etc) that are required as part of the migration to Spring Boot 4.0.
- io.moderne.java.spring.boot4.UpgradeSpringBoot_4_1
- Migrate to Spring Boot 4.1
- Migrate applications to the latest Spring Boot 4.1 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions. This recipe will also chain additional framework migrations (Spring Framework, Spring Data, etc) that are required as part of the migration to Spring Boot 4.1.
- io.moderne.java.spring.boot4.UpgradeSpringKafka_4_0
- Migrate to Spring Kafka 4.0
- Migrate applications to Spring Kafka 4.0. This includes removing deprecated configuration options that are no longer supported.
- io.moderne.java.spring.cloud2020.SpringCloudProperties_2020
- Migrate Spring Cloud properties to 2020
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud2021.SpringCloudProperties_2021
- Migrate Spring Cloud properties to 2021
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud2022.SpringCloudProperties_2022
- Migrate Spring Cloud properties to 2022
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud2023.SpringCloudProperties_2023
- Migrate Spring Cloud properties to 2023
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud2024.SpringCloudProperties_2024
- Migrate Spring Cloud properties to 2024
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud2025.SpringCloudProperties_2025
- Migrate Spring Cloud properties to 2025
- Migrate properties found in
application.propertiesandapplication.yml.
- io.moderne.java.spring.cloud20251.SpringCloudProperties_2025_1
- Migrate Spring Cloud properties to 2025.1
- Migrate properties found in
application.propertiesandapplication.ymlfor Spring Cloud 2025.1 (Oakwood). This includes the stubrunner property prefix migration fromstubrunner.tospring.cloud.contract.stubrunner..
- io.moderne.java.spring.cloud20251.UpgradeSpringCloud_2025_1
- Upgrade to Spring Cloud 2025.1
- Upgrade to Spring Cloud 2025.1 (Oakwood). This release is based on Spring Framework 7 and Spring Boot 4. Each Spring Cloud project has been updated to version 5.0.0.
- io.moderne.java.spring.framework.AddSetUseSuffixPatternMatch
- Add
setUseSuffixPatternMatch(true)in Spring MVC configuration - In Spring Framework 5.2.4 and earlier, suffix pattern matching was enabled by default. This meant a controller method mapped to
/userswould also match/users.json,/users.xml, etc. Spring Framework 5.3 deprecated this behavior and changed the default to false. This recipe addssetUseSuffixPatternMatch(true)toWebMvcConfigurerimplementations to preserve the legacy behavior during migration. Note: This only applies to Spring MVC; Spring WebFlux does not support suffix pattern matching.
- Add
- io.moderne.java.spring.framework.AddSetUseSuffixPatternMatchIfPreSpring53
- Add
setUseSuffixPatternMatch(true)for pre-Spring Framework 5.3 projects - Only adds
setUseSuffixPatternMatch(true)when the project is on Spring Framework < 5.3, where suffix pattern matching was enabled by default. Projects already on 5.3+ have been running with the new default (false) and should not get this configuration added.
- Add
- io.moderne.java.spring.framework.FindDeprecatedPathMatcherUsage
- Find deprecated
PathMatcherusage - In Spring Framework 7.0,
PathMatcherandAntPathMatcherare deprecated in favor ofPathPatternParser. This recipe finds usages of the deprecatedAntPathMatcherclass that may require manual migration toPathPatternParser.
- Find deprecated
- io.moderne.java.spring.framework.FlagSuffixPatternMatchUsage
- Flag deprecated suffix pattern matching usage for manual review
- Handles deprecated
setUseSuffixPatternMatch()andsetUseRegisteredSuffixPatternMatch()calls. When suffix pattern matching is explicitly enabled, adds TODO comments and search markers since there is no automatic migration path. When explicitly disabled, the call is safely removed sincefalseis already the default since Spring Framework 5.3.
- io.moderne.java.spring.framework.IsLikelySpringFramework
- Is likely a Spring Framework project
- Marks the project if it's likely a Spring Framework project.
- io.moderne.java.spring.framework.JaxRsToSpringWeb
- Convert JAX-RS annotations to Spring Web
- Converts JAX-RS annotations such as
@Path,@GET,@POST, etc., to their Spring Web equivalents like@RestController,@RequestMapping,@GetMapping, etc.
- io.moderne.java.spring.framework.MigrateConverterSetObjectMapper
- Replace
setObjectMapperwith constructor injection - Folds
setObjectMappercalls onMappingJackson2HttpMessageConverterinto the constructor. If the converter is instantiated in the same block with no other invocations, the setter call is replaced with constructor injection. Otherwise, a TODO comment is added.
- Replace
- io.moderne.java.spring.framework.MigrateDefaultResponseErrorHandler
- Migrate
DefaultResponseErrorHandler.handleErrormethod signature - Migrates overridden
handleError(ClientHttpResponse response)methods to the new signaturehandleError(URI url, HttpMethod method, ClientHttpResponse response)in classes extendingDefaultResponseErrorHandler. The old single-argument method was removed in Spring Framework 7.0.
- Migrate
- io.moderne.java.spring.framework.MigrateDeprecatedBeanXmlProperties
- Migrate Bean XML properties deprecated in Spring Framework 3.0
- Migrate Bean XML properties that were deprecated in Spring Framework 3.0.
- io.moderne.java.spring.framework.MigrateFilterToOncePerRequestFilter
- Migrate
FiltertoOncePerRequestFilter - Migrates classes that implement
javax.servlet.Filter(orjakarta.servlet.Filter) to extendorg.springframework.web.filter.OncePerRequestFilter. This transformation renamesdoFiltertodoFilterInternal, changes parameter types to HTTP variants, removes manual casting, and removes emptyinit()anddestroy()methods.
- Migrate
- io.moderne.java.spring.framework.MigrateHandleErrorMethodInvocations
- Migrate
handleErrormethod invocations to new signature - Updates invocations of
handleError(ClientHttpResponse)to the newhandleError(URI, HttpMethod, ClientHttpResponse)signature introduced in Spring Framework 7.0. In test sources, example values are used. In main sources,nullis passed with a TODO comment.
- Migrate
- io.moderne.java.spring.framework.MigrateHttpHeadersMultiValueMapMethods
- Migrate
HttpHeadersmethods removed whenMultiValueMapcontract was dropped - Spring Framework 7.0 changed
HttpHeadersto no longer implementMultiValueMap. This recipe replaces removed inherited method calls:containsKey()withcontainsHeader(),keySet()withheaderNames(), andentrySet()withheaderSet().
- Migrate
- io.moderne.java.spring.framework.MigrateTrailingSlashMatch
- Migrate trailing slash matching to explicit routes
- Migrates deprecated
setUseTrailingSlashMatch()configuration removed in Spring Framework 7.0. Only adds explicit trailing slash routes when the project previously enabled trailing slash matching viasetUseTrailingSlashMatch(true). The deprecated configuration calls are always removed.
- io.moderne.java.spring.framework.ModularSpringFrameworkDependencies
- Add Spring Framework modular dependencies
- Adds Spring Framework modular dependencies based on package usage, replacing legacy monolithic
org.springframework:spring.
- io.moderne.java.spring.framework.NullableSpringWebParameters
- Add
@Nullableto optional Spring web parameters - In Spring Boot 4, JSpecify's
@Nullableannotation should be used to indicate that a parameter can be null. This recipe adds@Nullableto parameters annotated with@PathVariable(required = false)or@RequestParam(required = false)and removes the now-redundantrequired = falseattribute.
- Add
- io.moderne.java.spring.framework.RemoveDeprecatedPathMappingOptions
- Migrate deprecated path mapping options
- Migrates deprecated path mapping configuration options that have been removed in Spring Framework 7.0. For trailing slash matching, this recipe adds explicit dual routes to controller methods before removing the deprecated configuration. For suffix pattern matching, this recipe flags usages for manual review since there is no automatic migration path. Path extension content negotiation options are removed as they should be replaced with query parameter-based negotiation.
- io.moderne.java.spring.framework.RemoveEmptyPathMatchConfiguration
- Remove empty path match configuration methods
- Removes empty
configurePathMatch(WebMvc) andconfigurePathMatching(WebFlux) method overrides. These methods may become empty after deprecated path matching options are removed.
- io.moderne.java.spring.framework.RemovePathExtensionContentNegotiation
- Remove path extension content negotiation methods
- Remove calls to
favorPathExtension()andignoreUnknownPathExtensions()onContentNegotiationConfigurer. These methods and the underlyingPathExtensionContentNegotiationStrategywere removed in Spring Framework 7.0. Path extension content negotiation was deprecated due to URI handling issues. Use query parameter-based negotiation withfavorParameter(true)as an alternative.
- io.moderne.java.spring.framework.RemoveSetPathMatcherCall
- Remove deprecated
setPathMatcher()calls - In Spring Framework 7.0,
PathMatcherandAntPathMatcherare deprecated in favor ofPathPatternParser, which has been the default in Spring MVC since 6.0. This recipe removes calls tosetPathMatcher(new AntPathMatcher())since they are now redundant. The defaultPathPatternParserprovides better performance through pre-parsed patterns.
- Remove deprecated
- io.moderne.java.spring.framework.ReplaceControllerWithRestController
- Replace
@Controllerwith@RestController - When a class is annotated with
@Controllerand either the class itself or all of its handler methods are annotated with@ResponseBody, the class can use@RestControllerinstead. This removes the need for individual@ResponseBodyannotations.
- Replace
- io.moderne.java.spring.framework.UpgradeSpringFramework_3_0
- Migrate to Spring Framework 3.x
- Migrate applications to the latest Spring Framework 3 release, pulling in additional proprietary Moderne recipes.
- io.moderne.java.spring.framework.UpgradeSpringFramework_5_3
- Migrate to Spring Framework 5.3 (Moderne Edition)
- Migrate applications to the latest Spring Framework 5.3 release, pulling in additional proprietary Moderne recipes.
- io.moderne.java.spring.framework.beansxml.BeansXmlToConfiguration
- Migrate
beans.xmlto Spring Framework configuration class - Converts Java/Jakarta EE
beans.xmlconfiguration files to Spring Framework@Configurationclasses.
- Migrate
- io.moderne.java.spring.framework.jsf23.MigrateFacesConfig
- Migrate JSF variable-resolver to el-resolver
- Migrates JSF faces-config.xml from namespaces, tags and values that was deprecated in JSF 1.2 and removed in later versions, to the JSF 2.3 compatible constructs.
- io.moderne.java.spring.framework.webxml.FindWelcomeFileConfiguration
- Add landing page controller for welcome file configuration
- Generates a
LandingPageControllerwhenwelcome-file-listis found inweb.xmlorcontext-rootinjboss-web.xml. When migrating to Spring Framework 5.3+, applications that rely on these server-side landing page configurations need a@Controllerwith a@RequestMappingfor/to avoid 404 errors, as Spring MVC can take over the root mapping. Skips generation if a controller already maps to/.
- io.moderne.java.spring.framework.webxml.WebXmlToWebApplicationInitializer
- Migrate
web.xmltoWebApplicationInitializer - Migrate
web.xmltoWebApplicationInitializerfor Spring applications. This allows for programmatic configuration of the web application context, replacing the need for XML-based configuration. This recipe only picks upweb.xmlfiles located in thesrc/main/webapp/WEB-INFdirectory to avoid inference with tests. It creates aWebXmlWebAppInitializerclass insrc/main/javawith respect to submodules if they contain java files. If it finds an existingWebXmlWebAppInitializer, it skips the creation.
- Migrate
- io.moderne.java.spring.framework7.AddDynamicDestinationResolverToJmsTemplate
- Explicitly set DynamicDestinationResolver on JmsTemplate
- Spring Framework 7.0 changed the default
DestinationResolverforJmsTemplatefromDynamicDestinationResolvertoSimpleDestinationResolver, which caches Session-resolved Queue and Topic instances. This recipe adds an explicit call tosetDestinationResolver(new DynamicDestinationResolver())to preserve the previous behavior. The caching behavior ofSimpleDestinationResolvershould be fine for most JMS brokers, so this explicit configuration can be removed once compatibility with the new default is verified.
- io.moderne.java.spring.framework7.AddSpringExtensionConfigForNestedTests
- Add
@SpringExtensionConfigfor nested tests - Spring Framework 7.0 changed
SpringExtensionto use test-method scopedExtensionContextinstead of test-class scoped. This can break@Nestedtest class hierarchies. Adding@SpringExtensionConfig(useTestClassScopedExtensionContext = true)restores the previous behavior.
- Add
- io.moderne.java.spring.framework7.FindOkHttp3IntegrationUsage
- Find Spring OkHttp3 integration usage
- Spring Framework 7.0 removes OkHttp3 integration classes. This recipe identifies usages of
OkHttp3ClientHttpRequestFactoryandOkHttp3ClientHttpConnectorthat need to be replaced. Consider migrating to Java's built-inHttpClientwithJdkClientHttpRequestFactoryorJdkClientHttpConnector, or to Apache HttpClient 5 withHttpComponentsClientHttpRequestFactory.
- io.moderne.java.spring.framework7.FindRemovedAPIs
- Find removed APIs in Spring Framework 7.0
- Finds usages of APIs that were removed in Spring Framework 7.0 and require manual intervention. This includes Theme support, OkHttp3 integration, and servlet view document/feed classes which have no direct automated replacement.
- io.moderne.java.spring.framework7.FindServletViewSupportUsage
- Find removed Spring servlet view classes
- Spring Framework 7.0 removes the
org.springframework.web.servlet.view.documentandorg.springframework.web.servlet.view.feedpackages. This recipe adds TODO comments to imports ofAbstractPdfView,AbstractXlsView,AbstractXlsxView,AbstractXlsxStreamingView,AbstractPdfStampView,AbstractFeedView,AbstractAtomFeedView, andAbstractRssFeedViewthat need to be replaced with direct usage of the underlying libraries (Apache POI, OpenPDF/iText, ROME) in web handlers.
- io.moderne.java.spring.framework7.FindThemeSupportUsage
- Find Spring Theme support usage
- Spring Framework 7.0 removes Theme support entirely. This recipe identifies usages of Theme-related classes like
ThemeResolver,ThemeSource, andThemeChangeInterceptorthat need to be removed or replaced with CSS-based alternatives. The Spring team recommends using CSS directly for theming functionality.
- io.moderne.java.spring.framework7.MigrateDeprecatedAPIs
- Migrate deprecated APIs removed in Spring Framework 7.0
- Migrates deprecated APIs that were removed in Spring Framework 7.0. This includes ListenableFuture to CompletableFuture migration, ContentCachingRequestWrapper constructor changes, and NestedServletException to ServletException type migration.
- io.moderne.java.spring.framework7.MigrateHttpStatusToRfc9110
- Migrate
HttpStatusenum values to RFC 9110 names - Spring Framework 7.0 aligns HttpStatus enum values with RFC 9110. This recipe replaces deprecated status code constants with their RFC 9110 equivalents:
PAYLOAD_TOO_LARGEbecomesCONTENT_TOO_LARGEandUNPROCESSABLE_ENTITYbecomesUNPROCESSABLE_CONTENT.
- Migrate
- io.moderne.java.spring.framework7.MigrateJackson2ObjectMapperBuilder
- Migrate
Jackson2ObjectMapperBuilderto mapper builder pattern - Replaces
Jackson2ObjectMapperBuilder.json().build()and similar factory methods with the corresponding Jackson mapper builder pattern (e.g.JsonMapper.builder()...build()). Setter calls on the resulting mapper are folded into the builder chain when safe, or annotated with a TODO comment when automatic migration is not possible.
- Migrate
- io.moderne.java.spring.framework7.MigrateJmsDestinationResolver
- Preserve DynamicDestinationResolver behavior for JmsTemplate
- Spring Framework 7.0 changed the default
DestinationResolverforJmsTemplatefromDynamicDestinationResolvertoSimpleDestinationResolver, which caches Session-resolved Queue and Topic instances. This recipe explicitly configuresDynamicDestinationResolverto preserve the pre-7.0 behavior. The caching behavior ofSimpleDestinationResolvershould be fine for most JMS brokers, so this explicit configuration can be removed once verified.
- io.moderne.java.spring.framework7.MigrateListenableFuture
- Migrate
ListenableFuturetoCompletableFuture - Spring Framework 6.0 deprecated
ListenableFuturein favor ofCompletableFuture. Spring Framework 7.0 removesListenableFutureentirely. This recipe migrates usages ofListenableFutureand its callbacks to useCompletableFutureandBiConsumerinstead.
- Migrate
- io.moderne.java.spring.framework7.MigrateResponseEntityGetStatusCodeValueMethod
- Migrate
ResponseEntity#getStatusCodeValue()togetStatusCode().value() - Replaces calls to
ResponseEntity#getStatusCodeValue()which was deprecated in Spring Framework 6.0 and removed in Spring Framework 7.0 withgetStatusCode().value().
- Migrate
- io.moderne.java.spring.framework7.RemoveNullabilityFromSpringHttpEntityTypeArguments
- Remove Kotlin nullability from Spring HTTP entity type arguments
- Spring Framework 7 narrowed
HttpEntity<T>(and its subtypesResponseEntityandRequestEntity) to<T : Any>. This recipe removes Kotlin's?nullable marker from the type argument of these types in declared parameterized types and in explicit method-invocation type arguments, so Kotlin sources continue to compile.
- io.moderne.java.spring.framework7.RemoveSpringJcl
- Remove spring-jcl dependency
- The
spring-jclmodule has been removed in Spring Framework 7.0 in favor of Apache Commons Logging 1.3.0. This recipe removes any explicit dependency onorg.springframework:spring-jcl. The change should be transparent for most applications, as spring-jcl was typically a transitive dependency and the logging API calls (org.apache.commons.logging.*) remain unchanged.
- io.moderne.java.spring.framework7.RenameMemberCategoryConstants
- Rename MemberCategory field constants for Spring Framework 7.0
- Renames deprecated
MemberCategoryconstants to their new names in Spring Framework 7.0.MemberCategory.PUBLIC_FIELDSis renamed toMemberCategory.INVOKE_PUBLIC_FIELDSandMemberCategory.DECLARED_FIELDSis renamed toMemberCategory.INVOKE_DECLARED_FIELDS. These renames clarify the original intent of these categories and align with the rest of the API.
- io.moderne.java.spring.framework7.RenameRequestContextJstlPresent
- Rename
RequestContext.jstPresenttoJSTL_PRESENT - Renames the protected static field
RequestContext.jstPresenttoJSTL_PRESENTin Spring Framework 7.0. This field was renamed as part of a codebase-wide effort to use uppercase for classpath-related static final field names (see https://github.com/spring-projects/spring-framework/issues/35525).
- Rename
- io.moderne.java.spring.framework7.ReplaceJUnit4SpringTestBaseClasses
- Replace JUnit 4 Spring test base classes with JUnit Jupiter annotations
- Replace
AbstractJUnit4SpringContextTestsandAbstractTransactionalJUnit4SpringContextTestsbase classes with@ExtendWith(SpringExtension.class)and@Transactionalannotations. These base classes are deprecated in Spring Framework 7.0 in favor of the SpringExtension for JUnit Jupiter.
- io.moderne.java.spring.framework7.SimplifyReflectionHintRegistration
- Simplify reflection hint registrations for Spring Framework 7.0
- Removes deprecated
MemberCategoryarguments fromregisterType()calls onReflectionHints. In Spring Framework 7.0, registering a reflection hint for a type now implies methods, constructors, and fields introspection. AllMemberCategoryvalues exceptINVOKE_*have been deprecated. This recipe removes those deprecated arguments, simplifying code likehints.reflection().registerType(MyType.class, MemberCategory.DECLARED_FIELDS)tohints.reflection().registerType(MyType.class).
- io.moderne.java.spring.framework7.UpdateGraalVmNativeHints
- Update GraalVM native reflection hints for Spring Framework 7.0
- Migrates GraalVM native reflection hints to Spring Framework 7.0 conventions. Spring Framework 7.0 adopts the unified reachability metadata format for GraalVM. This recipe renames deprecated
MemberCategoryconstants and simplifies reflection hint registrations where explicit member categories are no longer needed.
- io.moderne.java.spring.framework7.UpgradeSpringFramework_7_0
- Migrate to Spring Framework 7.0
- Migrates applications to Spring Framework 7.0. This recipe applies all necessary changes including API migrations, removed feature detection, and configuration updates.
- io.moderne.java.spring.framework7.WrapGenericMessageMapInMessageHeaders
- Wrap
GenericMessagemap argument inMessageHeaders - Wraps the
Mapargument inGenericMessageconstructors in Kotlin sources withMessageHeaders(map)to explicitly use theMessageHeadersoverload. This resolves Kotlin overload resolution ambiguity between theMapandMessageHeadersconstructor overloads.
- Wrap
- io.moderne.java.spring.hibernate.MigrateDaoSupportGetSession
- Migrate
HibernateDaoSupport#getSession()usage - Migrate
HibernateDaoSupport#getSession()usage toHibernateDaoSupport#getSessionFactory()#getCurrentSession()and annotate the methods with@Transactional.
- Migrate
- io.moderne.java.spring.hibernate.MigrateSaveOrUpdateAll
- Migrate
HibernateDaoSupport#getHibernateTemplate#saveOrUpdateAll - Migrate removed
HibernateDaoSupport#getHibernateTemplate#.saveOrUpdateAllto an iterativeHibernateDaoSupport#getHibernateTemplate#.saveOrUpdate.
- Migrate
- io.moderne.java.spring.kafka.consumer.FindKafkaListenerWithoutErrorHandling
- Find
@KafkaListenermethods without error handling - Flags
@KafkaListenermethods that lack proper error handling. Methods should have@RetryableTopic, specify anerrorHandlerin the annotation, or implement try-catch blocks for error handling.
- Find
- io.moderne.java.spring.kafka.consumer.FindMissingDltHandler
- Find
@RetryableTopicwithout@DltHandler - Flags classes that use
@RetryableTopicwithout a corresponding@DltHandlermethod. A DLT handler should be defined to process messages that have exhausted all retries.
- Find
- io.moderne.java.spring.kafka.consumer.IsKafkaConsumer
- Is likely a Kafka consumer module
- Marks the project if it's likely a Kafka consumer module.
- io.moderne.java.spring.kafka.producer.FindCustomKeyUsage
- Find
KafkaTemplate.send()with custom key - Flags
KafkaTemplate.send()calls that use a custom key (3+ arguments). Custom keys should be reviewed to ensure they provide appropriate partition distribution.
- Find
- io.moderne.java.spring.kafka.producer.IsKafkaProducer
- Is likely a Kafka producer module
- Marks the project if it's likely a Kafka producer module.
- io.moderne.java.spring.orm.SpringORM5
- Migrate to Spring ORM to 5
- Migrate applications using Spring ORM Hibernate Support to Hibernate 5 compatible version. This will enable a further migration by the Spring Framework migration past 5.
- io.moderne.java.spring.security.MigrateAcegiToSpringSecurity_5_0
- Migrate from Acegi Security 1.0.x to Spring Security 5.0
- Migrates Acegi Security 1.0.x directly to Spring Security 5.0. This recipe handles dependency changes, type renames, XML configuration updates, web.xml filter migration, and adds TODO comments for password encoders that require manual migration.
- io.moderne.java.spring.security6.MigrateAntPathRequestMatcher
- Migrate antPathRequestMatcher to pathPatternRequestMatcher
- In Spring Security 6.5,
AntPathRequestMatcheris deprecated in favor ofPathPatternRequestMatcher. This recipe migrates static method calls and constructor usage to the new pattern in both Java and Kotlin sources.
- io.moderne.java.spring.security6.UpgradeSpringSecurity_6_5
- Migrate to Spring Security 6.5 (Moderne Edition)
- Migrate applications to the latest Spring Security 6.5 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions.
- io.moderne.java.spring.security7.CommentOnSecurityContextAuthenticationInKotlin
- Comment on Kotlin usages of
SecurityContext.getAuthentication() - Spring Security 7 made
SecurityContext.getAuthentication()return@Nullable Authentication. In Kotlin this becomesAuthentication?, so existing chains likeSecurityContextHolder.getContext().authentication.credentialsno longer compile. This recipe adds a TODO comment on the line above each Kotlin statement that reads the authentication — both the explicitgetAuthentication()form and the Kotlin property form.authentication— so a developer can decide per call site whether to use a safe-call (?.) or a non-null assertion (!!).
- Comment on Kotlin usages of
- io.moderne.java.spring.security7.MigrateMvcRequestMatcher
- Migrate
MvcRequestMatchertoPathPatternRequestMatcher - In Spring Security 7.0,
MvcRequestMatcherwhich depends on the deprecatedHandlerMappingIntrospectoris removed in favor ofPathPatternRequestMatcher. This recipe migrates constructor and builder usage to the new pattern.
- Migrate
- io.moderne.java.spring.security7.MigrateOAuth2AccessTokenResponseClient
- Migrate
OAuth2AccessTokenResponseClientfromRestOperationstoRestClientbased implementations - A new set of
OAuth2AccessTokenResponseClientimplementations were introduced based onRestClient. This recipe replaces theRestOperations-based implementations which have been deprecated. TheRestClientimplementations are drop-in replacements for the deprecated implementations.
- Migrate
- io.moderne.java.spring.security7.MigrateOAuth2RestOperationsToRestClient
- Migrate OAuth2 token response client from
RestOperationstoRestClient - Migrates
setRestOperations(RestOperations)calls tosetRestClient(RestClient)on the newRestClient-based OAuth2AccessTokenResponseClientimplementations. TheRestClient-based implementations introduced in Spring Security 7 useRestClientinstead ofRestOperations.
- Migrate OAuth2 token response client from
- io.moderne.java.spring.security7.MigrateRequiresChannelToRedirectToHttps
- Migrate
requiresChannel()toredirectToHttps() - In Spring Security 7.0,
HttpSecurity.requiresChannel()is deprecated in favor ofHttpSecurity.redirectToHttps(). This recipe renames the method call and simplifiesanyRequest().requiresSecure()toCustomizer.withDefaults().
- Migrate
- io.moderne.java.spring.security7.ModularizeSpringSecurity7
- Spring Security 7 modularization
- Spring Security Core was modularized in version 7, deprecated classes that are still a crucial part of some applications are moved to
spring-security-access.
rewrite-tapestry
- org.openrewrite.tapestry.ChangeTapestryPackages
- Change Tapestry 4 packages to Tapestry 5
- Updates package imports from org.apache.tapestry to org.apache.tapestry5. Only renames packages that have direct equivalents in Tapestry 5.
- org.openrewrite.tapestry.ChangeTapestryTypes
- Change Tapestry 4 types to Tapestry 5 equivalents
- Renames Tapestry 4 types that have direct equivalents in Tapestry 5. This handles types from different packages that were reorganized in T5.
- org.openrewrite.tapestry.ConvertAnnotatedMethodToField
- Convert annotated abstract method to field
- Converts abstract getter methods annotated with
sourceAnnotationto private fields annotated withtargetAnnotation. Also removes corresponding abstract setter methods.
- org.openrewrite.tapestry.ConvertBeanAnnotation
- Convert Tapestry 4
@Beanto@Property - Converts Tapestry 4's
@Beanannotation to@Propertyfields. Bean initialization with 'initializer' attribute requires manual migration.
- Convert Tapestry 4
- org.openrewrite.tapestry.ConvertListenerInterfaces
- Convert Tapestry 4 listener interfaces to Tapestry 5 annotations
- Converts Tapestry 4 page lifecycle listener interfaces (
PageBeginRenderListener,PageEndRenderListener, etc.) to Tapestry 5 lifecycle annotations (@SetupRender,@CleanupRender, etc.) and removes the interface implementations.
- org.openrewrite.tapestry.MigrateTapestry4To5
- Migrate Tapestry 4 to Tapestry 5
- Migrates Apache Tapestry 4 applications to Tapestry 5. This includes package renames, removing base class inheritance, converting listener interfaces to annotations, and updating dependencies.
- org.openrewrite.tapestry.RemoveIRequestCycleParameter
- Remove
IRequestCycleparameters - Removes
IRequestCycleparameters from methods. In Tapestry 5, event handler methods don't receive the request cycle as a parameter.
- Remove
- org.openrewrite.tapestry.RemoveObsoleteFormTypes
- Remove obsolete Tapestry form types
- Removes field declarations and imports for Tapestry 4 form component types (
IPropertySelectionModel,StringPropertySelectionModel, etc.) that don't exist in Tapestry 5. Code using these types will need manual refactoring to use Tapestry 5'sSelectModelpattern.
- org.openrewrite.tapestry.RemoveTapestryBaseClasses
- Remove Tapestry 4 base classes
- Removes Tapestry 4 base class inheritance (
BasePage,BaseComponent,AbstractComponent) and converts the class to a POJO suitable for Tapestry 5. Abstract getter/setter methods are converted to fields with@Propertyannotation.
- org.openrewrite.tapestry.ReplaceReverseComparator
- Replace
ReverseComparatorwithCollections.reverseOrder() - Replaces tapestry-contrib's
ReverseComparatorwith the standard JavaCollections.reverseOrder()method.
- Replace
- org.openrewrite.tapestry.UpdateTapestryDependencies
- Update Tapestry dependencies
- Updates dependencies from Tapestry 4 to Tapestry 5.
rewrite-vulncheck
- io.moderne.vulncheck.FixVulnCheckVulnerabilities
- Use VulnCheck Exploit Intelligence to fix vulnerabilities
- This software composition analysis (SCA) tool detects and upgrades dependencies with publicly disclosed vulnerabilities. This recipe both generates a report of vulnerable dependencies and upgrades to newer versions with fixes. This recipe by default only upgrades to the latest patch version. If a minor or major upgrade is required to reach the fixed version, this can be controlled using the
maximumUpgradeDeltaoption. Vulnerability information comes from VulnCheck Vulnerability Intelligence. The recipe has an option to limit fixes to only those vulnerabilities that have evidence of exploitation at various levels of severity.
org.openrewrite
rewrite-python
- org.openrewrite.python.AddDependency
- Add Python dependency
- Add a dependency to a Python project. Supports
pyproject.toml(with scope/group targeting),requirements.txt, andPipfile. When the matching package manager (uvorpipenv) is available, the corresponding lock file (uv.lockorPipfile.lock) is regenerated. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.
- org.openrewrite.python.AddLiteralMethodArgument
- Add literal method argument
- Add a literal argument to method invocations matching a pattern.
- org.openrewrite.python.ChangeDependency
- Change Python dependency
- Change a dependency to a different package. Supports
pyproject.toml,requirements.txt, andPipfile. Searches all dependency scopes. When the matching package manager (uvorpipenv) is available, the corresponding lock file (uv.lockorPipfile.lock) is regenerated. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.
- org.openrewrite.python.ChangeImport
- Change import
- Change a Python import from one module/name to another, updating all type attributions.
- org.openrewrite.python.ChangeMethodName
- Change method name
- Rename method invocations matching a pattern.
- org.openrewrite.python.ChangePackage
- Change package
- Change package/module references from one name to another.
- org.openrewrite.python.ChangeType
- Change type
- Change a type reference from one fully qualified name to another.
- org.openrewrite.python.DeleteMethodArgument
- Delete method argument
- Remove an argument from method invocations matching a pattern.
- org.openrewrite.python.RemoveDependency
- Remove Python dependency
- Remove a dependency from a Python project. Supports
pyproject.toml(with scope/group targeting),requirements.txt, andPipfile. When the matching package manager (uvorpipenv) is available, the corresponding lock file (uv.lockorPipfile.lock) is regenerated. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.
- org.openrewrite.python.RemovePass
- Remove redundant pass statements
- Remove redundant
passstatements from Python code when there are other executable statements in the block.
- org.openrewrite.python.ReorderMethodArguments
- Reorder method arguments
- Reorder arguments in method invocations matching a pattern.
- org.openrewrite.python.UpgradeDependencyVersion
- Upgrade Python dependency version
- Upgrade the version constraint for a dependency. Supports
pyproject.toml(with scope/group targeting),requirements.txt, andPipfile. When the matching package manager (uvorpipenv) is available, the corresponding lock file (uv.lockorPipfile.lock) is regenerated. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.
- org.openrewrite.python.UpgradeTransitiveDependencyVersion
- Upgrade transitive Python dependency version
- Pin a transitive dependency version using the strategy appropriate for the file type and package manager. For
pyproject.toml: uv uses[tool.uv].constraint-dependencies, PDM uses[tool.pdm.overrides], and other managers add a direct dependency. Forrequirements.txtandPipfile: appends the dependency. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.
- org.openrewrite.python.format.PythonSpaces
- Formats spaces in Python code
- Standardizes spaces in Python code. Currently limited to formatting method arguments.
- org.openrewrite.python.search.DependencyInsight
- Python dependency insight
- Find direct and transitive Python dependencies matching a package name pattern. Results include dependencies that either directly match or transitively include a matching dependency.
org.openrewrite.recipe
rewrite-ai-search
- io.moderne.ai.FindCommentsLanguage
- Find comments' language distribution
- Finds all comments and uses AI to predict which language the comment is in.
- io.moderne.ai.FixMisencodedCommentsInFrench
- Fix mis-encoded French comments, javadocs and pom.xml comments
- Fixes mis-encoded French comments in your code, javadocs and in your pom.xml files. Mis-encoded comments contain a ? or � character.
- io.moderne.ai.ListAllMethodsUsed
- List all methods used
- List all methods used in any Java source file.
- io.moderne.ai.SpellCheckCommentsInFrench
- Fix mis-encoded comments in French
- Use spellchecker to fix mis-encoded French comments in comments, JavaDocs, properties or XML files. Mis-encoded comments will contain either '?' or '�'.
- io.moderne.ai.research.FindCodeThatResembles
- Find method invocations that resemble a pattern
- This recipe uses two phase AI approach to find a method invocation that resembles a search string.
- io.moderne.ai.research.GetCodeEmbedding
- Get embeddings for code snippets in code
- This recipe calls an AI model to get an embedding for either classes or methods which can then be used for downstream tasks.
- io.moderne.ai.research.GetRecommendations
- Get recommendations
- This recipe calls an AI model to get recommendations for modernizing the code base by looking at a sample of method declarations.
rewrite-android
- org.openrewrite.android.ChangeAndroidSdkVersion
- Change Android SDK version
- Change
compileSdk,compileSdkVersion,targetSdkandtargetSdkVersionin an Android Gradle build file to the argument version.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_7_2
- Migrate to Android Gradle Plugin 7.2
- Recipes to migrate to Android Gradle Plugin version 7.2.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_7_3
- Migrate to Android Gradle Plugin 7.3
- Recipes to migrate to Android Gradle Plugin version 7.3.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_7_4
- Migrate to Android Gradle Plugin 7.4
- Recipes to migrate to Android Gradle Plugin version 7.4.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_0
- Migrate to Android Gradle Plugin 8.0
- Recipes to migrate to Android Gradle Plugin version 8.0.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_1
- Migrate to Android Gradle Plugin 8.1
- Recipes to migrate to Android Gradle Plugin version 8.1.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_10
- Migrate to Android Gradle Plugin 8.10
- Recipes to migrate to Android Gradle Plugin version 8.10.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_11
- Migrate to Android Gradle Plugin 8.11
- Recipes to migrate to Android Gradle Plugin version 8.11.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_12
- Migrate to Android Gradle Plugin 8.12
- Recipes to migrate to Android Gradle Plugin version 8.12.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_13
- Migrate to Android Gradle Plugin 8.13
- Recipes to migrate to Android Gradle Plugin version 8.13.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_2
- Migrate to Android Gradle Plugin 8.2
- Recipes to migrate to Android Gradle Plugin version 8.2.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_3
- Migrate to Android Gradle Plugin 8.3
- Recipes to migrate to Android Gradle Plugin version 8.3.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_4
- Migrate to Android Gradle Plugin 8.4
- Recipes to migrate to Android Gradle Plugin version 8.4.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_5
- Migrate to Android Gradle Plugin 8.5
- Recipes to migrate to Android Gradle Plugin version 8.5.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_6
- Migrate to Android Gradle Plugin 8.6
- Recipes to migrate to Android Gradle Plugin version 8.6.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_7
- Migrate to Android Gradle Plugin 8.7
- Recipes to migrate to Android Gradle Plugin version 8.7.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_8
- Migrate to Android Gradle Plugin 8.8
- Recipes to migrate to Android Gradle Plugin version 8.8.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_8_9
- Migrate to Android Gradle Plugin 8.9
- Recipes to migrate to Android Gradle Plugin version 8.9.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_9_0
- Migrate to Android Gradle Plugin 9.0
- Recipes to migrate to Android Gradle Plugin version 9.0.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_9_1
- Migrate to Android Gradle Plugin 9.1
- Recipes to migrate to Android Gradle Plugin version 9.1.
- org.openrewrite.android.MigrateToAndroidGradlePlugin_9_2
- Migrate to Android Gradle Plugin 9.2
- Recipes to migrate to Android Gradle Plugin version 9.2.
- org.openrewrite.android.RemoveBuildToolsVersion
- Remove
buildToolsVersion - Remove the
buildToolsVersiondeclaration from theandroidblock in a Gradle build file. Since Android Gradle Plugin 3.0 the build tools version is selected automatically based on the AGP version, so explicitbuildToolsVersiondeclarations are ignored and add noise to build files.
- Remove
- org.openrewrite.android.RenameAaptOptionsToAndroidResources
- Rename
aaptOptionstoandroidResources - The
aaptOptions \{ ... \}DSL block was renamed toandroidResources \{ ... \}in Android Gradle Plugin 7.0 and may be removed in AGP 9.x. This is a pure block rename with no semantic change.
- Rename
- org.openrewrite.android.RenameLintOptionsToLint
- Rename
lintOptionstolint - The
lintOptions \{ ... \}DSL block was renamed tolint \{ ... \}in Android Gradle Plugin 7.0 and may be removed in AGP 9.x. This is a pure block rename with no semantic change.
- Rename
- org.openrewrite.android.UpgradeAndroidGradlePluginVersion
- Upgrade Android Gradle Plugin (AGP) version
- Upgrade Android Gradle Plugin (AGP) version and update the Gradle Wrapper version. Compatible versions are published in the AGP release notes.
- org.openrewrite.android.UpgradeToAndroidSDK33
- Upgrade to Android SDK 33
- Recipes to upgrade to Android SDK version 33.
- org.openrewrite.android.UpgradeToAndroidSDK34
- Upgrade to Android SDK 34
- Recipes to upgrade to Android SDK version 34.
- org.openrewrite.android.UpgradeToAndroidSDK35
- Upgrade to Android SDK 35
- Recipes to upgrade to Android SDK version 35.
- org.openrewrite.android.UpgradeToAndroidSDK36
- Upgrade to Android SDK 36
- Recipes to upgrade to Android SDK version 36.
rewrite-circleci
- org.openrewrite.circleci.InstallOrb
- Install an orb
- Install a CircleCI orb if it is not already installed.
- org.openrewrite.circleci.UpdateImage
- Update CircleCI image
- See the list of pre-built CircleCI images.
rewrite-codemods-ng
- org.openrewrite.codemods.migrate.angular.ApplyAngularCLI
- Upgrade Angular versions
- Run
ng updateto upgrade Angular CLI and Angular Core to the specified version.
- org.openrewrite.codemods.migrate.angular.v15
- Update to Angular v15
- Upgrade to Angular v15 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v16
- Update to Angular v16
- Upgrade to Angular v16 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v17
- Update to Angular v17
- Upgrade to Angular v17 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v18
- Update to Angular v18
- Upgrade to Angular v18 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v19
- Update to Angular v19
- Upgrade to Angular v19 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v20
- Update to Angular v20
- Upgrade to Angular v20 through
ApplyAngularCLI.
- org.openrewrite.codemods.migrate.angular.v21
- Update to Angular v21
- Upgrade to Angular v21 through
ApplyAngularCLI.
rewrite-compiled-analysis
- io.moderne.compiled.verification.ChangeListMethodAndVerify
- Change
List#addtoList#plusand verify - We know this won't compile.
- Change
- io.moderne.compiled.verification.VerifyCompilation
- Verify compilation
- This is a task that runs after another recipe to verify that the changes made by that recipe would result in a successful compilation.
rewrite-concourse
- org.openrewrite.concourse.ChangeResourceVersion
- Change resource version
- Pin or unpin a resource to a particular version.
- org.openrewrite.concourse.ChangeValue
- Change Concourse value
- Change every value matching the key pattern.
- org.openrewrite.concourse.FindResource
- Find resource
- Find a Concourse resource by name.
- org.openrewrite.concourse.UpdateGitResourceUri
- Update git resource
source.urireferences - Update git resource
source.uriURI values to point to a new URI value.
- Update git resource
- org.openrewrite.concourse.search.FindPinnedResource
- Find pinned resources by type
- Find resources of a particular type that have pinned versions.
- org.openrewrite.concourse.search.FindPrivilegedResourceType
- Find privileged
resource_typedefinitions - By default,
resource_typedefinitions are unprivileged.
- Find privileged
rewrite-dotnet
- org.openrewrite.dotnet.MigrateToNet6
- Upgrade to .NET 6.0 using upgrade-assistant
- Run upgrade-assistant upgrade across a repository to upgrade projects to .NET 6.0.
- org.openrewrite.dotnet.MigrateToNet7
- Upgrade to .NET 7.0 using upgrade-assistant
- Run upgrade-assistant upgrade across a repository to upgrade projects to .NET 7.0.
- org.openrewrite.dotnet.MigrateToNet8
- Upgrade to .NET 8.0 using upgrade-assistant
- Run upgrade-assistant upgrade across a repository to upgrade projects to .NET 8.0.
- org.openrewrite.dotnet.MigrateToNet9
- Upgrade to .NET 9.0 using upgrade-assistant
- Run upgrade-assistant upgrade across a repository to upgrade projects to .NET 9.0.
- org.openrewrite.dotnet.UpgradeAssistant
- Upgrade a .NET project using upgrade-assistant
- Run upgrade-assistant upgrade across a repository to upgrade projects to a newer version of .NET.
- org.openrewrite.dotnet.UpgradeAssistantAnalyze
- Analyze a .NET project using upgrade-assistant
- Run upgrade-assistant analyze across a repository to analyze changes required to upgrade projects to a newer version of .NET. This recipe will generate an
org.openrewrite.dotnet.UpgradeAssistantAnalysisdata table containing the report details.
rewrite-java-security
- org.openrewrite.csharp.dependencies.DependencyInsight
- Dependency insight for C#
- Finds dependencies in
*.csprojandpackages.config.
- org.openrewrite.csharp.dependencies.DependencyVulnerabilityCheck
- Find and fix vulnerable Nuget dependencies
- This software composition analysis (SCA) tool detects and upgrades dependencies with publicly disclosed vulnerabilities. This recipe both generates a report of vulnerable dependencies and upgrades to newer versions with fixes. This recipe by default only upgrades to the latest patch version. If a minor or major upgrade is required to reach the fixed version, this can be controlled using the
maximumUpgradeDeltaoption. Vulnerability information comes from the GitHub Security Advisory Database, which aggregates vulnerability data from several public databases, including the National Vulnerability Database maintained by the United States government. Dependencies following Semantic Versioning will see their patch version updated where applicable. Last updated: 2026-05-11T1202.
- org.openrewrite.csharp.dependencies.UpgradeDependencyVersion
- Upgrade C# dependency versions
- Upgrades dependencies in
*.csproj,Directory.Packages.props, andpackages.config.
- org.openrewrite.java.dependencies.AddExplicitTransitiveDependencies
- Add explicit transitive dependencies
- Detects when Java source code or configuration files reference types from transitive Maven dependencies and promotes those transitive dependencies to explicit direct dependencies in the pom.xml. This ensures the build is resilient against changes in transitive dependency trees of upstream libraries.
- org.openrewrite.java.dependencies.DependencyLicenseCheck
- Find licenses in use in third-party dependencies
- Locates and reports on all licenses in use.
- org.openrewrite.java.dependencies.DependencyVulnerabilityCheck
- Find and fix vulnerable dependencies
- This software composition analysis (SCA) tool detects and upgrades dependencies with publicly disclosed vulnerabilities. This recipe both generates a report of vulnerable dependencies and upgrades to newer versions with fixes. This recipe by default only upgrades to the latest patch version. If a minor or major upgrade is required to reach the fixed version, this can be controlled using the
maximumUpgradeDeltaoption. Vulnerability information comes from the GitHub Security Advisory Database, which aggregates vulnerability data from several public databases, including the National Vulnerability Database maintained by the United States government. Upgrades dependencies versioned according to Semantic Versioning. ## Customizing Vulnerability Data This recipe can be customized by extendingDependencyVulnerabilityCheckBaseand overriding the vulnerability data sources: -baselineVulnerabilities(ExecutionContext ctx): Provides the default set of known vulnerabilities. The base implementation loads vulnerability data from the GitHub Security Advisory Database CSV file usingResourceUtils.parseResourceAsCsv(). Override this method to replace the entire vulnerability dataset with your own curated list. -supplementalVulnerabilities(ExecutionContext ctx): Allows adding custom vulnerability data beyond the baseline. The base implementation returns an empty list. Override this method to add organization-specific vulnerabilities, internal security advisories, or vulnerabilities from additional sources while retaining the baseline GitHub Advisory Database. Both methods returnList<Vulnerability>objects. Vulnerability data can be loaded from CSV files usingResourceUtils.parseResourceAsCsv(path, Vulnerability.class, consumer)or constructed programmatically. To customize, extendDependencyVulnerabilityCheckBaseand override one or both methods depending on your needs. For example, overridesupplementalVulnerabilities()to add custom CVEs while keeping the standard vulnerability database, or overridebaselineVulnerabilities()to use an entirely different vulnerability data source. Last updated: 2026-05-11T1202.
- org.openrewrite.java.dependencies.RemoveUnusedDependencies
- Remove unused dependencies
- Scans through source code collecting references to types and methods, removing any dependencies that are not used from Maven or Gradle build files. This is best effort and not guaranteed to work well in all cases; false positives are still possible. This recipe takes reflective access into account: - When reflective access to a class is made unambiguously via a string literal, such as:
Class.forName("java.util.List")that is counted correctly. - When reflective access to a class is made ambiguously via anything other than a string literal no dependencies will be removed. This recipe takes transitive dependencies into account: - When a direct dependency is not used but a transitive dependency it brings in is in use the direct dependency is not removed.
- org.openrewrite.java.dependencies.SoftwareBillOfMaterials
- Software bill of materials
- Produces a software bill of materials (SBOM) for a project. An SBOM is a complete list of all dependencies used in a project, including transitive dependencies. The produced SBOM is in the CycloneDX XML format. Supports Gradle and Maven. Places a file named sbom.xml adjacent to the Gradle or Maven build file.
- org.openrewrite.java.security.FindTextDirectionChanges
- Find text-direction changes
- Finds unicode control characters which can change the direction text is displayed in. These control characters can alter how source code is presented to a human reader without affecting its interpretation by tools like compilers. So a malicious patch could pass code review while introducing vulnerabilities. Note that text direction-changing unicode control characters aren't inherently malicious. These characters can appear for legitimate reasons in code written in or dealing with right-to-left languages. See: https://trojansource.codes/ for more information.
- org.openrewrite.java.security.FixCwe338
- Fix CWE-338 with
SecureRandom - Use a cryptographically strong pseudo-random number generator (PRNG).
- Fix CWE-338 with
- org.openrewrite.java.security.FixCwe918
- Remediate server-side request forgery (SSRF)
- Inserts a guard that validates URLs constructed from user-controlled input do not target internal network addresses, blocking server-side request forgery (SSRF) attacks.
- org.openrewrite.java.security.ImproperPrivilegeManagement
- Improper privilege management
- Marking code as privileged enables a piece of trusted code to temporarily enable access to more resources than are available directly to the code that called it.
- org.openrewrite.java.security.JavaSecurityBestPractices
- Java security best practices
- Applies security best practices to Java code.
- org.openrewrite.java.security.Owasp2025A01
- Remediate OWASP A01:2025 Broken access control
- OWASP A01:2025 describes failures related to broken access control.
- org.openrewrite.java.security.Owasp2025A02
- Remediate OWASP A02:2025 Security misconfiguration
- OWASP A02:2025 describes failures related to security misconfiguration. Previously A05:2021, this category moved up to #2 in 2025.
- org.openrewrite.java.security.Owasp2025A03
- Remediate OWASP A03:2025 Software supply chain failures
- OWASP A03:2025 describes failures related to the software supply chain, including vulnerable and outdated components. Expanded from A06:2021 Vulnerable and Outdated Components.
- org.openrewrite.java.security.Owasp2025A04
- Remediate OWASP A04:2025 Cryptographic failures
- OWASP A04:2025 describes failures related to cryptography (or lack thereof), which often lead to exposure of sensitive data. Previously A02:2021.
- org.openrewrite.java.security.Owasp2025A05
- Remediate OWASP A05:2025 Injection
- OWASP A05:2025 describes failures related to user-supplied data being used to influence program state to operate outside of its intended bounds. Previously A03:2021.
- org.openrewrite.java.security.Owasp2025A07
- Remediate OWASP A07:2025 Identification and authentication failures
- OWASP A07:2025 describes failures related to identification and authentication, including weak credential management, missing brute force protections, session fixation, hardcoded credentials, insecure "remember me", and missing multi-factor authentication. Same position as A07:2021 (no prior aggregator existed).
- org.openrewrite.java.security.OwaspA01
- Remediate OWASP A01:2021 Broken access control
- OWASP A01:2021 describes failures related to broken access control.
- org.openrewrite.java.security.OwaspA02
- Remediate OWASP A02:2021 Cryptographic failures
- OWASP A02:2021 describes failures related to cryptography (or lack thereof), which often lead to exposure of sensitive data. This recipe seeks to remediate these vulnerabilities.
- org.openrewrite.java.security.OwaspA03
- Remediate OWASP A03:2021 Injection
- OWASP A03:2021 describes failures related to user-supplied data being used to influence program state to operate outside of its intended bounds. This recipe seeks to remediate these vulnerabilities.
- org.openrewrite.java.security.OwaspA05
- Remediate OWASP A05:2021 Security misconfiguration
- OWASP A05:2021 describes failures related to security misconfiguration.
- org.openrewrite.java.security.OwaspA06
- Remediate OWASP A06:2021 Vulnerable and outdated components
- OWASP A06:2021 describes failures related to vulnerable and outdated components.
- org.openrewrite.java.security.OwaspA08
- Remediate OWASP A08:2021 Software and data integrity failures
- OWASP A08:2021 software and data integrity failures.
- org.openrewrite.java.security.OwaspTopTen
- Remediate vulnerabilities from the OWASP Top Ten
- OWASP publishes a list of the most impactful common security vulnerabilities. These recipes identify and remediate vulnerabilities from the OWASP Top Ten.
- org.openrewrite.java.security.PartialPathTraversalVulnerability
- Partial path traversal vulnerability
- Replaces
dir.getCanonicalPath().startsWith(parent.getCanonicalPath(), which is vulnerable to partial path traversal attacks, with the more securedir.getCanonicalFile().toPath().startsWith(parent.getCanonicalFile().toPath()). To demonstrate this vulnerability, consider"/usr/outnot".startsWith("/usr/out"). The check is bypassed although/outnotis not under the/outdirectory. It's important to understand that the terminating slash may be removed when using variousStringrepresentations of theFileobject. For example, on Linux,println(new File("/var"))will print/var, butprintln(new File("/var", "/")will print/var/; however,println(new File("/var", "/").getCanonicalPath())will print/var.
- org.openrewrite.java.security.RegularExpressionDenialOfService
- Regular Expression Denial of Service (ReDOS)
- ReDoS is a Denial of Service attack that exploits the fact that most Regular Expression implementations may reach extreme situations that cause them to work very slowly (exponentially related to input size). See the OWASP description of this attack here for more details.
- org.openrewrite.java.security.SecureRandom
- Secure random
- Use cryptographically secure Pseudo Random Number Generation in the "main" source set. Replaces instantiation of
java.util.Randomwithjava.security.SecureRandom.
- org.openrewrite.java.security.SecureRandomPrefersDefaultSeed
- SecureRandom seeds are not constant or predictable
- Remove
SecureRandom#setSeed(*)method invocations having constant or predictable arguments.
- org.openrewrite.java.security.SecureTempFileCreation
- Use secure temporary file creation
java.io.File.createTempFile()has exploitable default file permissions. This recipe migrates to the more securejava.nio.file.Files.createTempFile().
- org.openrewrite.java.security.UseFilesCreateTempDirectory
- Use
Files#createTempDirectory - Use
Files#createTempDirectorywhen the sequenceFile#createTempFile(..)->File#delete()->File#mkdir()is used for creating a temp directory.
- Use
- org.openrewrite.java.security.XmlParserXXEVulnerability
- XML parser XXE vulnerability
- Avoid exposing dangerous features of the XML parser by updating certain factory settings.
- org.openrewrite.java.security.ZipSlip
- Zip slip
- Zip slip is an arbitrary file overwrite critical vulnerability, which typically results in remote command execution. A fuller description of this vulnerability is available in the Snyk documentation on it.
- org.openrewrite.java.security.marshalling.InsecureJmsDeserialization
- Insecure JMS deserialization
- JMS
Objectmessages depend on Java Serialization for marshalling/unmarshalling of the message payload whenObjectMessage#getObjectis called. Deserialization of untrusted data can lead to security flaws.
- org.openrewrite.java.security.marshalling.SecureJacksonDefaultTyping
- Secure the use of Jackson default typing
- See the blog post on this subject.
- org.openrewrite.java.security.marshalling.SecureSnakeYamlConstructor
- Secure the use of SnakeYAML's constructor
- See the paper on this subject.
- org.openrewrite.java.security.search.FindCommandInjection
- Find OS command injection vectors
- Finds calls to
Runtime.exec(String)which passes the command through a shell interpreter, enabling command injection via metacharacters like;,|, and&&. Use theString[]overload instead to avoid shell interpretation.
- org.openrewrite.java.security.search.FindExpressionLanguageInjection
- Find Expression Language injection vectors
- Finds calls to Expression Language (EL) evaluation methods which, when the expression is built from user input, can allow arbitrary code execution. Use parameterized expressions or input validation instead.
- org.openrewrite.java.security.search.FindHardcodedAuthenticationCredentials
- Find hardcoded authentication credentials
- Finds hardcoded passwords flowing into Spring Security user builders:
InMemoryUserDetailsManagerConfigurer(inMemoryAuthentication().withUser(...).password(...)) and theUser.UserBuilder.password(...)API. Uses taint analysis so credentials assigned to a variable, field, or constant before being passed to.password(...)are also detected.
- org.openrewrite.java.security.search.FindHardcodedIv
- Find hardcoded initialization vectors
- Finds
IvParameterSpecconstructed with hardcoded byte arrays or string literals. A static IV makes CBC and other modes deterministic, enabling chosen-plaintext attacks. IVs should be generated randomly usingSecureRandomfor each encryption operation.
- org.openrewrite.java.security.search.FindHttpResponseSplitting
- Find HTTP response splitting vectors
- Finds calls to
HttpServletResponse.addHeader(),setHeader(), andaddCookie()which, when header values are derived from user input without CRLF sanitization, can allow HTTP response splitting attacks. Full taint-based detection requires rewrite-program-analysis; this recipe identifies the sink call sites for manual review.
- org.openrewrite.java.security.search.FindInadequateKeySize
- Find inadequate cryptographic key sizes
- Finds cryptographic key generation with inadequate key sizes. RSA keys should be at least 2048 bits, DSA keys at least 2048 bits, EC keys at least 256 bits, and symmetric keys (AES) at least 128 bits. NIST recommends RSA-2048+ and AES-128+ as minimum for all new applications.
- org.openrewrite.java.security.search.FindInsecureRememberMeConfig
- Find insecure Spring Security RememberMe configuration
- Finds Spring Security RememberMe configurations with insecure settings:
useSecureCookie(false)(allows cookie transmission over HTTP),alwaysRemember(true)(bypasses user opt-in), ortokenValiditySeconds(...)set longer than 30 days (extends the window in which a stolen remember-me cookie can be replayed).
- org.openrewrite.java.security.search.FindInsecureSessionFixationConfig
- Find Spring Security configurations that disable session fixation protection
- Finds Spring Security configurations that disable session fixation protection by calling
sessionFixation().none(). Without session fixation protection, an attacker who obtains a victim's session identifier before authentication can reuse it to hijack the authenticated session. Spring Security defaults tochangeSessionId(); applications should keep that default or usemigrateSession().
- org.openrewrite.java.security.search.FindJacksonDefaultTypeMapping
- Find Jackson default type mapping enablement
ObjectMapper#enableTypeMapping(..)can lead to vulnerable deserialization.
- org.openrewrite.java.security.search.FindLongSessionTimeout
- Find long or disabled HTTP session timeout
- Finds calls to
HttpSession.setMaxInactiveInterval(int)whose integer-literal argument exceeds 30 minutes or is zero/negative (which disables session expiration). Long-lived or non-expiring sessions increase the window for session hijacking and replay (CWE-613).
- org.openrewrite.java.security.search.FindPermissiveCorsConfiguration
- Find permissive CORS configuration
- Finds overly permissive CORS configurations that allow all origins, which can expose the application to cross-domain attacks.
- org.openrewrite.java.security.search.FindPredictableSalt
- Find predictable cryptographic salts
- Finds
PBEParameterSpecandPBEKeySpecconstructed with hardcoded salt byte arrays. A predictable salt undermines the purpose of salting, making rainbow table and precomputation attacks feasible. Salts should be generated randomly usingSecureRandom.
- org.openrewrite.java.security.search.FindProcessControl
- Find process control vectors
- Finds calls to
System.loadLibrary(),System.load(), andRuntime.load()which, when the library path or name is derived from user input, can allow an attacker to load arbitrary native code. Ensure library names are not externally controlled.
- org.openrewrite.java.security.search.FindResourceInjection
- Find resource injection vectors
- Detects resource injection vulnerabilities where user-controlled input flows to resource access operations — file paths, JNDI lookups, class loading, and native library loading. Uses taint analysis from rewrite-program-analysis for source-to-sink tracking with sanitizer support, plus structural detection as fallback.
- org.openrewrite.java.security.search.FindRsaWithoutOaep
- Find RSA encryption without OAEP padding
- Finds uses of RSA encryption with PKCS#1 v1.5 padding or no padding specification. RSA without OAEP padding is vulnerable to padding oracle attacks. Use
RSA/ECB/OAEPWithSHA-256AndMGF1Paddingor equivalent OAEP mode instead.
- org.openrewrite.java.security.search.FindScriptEngineInjection
- Find script engine code injection vectors
- Finds calls to
ScriptEngine.eval()which can execute arbitrary code if the script string is influenced by user input. Consider sandboxing or removing dynamic script evaluation.
- org.openrewrite.java.security.search.FindSensitiveApiEndpoints
- Find sensitive API endpoints
- Find data models exposed by REST APIs that contain sensitive information like PII and secrets.
- org.openrewrite.java.security.search.FindSqlInjection
- Find potential SQL injection
- Finds SQL query methods where the query string is constructed via string concatenation, which may indicate SQL injection vulnerabilities. Use parameterized queries or prepared statements instead.
- org.openrewrite.java.security.search.FindUnsafeReflection
- Find unsafe reflection vectors
- Finds calls to
Class.forName()which, when the class name is derived from user input, can allow an attacker to instantiate arbitrary classes. Review these call sites to ensure the class name is not externally controlled.
- org.openrewrite.java.security.search.FindUnsignedJwt
- Find unsigned JWT usage
- Finds construction or parsing of Nimbus
PlainJWT— an unsecured JWT that has no signature or MAC. Unsecured JWTs allow an attacker to forge tokens because their payloads are not integrity-protected. Use a signed (SignedJWT) or encrypted (EncryptedJWT) JWT instead.
- org.openrewrite.java.security.search.FindUserWithDefaultPasswordEncoder
- Find
User.withDefaultPasswordEncoder()usage - Flags any call to
User.withDefaultPasswordEncoder()from Spring Security. The factory is documented as for non-production demos only: it stores credentials in memory with a fixed encoder and is unsafe for real workloads.
- Find
- org.openrewrite.java.security.search.FindVulnerableJacksonJsonTypeInfo
- Find vulnerable uses of Jackson
@JsonTypeInfo - Identify where attackers can deserialize gadgets into a target field.
- Find vulnerable uses of Jackson
- org.openrewrite.java.security.search.FindWeakCryptoAlgorithm
- Find weak cryptographic algorithms
- Finds uses of broken or risky cryptographic algorithms such as MD5, SHA-1, DES, DESede (3DES), RC2, RC4, and Blowfish in calls to
Cipher.getInstance(),MessageDigest.getInstance(),Mac.getInstance(),KeyGenerator.getInstance(), andSecretKeyFactory.getInstance().
- org.openrewrite.java.security.search.FindWeakDigestInPasswordEncoder
- Find weak message digests used inside custom
PasswordEncoderimplementations - Finds calls to
MessageDigest.getInstance("...")whose algorithm is unsuitable for password storage, scoped to classes implementingorg.springframework.security.crypto.password.PasswordEncoder. Unsalted and non-iterated digests (MD2, MD4, MD5, SHA-1, SHA-224/256/384/512) are unsuitable for password hashing regardless of how they are wrapped. Delegate toBCryptPasswordEncoder,Argon2PasswordEncoder,Pbkdf2PasswordEncoder, orSCryptPasswordEncoderinstead of implementingPasswordEncoderyourself.
- Find weak message digests used inside custom
- org.openrewrite.java.security.search.FindWeakPasswordEncoderStrength
- Find weak password encoder strength
- Finds Spring Security
BCryptPasswordEncoderinstantiations with a strength (work factor) below 10. The default and OWASP-recommended minimum is 10; lower values make stolen password hashes substantially cheaper to brute-force.
- org.openrewrite.java.security.search.FindWeakPasswordHashing
- Find weak password hashing
- Finds uses of
MessageDigest.getInstance()with algorithms unsuitable for password hashing (MD5, SHA-1, SHA-256, SHA-384, SHA-512). Passwords should be hashed with a purpose-built password hashing function such as bcrypt, scrypt, Argon2, or PBKDF2 that includes a salt and a tunable work factor.
- org.openrewrite.java.security.search.FindWeakSpringPasswordEncoder
- Find weak Spring Security password encoders
- Finds uses of Spring Security password encoders that are unsuitable for production password storage:
NoOpPasswordEncoder(plaintext),StandardPasswordEncoder(deprecated SHA-256),MessageDigestPasswordEncoder(raw message digest),Md4PasswordEncoder(MD4, broken), andLdapShaPasswordEncoder(deprecated). Use an adaptive function such asBCryptPasswordEncoder,Argon2PasswordEncoder,Pbkdf2PasswordEncoder, orSCryptPasswordEncoderinstead.
- org.openrewrite.java.security.search.FindXPathInjection
- Find XPath injection vectors
- Finds calls to
XPath.evaluate()andXPath.compile()which, when the expression is built from user input, can allow XPath injection attacks. Use parameterized XPath expressions or input validation instead.
- org.openrewrite.java.security.secrets.FindArtifactorySecrets
- Find Artifactory secrets
- Locates Artifactory secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindAwsSecrets
- Find AWS secrets
- Locates AWS secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindAzureSecrets
- Find Azure secrets
- Locates Azure secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindBasicAuthSecrets
- Find HTTP Basic authentication secrets
- Locates HTTP Basic authentication credentials stored in plain text in code.
- org.openrewrite.java.security.secrets.FindBearerTokenSecrets
- Find Bearer token secrets
- Locates HTTP Bearer tokens (RFC 6750) stored in plain text in code.
- org.openrewrite.java.security.secrets.FindDiscordSecrets
- Find Discord secrets
- Locates Discord secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindFacebookSecrets
- Find Facebook secrets
- Locates Facebook secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindGenericSecrets
- Find generic secrets
- Locates generic secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindGitHubSecrets
- Find GitHub secrets
- Locates GitHub secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindGoogleSecrets
- Find Google secrets
- Locates Google secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindHerokuSecrets
- Find Heroku secrets
- Locates Heroku secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindJwtSecrets
- Find JWT secrets
- Locates JWTs stored in plain text in code.
- org.openrewrite.java.security.secrets.FindMailChimpSecrets
- Find MailChimp secrets
- Locates MailChimp secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindMailgunSecrets
- Find Mailgun secrets
- Locates Mailgun secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindNpmSecrets
- Find NPM secrets
- Locates NPM secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindPasswordInUrlSecrets
- Find passwords used in URLs
- Locates URLs that contain passwords in plain text.
- org.openrewrite.java.security.secrets.FindPayPalSecrets
- Find PayPal secrets
- Locates PayPal secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindPgpSecrets
- Find PGP secrets
- Locates PGP secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindPicaticSecrets
- Find Picatic secrets
- Locates Picatic secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindRsaSecrets
- Find RSA private keys
- Locates RSA private keys stored in plain text in code.
- org.openrewrite.java.security.secrets.FindSecrets
- Find secrets
- Locates secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindSecretsByPattern
- Find secrets with regular expressions
- A secret is a literal that matches any one of the provided patterns.
- org.openrewrite.java.security.secrets.FindSendGridSecrets
- Find SendGrid secrets
- Locates SendGrid secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindSlackSecrets
- Find Slack secrets
- Locates Slack secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindSquareSecrets
- Find Square secrets
- Locates Square secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindSshSecrets
- Find SSH secrets
- Locates SSH secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindStripeSecrets
- Find Stripe secrets
- Locates Stripe secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindTelegramSecrets
- Find Telegram secrets
- Locates Telegram secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindTwilioSecrets
- Find Twilio secrets
- Locates Twilio secrets stored in plain text in code.
- org.openrewrite.java.security.secrets.FindTwitterSecrets
- Find Twitter secrets
- Locates Twitter secrets stored in plain text in code.
- org.openrewrite.java.security.servlet.CookieSetHttpOnly
- Cookies missing HttpOnly flag
- Check for use of cookies without the HttpOnly flag. Cookies should be marked as HttpOnly to prevent client-side scripts from accessing them, reducing the risk of cross-site scripting (XSS) attacks.
- org.openrewrite.java.security.servlet.CookieSetSecure
- Insecure cookies
- Check for use of insecure cookies. Cookies should be marked as secure. This ensures that the cookie is sent only over HTTPS to prevent cross-site scripting attacks.
- org.openrewrite.java.security.spring.CsrfProtection
- Enable CSRF attack prevention
- Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user's web browser to perform an unwanted action on a trusted site when the user is authenticated. See the full OWASP cheatsheet.
- org.openrewrite.java.security.spring.InsecureSpringServiceExporter
- Secure Spring service exporters
- The default Java deserialization mechanism is available via
ObjectInputStreamclass. This mechanism is known to be vulnerable. If an attacker can make an application deserialize malicious data, it may result in arbitrary code execution. Spring’sRemoteInvocationSerializingExporteruses the default Java deserialization mechanism to parse data. As a result, all classes that extend it are vulnerable to deserialization attacks. The Spring Framework contains at leastHttpInvokerServiceExporterandSimpleHttpInvokerServiceExporterthat extendRemoteInvocationSerializingExporter. These exporters parse data from the HTTP body using the unsafe Java deserialization mechanism. See the full blog post by Artem Smotrakov on CVE-2016-1000027 from which the above description is excerpted.
- org.openrewrite.java.security.spring.PreventClickjacking
- Prevent clickjacking
- The
frame-ancestorsdirective can be used in a Content-Security-Policy HTTP response header to indicate whether or not a browser should be allowed to render a page in a<frame>or<iframe>. Sites can use this to avoid Clickjacking attacks by ensuring that their content is not embedded into other sites.
- org.openrewrite.java.security.spring.RemoveEnableWebSecurityDebug
- Remove debug mode from Spring Security
- Removes the debug attribute from @EnableWebSecurity annotations to prevent sensitive security information from being logged in production.
- org.openrewrite.python.dependencies.DependencyVulnerabilityCheck
- Find and fix vulnerable PyPI dependencies
- This software composition analysis (SCA) tool detects and upgrades dependencies with publicly disclosed vulnerabilities. This recipe both generates a report of vulnerable dependencies and upgrades to newer versions with fixes. This recipe by default only upgrades to the latest patch version. If a minor or major upgrade is required to reach the fixed version, this can be controlled using the
maximumUpgradeDeltaoption. Vulnerability information comes from the GitHub Security Advisory Database, which aggregates vulnerability data from several public databases, including the National Vulnerability Database maintained by the United States government. Dependencies following Semantic Versioning will see their patch version updated where applicable. ## Customizing Vulnerability Data This recipe can be customized by extendingDependencyVulnerabilityCheckBaseand overriding the vulnerability data sources: -baselineVulnerabilities(ExecutionContext ctx): Provides the default set of known vulnerabilities. The base implementation loads vulnerability data from the GitHub Security Advisory Database CSV file usingResourceUtils.parseResourceAsCsv(). Override this method to replace the entire vulnerability dataset with your own curated list. -supplementalVulnerabilities(ExecutionContext ctx): Allows adding custom vulnerability data beyond the baseline. The base implementation returns an empty list. Override this method to add organization-specific vulnerabilities, internal security advisories, or vulnerabilities from additional sources while retaining the baseline GitHub Advisory Database. Both methods returnList<Vulnerability>objects. Vulnerability data can be loaded from CSV files usingResourceUtils.parseResourceAsCsv(path, Vulnerability.class, consumer)or constructed programmatically. To customize, extendDependencyVulnerabilityCheckBaseand override one or both methods depending on your needs. For example, overridesupplementalVulnerabilities()to add custom CVEs while keeping the standard vulnerability database, or overridebaselineVulnerabilities()to use an entirely different vulnerability data source.
- org.openrewrite.recipe.rewrite-java-security.InlineDeprecatedMethods
- Inline deprecated delegating methods
- Automatically generated recipes to inline deprecated method calls that delegate to other methods in the same class.
- org.openrewrite.text.FindHardcodedLoopbackAddresses
- Find hard-coded loopback IPv4 addresses
- Locates mentions of hard-coded IPv4 addresses from the loopback IP range. The loopback IP range includes
127.0.0.0to127.255.255.255. This detects the entire localhost/loopback subnet range, not just the commonly used127.0.0.1.
- org.openrewrite.text.FindHardcodedPrivateIPAddresses
- Find hard-coded private IPv4 addresses
- Locates mentions of hard-coded IPv4 addresses from private IP ranges. Private IP ranges include: *
192.168.0.0to192.168.255.255*10.0.0.0to10.255.255.255*172.16.0.0to172.31.255.255It is not detecting the localhost subnet127.0.0.0to127.255.255.255.
- org.openrewrite.text.RemoveHardcodedIPAddressesFromComments
- Remove hard-coded IP addresses from comments
- Removes hard-coded IPv4 addresses from comments when they match private IP ranges or loopback addresses. This targets IP addresses that are commented out in various comment formats: Private IP ranges: *
192.168.0.0to192.168.255.255*10.0.0.0to10.255.255.255*172.16.0.0to172.31.255.255Loopback IP range: *127.0.0.0to127.255.255.255Supported comment formats: * C-style line comments (//) * C-style block comments (/* */) * Shell/Python style comments (#) * XML comments (<!-- -->) * YAML comments (#) * Properties file comments (#or!) For line comments, the entire line is removed. For block comments, only the IP address is removed.
rewrite-kubernetes
- org.openrewrite.kubernetes.AddConfiguration
- Add Kubernetes configuration
- Add default required configuration when it is missing.
- org.openrewrite.kubernetes.ChangeApiVersion
- Change Kubernetes API version
- Change the Kubernetes API version in a resource.
- org.openrewrite.kubernetes.ImagePullPolicyAlways
- Ensure image pull policy is
Always - Ensures the latest version of a tag is deployed each time.
- Ensure image pull policy is
- org.openrewrite.kubernetes.KubernetesBestPractices
- Kubernetes best practices
- Applies best practices to Kubernetes manifests.
- org.openrewrite.kubernetes.LifecycleRuleOnStorageBucket
- Ensure lifecycle rule on
StorageBucket - When defining a rule, you can specify any set of conditions for any action. The following configuration defines a rule to delete all objects older than 7 days in a bucket.
- Ensure lifecycle rule on
- org.openrewrite.kubernetes.LimitContainerCapabilities
- Limit root capabilities in a container
- Limiting the admission of containers with capabilities ensures that only a small number of containers have extended capabilities outside the default range.
- org.openrewrite.kubernetes.MissingCpuLimits
- Ensure CPU limits are set
- A system without managed quotas could eventually collapse due to inadequate resources for the tasks it bares.
- org.openrewrite.kubernetes.MissingCpuRequest
- Ensure CPU request is set
- If a container is created in a namespace that has a default CPU limit, and the container does not specify its own CPU limit, then the container is assigned the default CPU limit.
- org.openrewrite.kubernetes.MissingMemoryLimits
- Ensure memory limits are set
- With no limit set, kubectl allocates more and more memory to the container until it runs out.
- org.openrewrite.kubernetes.MissingMemoryRequest
- Ensure memory request is set
- A container is guaranteed to have as much memory as it requests, but is not allowed to use more memory than the limit set. This configuration may save resources and prevent an attack on an exploited container.
- org.openrewrite.kubernetes.MissingPodLivenessProbe
- Ensure liveness probe is configured
- The kubelet uses liveness probes to know when to schedule restarts for containers. Restarting a container in a deadlock state can help to make the application more available, despite bugs.
- org.openrewrite.kubernetes.MissingPodReadinessProbe
- Ensure readiness probe is configured
- Using the Readiness Probe ensures teams define what actions need to be taken to prevent failure and ensure recovery in case of unexpected errors.
- org.openrewrite.kubernetes.NoHostIPCSharing
- No host IPC sharing
- Preventing sharing of host PID/IPC namespace, networking, and ports ensures proper isolation between Docker containers and the underlying host.
- org.openrewrite.kubernetes.NoHostNetworkSharing
- No host network sharing
- When using the host network mode for a container, that container’s network stack is not isolated from the Docker host, so the container shares the host’s networking namespace and does not get its own IP-address allocation.
- org.openrewrite.kubernetes.NoHostProcessIdSharing
- No host process ID sharing
- Sharing the host process ID namespace breaks the isolation between container images and can make processes visible to other containers in the pod. This includes all information in the /proc directory, which can sometimes include passwords or keys, passed as environment variables.
- org.openrewrite.kubernetes.NoPrivilegeEscalation
- No privilege escalation
- Does not allow a process to gain more privileges than its parent process.
- org.openrewrite.kubernetes.NoPrivilegedContainers
- No privileged containers
- Privileged containers are containers that have all of the root capabilities of a host machine, allowing access to resources that are not accessible in ordinary containers.
- org.openrewrite.kubernetes.NoRootContainers
- No root containers
- Containers that run as root frequently have more permissions than their workload requires which, in case of compromise, could help an attacker further their exploits.
- org.openrewrite.kubernetes.ReadOnlyRootFilesystem
- Read-only root filesystem
- Using an immutable root filesystem and a verified boot mechanism prevents against attackers from "owning" the machine through permanent local changes.
- org.openrewrite.kubernetes.UpdateContainerImageName
- Update image name
- Search for image names that match patterns and replace the components of the name with new values.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_16
- Migrate to Kubernetes API v1.16
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.16.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_22
- Migrate to Kubernetes API v1.22
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.22.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_25
- Migrate to Kubernetes API v1.25
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.25.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_26
- Migrate to Kubernetes API v1.26
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.26.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_27
- Migrate to Kubernetes API v1.27
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.27.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_29
- Migrate to Kubernetes API v1.29
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.29.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_32
- Migrate to Kubernetes API v1.32
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.32.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_33
- Migrate to Kubernetes API v1.33
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.33.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_34
- Migrate to Kubernetes API v1.34
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.34.
- org.openrewrite.kubernetes.migrate.MigrateToAPIv1_35
- Migrate to Kubernetes API v1.35
- This recipe will apply changes commonly needed when migrating to Kubernetes API v1.35.
- org.openrewrite.kubernetes.rbac.AddRuleToRole
- Add RBAC rules
- Add RBAC rules to ClusterRoles or namespaced Roles.
- org.openrewrite.kubernetes.resource.CapResourceValueToMaximum
- Cap exceeds resource value
- Cap resource values that exceed a specific maximum.
- org.openrewrite.kubernetes.resource.FindExceedsResourceRatio
- Find exceeds resource ratio
- Find resource manifests that have requests to limits ratios beyond a specific maximum.
- org.openrewrite.kubernetes.resource.FindExceedsResourceValue
- Find exceeds resource limit
- Find resource manifests that have limits set beyond a specific maximum.
- org.openrewrite.kubernetes.search.FindAnnotation
- Find annotation
- Find annotations that optionally match a given regex.
- org.openrewrite.kubernetes.search.FindDisallowedImageTags
- Find disallowed image tags
- The set of image tags to find which are considered disallowed.
- org.openrewrite.kubernetes.search.FindHarcodedIPAddresses
- Find hardcoded IP addresses
- Find hardcoded IP address anywhere in text-based files.
- org.openrewrite.kubernetes.search.FindImage
- Find image by name
- The image name to search for in containers and initContainers.
- org.openrewrite.kubernetes.search.FindMissingDigest
- Find missing image digest
- Find instances of a container name that fails to specify a digest.
- org.openrewrite.kubernetes.search.FindMissingOrInvalidAnnotation
- Find annotation
- Find annotations that optionally match a given value.
- org.openrewrite.kubernetes.search.FindMissingOrInvalidLabel
- Find label
- Find labels that optionally match a given regex.
- org.openrewrite.kubernetes.search.FindNonTlsIngress
- Find non-TLS Ingresses
- Find Ingress resources that don't disallow HTTP or don't have TLS configured.
- org.openrewrite.kubernetes.search.FindResourceMissingConfiguration
- Find missing configuration
- Find Kubernetes resources with missing configuration.
- org.openrewrite.kubernetes.services.FindServiceExternalIPs
- Find uses of
externalIP - Find any
ServicewhoseexternalIPlist contains, or does not contain, one of a list of IPs.
- Find uses of
- org.openrewrite.kubernetes.services.FindServicesByType
- Service type
- Type of Kubernetes
Serviceto find.
- org.openrewrite.kubernetes.services.UpdateServiceExternalIP
- Update
ServiceexternalIP - Swap out an IP address with another one in
ServiceexternalIPsettings.
- Update
rewrite-migrate-kotlin
- androidx.compose.animation.ReplaceDeprecatedAnimationCore1Methods
- Replace deprecated
animation-coremethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- androidx.compose.material.ReplaceDeprecatedMaterial1Methods
- Replace deprecated
materialmethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- androidx.compose.material3.ReplaceDeprecatedMaterial31Methods
- Replace deprecated
material3methods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- androidx.compose.runtime.ReplaceDeprecatedRuntime1Methods
- Replace deprecated
runtimemethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.jetbrains.kotlinx.ReplaceDeprecatedKotlinxCollectionsImmutable0Methods
- Replace deprecated
kotlinx-collections-immutablemethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.jetbrains.kotlinx.ReplaceDeprecatedKotlinxCoroutinesCore1Methods
- Replace deprecated
kotlinx-coroutines-coremethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.jetbrains.kotlinx.ReplaceDeprecatedKotlinxDatetime0Methods
- Replace deprecated
kotlinx-datetimemethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.jetbrains.kotlinx.ReplaceDeprecatedKotlinxIoCore0Methods
- Replace deprecated
kotlinx-io-coremethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.jetbrains.kotlinx.ReplaceDeprecatedKotlinxSerializationCore1Methods
- Replace deprecated
kotlinx-serialization-coremethods - Automatically generated recipes to replace deprecated Kotlin methods based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.openrewrite.kotlin.compose.ReplaceDeprecatedComposeMethods
- Replace deprecated Jetpack Compose methods
- Replace deprecated Jetpack Compose method calls with their recommended replacements, based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- org.openrewrite.kotlin.exposed.ExposedChangeMethodNames
- Rename Exposed deprecated methods for 1.0
- Rename deprecated Exposed method and property references to their 1.0 replacements.
- org.openrewrite.kotlin.exposed.ExposedChangeTypes
- Migrate Exposed type references to 1.0 packages
- Change fully qualified type references from Exposed 0.x packages to Exposed 1.0 packages. The 1.0 release reorganized all packages under
org.jetbrains.exposed.v1.*and split classes acrosscore,jdbc, anddaomodules.
- org.openrewrite.kotlin.exposed.ExposedUpgradeGradleDependencies
- Upgrade Exposed Gradle dependencies to 1.0
- Update JetBrains Exposed Gradle dependencies for the 1.0.0 migration. Upgrades dependency versions and handles the
exposed-migrationmodule split.
- org.openrewrite.kotlin.exposed.UpgradeToExposed_1
- Migrate to JetBrains Exposed 1.0
- Migrate from JetBrains Exposed 0.x to 1.0.0. This includes package reorganization (adding
v1prefix), type moves between modules, class renames, method renames, and Gradle dependency updates. Some changes require manual intervention and are not covered by this recipe:Table.uuid()should be changed toTable.javaUUID()forjava.util.UUIDvalues,DateColumnTypewith constructor parametertime=falseortime=trueshould be split intoJodaLocalDateColumnTypeorJodaLocalDateTimeColumnType,SqlExpressionBuilder.*usages should be replaced with top-level function imports, andStatement.execute()calls should useBlockingExecutablewrapping.
- org.openrewrite.kotlin.kotlinx.ReplaceDeprecatedKotlinxMethods
- Replace deprecated
kotlinxmethods - Replace deprecated Kotlin extension library method calls with their recommended replacements, based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
- Replace deprecated
- org.openrewrite.kotlin.migrate.RemoveDeprecatedKotlinGradleProperties
- Remove deprecated Kotlin Gradle properties
- Remove deprecated Kotlin Gradle properties from
gradle.properties.kotlin.experimental.coroutineswas removed in Kotlin 2.x.
- org.openrewrite.kotlin.migrate.RemoveRedundantKotlinStdlib
- Remove redundant kotlin-stdlib dependencies
- Remove explicit
kotlin-stdlib,kotlin-stdlib-jdk7,kotlin-stdlib-jdk8, andkotlin-stdlib-commondependencies. The Kotlin Gradle plugin has automatically included the stdlib since Kotlin 1.4, making explicit declarations redundant.
- org.openrewrite.kotlin.migrate.ReplaceDeprecatedAppendln
- Replace deprecated
appendlnwithappendLine - Replace
appendln()withappendLine(). This was deprecated in Kotlin 1.4 and becomes an error in Kotlin 2.1.
- Replace deprecated
- org.openrewrite.kotlin.migrate.ReplaceDeprecatedCapitalizeAndDecapitalize
- Replace deprecated
capitalizeanddecapitalize - Replace
String.capitalize()withString.replaceFirstChar \{ if (it.isLowerCase()) it.titlecase() else it.toString() \}andString.decapitalize()withString.replaceFirstChar \{ it.lowercase() \}. These were deprecated in Kotlin 1.5 and become errors in Kotlin 2.1.
- Replace deprecated
- org.openrewrite.kotlin.migrate.ReplaceDeprecatedCharCaseConversions
- Replace deprecated Char case conversions
- Replace
Char.toLowerCase()withChar.lowercaseChar()andChar.toUpperCase()withChar.uppercaseChar(). These were deprecated in Kotlin 1.5 and become errors in Kotlin 2.1.
- org.openrewrite.kotlin.migrate.ReplaceDeprecatedStringCaseConversions
- Replace deprecated String case conversions
- Replace
String.toLowerCase()withString.lowercase()andString.toUpperCase()withString.uppercase(). These were deprecated in Kotlin 1.5 and become errors in Kotlin 2.1.
- org.openrewrite.kotlin.migrate.ReplaceEnumValuesFunctionWithEnumEntries
- Replace
enumValues<T>()withenumEntries<T>() - Replace calls to
enumValues<T>()withenumEntries<T>(). TheenumEntriesfunction returns an efficient immutable list instead of creating a new array. Deprecated since Kotlin 1.9, recommended replacement for Kotlin 2.x.
- Replace
- org.openrewrite.kotlin.migrate.ReplaceEnumValuesWithEntries
- Replace
Enum.values()withEnum.entries - Replace calls to
Enum.values()with theEnum.entriesproperty. Theentriesproperty returns an efficient immutable list instead of creating a new array on each call. Deprecated since Kotlin 1.9, recommended replacement for Kotlin 2.x.
- Replace
- org.openrewrite.kotlin.migrate.ReplaceKotlinOptionsWithCompilerOptions
- Replace
kotlinOptionswithcompilerOptionsin Gradle build files - Rename the deprecated
kotlinOptionsDSL block tocompilerOptionsin Gradle build files. ThekotlinOptionsDSL was deprecated in Kotlin 2.0 and removed in Kotlin 2.2.
- Replace
- org.openrewrite.kotlin.migrate.UpgradeKotlinGradlePlugins
- Upgrade Kotlin Gradle plugins to 2.x
- Upgrade all
org.jetbrains.kotlin.*Gradle plugins to Kotlin 2.x. This includes the core kotlin-jvm plugin as well as all official Kotlin Gradle plugins such as serialization, Spring, allopen, noarg, JPA, and parcelize.
- org.openrewrite.kotlin.migrate.UpgradeKotlinxCoroutines_1_10
- Upgrade to
kotlinx-coroutines1.10 - Upgrade kotlinx-coroutines to 1.10.x and replace deprecated method calls.
- Upgrade to
- org.openrewrite.kotlin.migrate.UpgradeKotlinxDatetime_0_7
- Migrate to
kotlinx-datetime0.7 - Migrate from kotlinx-datetime 0.6.x to 0.7.x. This includes replacing
kotlinx.datetime.Instantandkotlinx.datetime.Clockwith theirkotlin.timeequivalents and replacing deprecated method calls.
- Migrate to
- org.openrewrite.kotlin.migrate.UpgradeKotlinxSerialization_1_8
- Upgrade to
kotlinx-serialization1.8 - Upgrade kotlinx-serialization to 1.8.x and replace deprecated method calls.
- Upgrade to
- org.openrewrite.kotlin.migrate.UpgradeToKotlin2
- Migrate to Kotlin 2
- Migrate deprecated Kotlin 1.x APIs to their Kotlin 2.x replacements and update Gradle build files for Kotlin 2.x compatibility. Deprecated APIs were deprecated in Kotlin 1.4-1.5 and become errors in Kotlin 2.1.
- org.openrewrite.kotlin.replace.ReplaceKotlinMethod
- Replace Kotlin method
- Replaces Kotlin method calls based on
@Deprecated(replaceWith=ReplaceWith(...))annotations.
rewrite-migrate-python
- org.openrewrite.python.migrate.DependencyInsight
- Python dependency insight
- Find Python dependencies, including transitive dependencies, matching a package name pattern. Results include the resolved version, scope, and whether the dependency is direct or transitive.
- org.openrewrite.python.migrate.FindFutureImports
- Find
__future__imports - Find
__future__imports and add a search marker.
- Find
- org.openrewrite.python.migrate.FindMethods
- Find Python function and method usages
- Find function and method calls by pattern. Covers standalone functions, class methods, static methods, and constructor calls.
- org.openrewrite.python.migrate.FindTypes
- Find Python types
- Find type references by name. Identifies classes matching a type pattern. In Python, all type definitions use the
classkeyword, covering regular classes, abstract base classes, protocols, enums, dataclasses, named tuples, typed dicts, and more.
- org.openrewrite.python.migrate.MigrateToPyprojectToml
- Migrate to
pyproject.toml - Migrate Python projects from
requirements.txtand/orsetup.cfgtopyproject.tomlwithhatchlingbuild backend.
- Migrate to
rewrite-nodejs
- org.openrewrite.node.dependency-vulnerability-check
- Find and fix vulnerable npm dependencies
- This software composition analysis (SCA) tool detects and upgrades dependencies with publicly disclosed vulnerabilities. This recipe both generates a report of vulnerable dependencies and upgrades to newer versions with fixes. This recipe by default only upgrades to the latest patch version. If a minor or major upgrade is required to reach the fixed version, this can be controlled using the
maximumUpgradeDeltaoption. Vulnerability information comes from the GitHub Security Advisory Database, which aggregates vulnerability data from several public databases, including the National Vulnerability Database maintained by the United States government. ## Customizing Vulnerability Data This recipe can be customized by extendingDependencyVulnerabilityCheckand overriding the vulnerability data sources: -baselineVulnerabilities(ctx): Provides the default set of known vulnerabilities. The base implementation loads vulnerability data from the GitHub Security Advisory Database CSV file. Override this method to replace the entire vulnerability dataset with your own curated list. -supplementalVulnerabilities(ctx): Allows adding custom vulnerability data beyond the baseline. The base implementation returns an empty list. Override this method to add organization-specific vulnerabilities, internal security advisories, or vulnerabilities from additional sources while retaining the baseline GitHub Advisory Database. Both methods returnVulnerability[]arrays. Vulnerability data can be loaded from CSV files usingVulnerabilityDatabase.loadFromFile(path).getAllVulnerabilities()or constructed programmatically. For example, overridesupplementalVulnerabilities()to add custom CVEs while keeping the standard vulnerability database, or overridebaselineVulnerabilities()to use an entirely different vulnerability data source.
- org.openrewrite.node.migrate.buffer.replace-deprecated-slice
- Replace deprecated
Buffer.slice()withBuffer.subarray() - Replace deprecated
buffer.slice()calls withbuffer.subarray()for compatibility with Uint8Array.prototype.slice().
- Replace deprecated
- org.openrewrite.node.migrate.buffer.replace-slow-buffer
- Replace deprecated
SlowBufferwithBuffer.allocUnsafeSlow() - Replace deprecated
new SlowBuffer(size)calls withBuffer.allocUnsafeSlow(size). SlowBuffer was used to create un-pooled Buffer instances, but has been removed in favor of the explicit Buffer.allocUnsafeSlow() method.
- Replace deprecated
- org.openrewrite.node.migrate.crypto.find-create-cipher
- Find deprecated
crypto.createCipher()andcrypto.createDecipher()usage crypto.createCipher()andcrypto.createDecipher()were deprecated in Node.js 10 (DEP0106) and removed in Node.js 22. Usecrypto.createCipheriv()andcrypto.createDecipheriv()instead.
- Find deprecated
- org.openrewrite.node.migrate.crypto.replace-crypto-fips
- Replace deprecated
crypto.fipswithcrypto.getFips()andcrypto.setFips() - Replace deprecated
crypto.fipsproperty access withcrypto.getFips()for reads andcrypto.setFips(value)for writes.
- Replace deprecated
- org.openrewrite.node.migrate.crypto.replace-hash-constructor
- Replace deprecated
new crypto.Hash()andnew crypto.Hmac()with factory methods - Replace deprecated
new crypto.Hash(algorithm)constructor calls withcrypto.createHash(algorithm)andnew crypto.Hmac(algorithm, key)withcrypto.createHmac(algorithm, key)factory methods.
- Replace deprecated
- org.openrewrite.node.migrate.find-process-assert
- Find deprecated
process.assert()usage process.assert()was deprecated in Node.js 10 (DEP0100) and removed in Node.js 23. Use theassertmodule instead.
- Find deprecated
- org.openrewrite.node.migrate.find-punycode-usage
- Find deprecated
punycodemodule usage - The
punycodebuilt-in module was deprecated in Node.js 21 (DEP0040). Use the userlandpunycodepackage from npm orurl.domainToASCII/url.domainToUnicodeinstead.
- Find deprecated
- org.openrewrite.node.migrate.fs.replace-dirent-path
- Replace
dirent.pathwithdirent.parentPath - Replaces deprecated
dirent.pathproperty access withdirent.parentPathonfs.Direntinstances to address DEP0178 deprecation.
- Replace
- org.openrewrite.node.migrate.fs.replace-fs-access-constants
- Replace deprecated
fs.F_OK,fs.R_OK,fs.W_OK,fs.X_OKwithfs.constants.* - Replace deprecated file access constants (
fs.F_OK,fs.R_OK,fs.W_OK,fs.X_OK) with their equivalents fromfs.constants. These constants were removed in Node.js v24+ and should be accessed through the constants namespace.
- Replace deprecated
- org.openrewrite.node.migrate.fs.replace-fs-truncate-fd
- Replace
fs.truncate()with file descriptor tofs.ftruncate() - Replace deprecated
fs.truncate(fd, ...)andfs.truncateSync(fd, ...)calls withfs.ftruncate(fd, ...)andfs.ftruncateSync(fd, ...)when the first argument is a file descriptor (number).
- Replace
- org.openrewrite.node.migrate.fs.replace-stats-constructor
- Replace deprecated
fs.Statsconstructor with object literal - Replace deprecated
new fs.Stats()constructor calls with an object literal containing Stats properties initialized to undefined.
- Replace deprecated
- org.openrewrite.node.migrate.http.replace-outgoing-message-headers
- Replace
OutgoingMessage._headersand._headerNameswith public methods - Replace deprecated
OutgoingMessage.prototype._headerswithgetHeaders(),setHeader(),removeHeader()andOutgoingMessage.prototype._headerNameswithgetHeaderNames()to address DEP0066 deprecation.
- Replace
- org.openrewrite.node.migrate.increase-node-engine-version
- Increase Node.js engine version
- Increases the upper bound of the
engines.nodeversion range in package.json to allow the specified Node.js version.
- org.openrewrite.node.migrate.increase-node-engine-version-in-github-actions
- Increase Node.js version in GitHub Actions
- Increases
node-versioninactions/setup-nodesteps in GitHub Actions workflows. Only modifies plain major version values (e.g.20) and x-ranges (e.g.20.x). Never decreases the version.
- org.openrewrite.node.migrate.net.remove-set-simultaneous-accepts
- Remove deprecated
net._setSimultaneousAccepts() - Remove calls to deprecated
net._setSimultaneousAccepts()which was an undocumented internal function that is no longer necessary.
- Remove deprecated
- org.openrewrite.node.migrate.process.coerce-process-exit-code
- Coerce
process.exit()andprocess.exitCodeto integer - Wraps non-integer values passed to
process.exit()or assigned toprocess.exitCodewithMath.trunc()to avoid the DEP0164 deprecation warning about implicit coercion to integer.
- Coerce
- org.openrewrite.node.migrate.process.remove-usage-of-features-tls-underscore_constants
- Remove usage of deprecated
process.features.tls_*properties - Remove references to deprecated
process.features.tls_*properties, replace withprocess.features.tls.
- Remove usage of deprecated
- org.openrewrite.node.migrate.stream.replace-internal-modules
- Replace deprecated
node:_stream_*withnode:stream - Replace deprecated internal stream module imports like
require('node:_stream_readable')with the publicnode:streammodule.
- Replace deprecated
- org.openrewrite.node.migrate.timers.find-timers-active
- Find deprecated
timers.active()andtimers._unrefActive()usage timers.active()(DEP0126) andtimers._unrefActive()(DEP0127) were deprecated and removed in Node.js 24. Usetimeout.refresh()instead.
- Find deprecated
- org.openrewrite.node.migrate.tls.find-tls-secure-pair
- Find deprecated
tls.SecurePairandtls.createSecurePair()usage tls.SecurePair(DEP0043) andtls.createSecurePair()(DEP0064) were deprecated and removed in Node.js 24. Usetls.TLSSocketinstead.
- Find deprecated
- org.openrewrite.node.migrate.tls.replace-internal-modules
- Replace deprecated
node:_tls_commonandnode:_tls_wrapwithnode:tls - Replace deprecated internal TLS module imports
require('node:_tls_common')andrequire('node:_tls_wrap')with the publicnode:tlsmodule.
- Replace deprecated
- org.openrewrite.node.migrate.upgrade-node-22
- Upgrade to Node.js 22
- Migrate deprecated APIs for Node.js 22 compatibility. Addresses Node 22 runtime deprecations and deprecations from earlier versions.
- org.openrewrite.node.migrate.upgrade-node-24
- Upgrade to Node.js 24
- Migrate deprecated APIs for Node.js 24 compatibility. Includes all migrations from Node.js 22, plus Node 23 and Node 24 deprecations.
- org.openrewrite.node.migrate.util.remove-promisify-on-promise
- Remove unnecessary
util.promisify()on Promise-returning functions - Removes
util.promisify()calls on functions that already return a Promise. Since Node.js v17.0.0, calling promisify on a function that returns a Promise emits a runtime deprecation warning (DEP0174).
- Remove unnecessary
- org.openrewrite.node.migrate.util.replace-is-webassembly-compiled-module
- Replace deprecated
util.types.isWebAssemblyCompiledModule() - Replace
util.types.isWebAssemblyCompiledModule(value)withvalue instanceof WebAssembly.Module.
- Replace deprecated
- org.openrewrite.node.migrate.util.replace-util-extend
- Replace deprecated
util._extend()withObject.assign() - Replace deprecated
util._extend(target, source)calls withObject.assign(target, source)which preserves the mutation behavior.
- Replace deprecated
- org.openrewrite.node.migrate.util.replace-util-log
- Replace deprecated
util.log()withconsole.log() - Replace deprecated
util.log()calls withconsole.log(). Note:util.log()included timestamps, butconsole.log()does not.
- Replace deprecated
- org.openrewrite.node.migrate.util.use-native-type-checking-methods
- Replace deprecated
util.isX()methods with native JavaScript - The
utilmodule's type-checking methods have been removed in Node 22.
- Replace deprecated
- org.openrewrite.node.migrate.zlib.replace-bytes-read
- Replace deprecated
zlib.bytesReadwithzlib.bytesWritten - Replace deprecated
bytesReadproperty on zlib streams withbytesWritten.
- Replace deprecated
- org.openrewrite.node.security.remove-redundant-overrides
- Remove redundant dependency overrides
- Removes overrides/resolutions from package.json that are redundant because the dependency tree already resolves to the overridden version or higher.
- org.openrewrite.nodejs.UpgradeDependencyVersion
- Upgrade Node.js dependencies
- Upgrade matching Node.js direct dependencies.
- org.openrewrite.nodejs.search.DatabaseInteractionInsights
- Javascript database interaction library insights
- Discover which popular javascript database interaction libraries (Sequelize, TypeORM, Mongoose, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.DependencyInsight
- Node.js dependency insight
- Identify the direct and transitive Node.js dependencies used in a project.
- org.openrewrite.nodejs.search.FindNodeProjects
- Find Node.js projects
- Find Node.js projects and summarize data about them.
- org.openrewrite.nodejs.search.FormHandlingInsights
- Javascript form handling library insights
- Discover which popular javascript form handling libraries (Formik, React Hook Form, Yup, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.LintingFormattingInsights
- Javascript linting & formatting library insights
- Discover which popular javascript linting and formatting libraries (ESLint, Prettier, Stylelint, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.RealTimeCommunicationInsights
- Javascript real-time communication library insights
- Discover which popular javascript real-time communication libraries (Socket.io, Ws, SockJS, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.SecurityInsights
- Javascript security library insights
- Discover which popular javascript security libraries (Helmet, Cors, Bcrypt, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.ServerSideFrameworksInsights
- Javascript server-side frameworks insights
- Discover which popular javascript server-side frameworks (Express, Koa, Hapi, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.StateManagementInsights
- Javascript state management library insights
- Discover which popular javascript state management libraries (Redux, MobX, Vuex, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.TaskRunnersBuildToolsInsights
- Javascript task runners & build tools insights
- Discover which popular javascript task runners and build tools (Webpack, Parcel, Gulp, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.TestingInsights
- Javascript testing library insights
- Discover which popular javascript testing libraries (Jest, Mocha, Chai, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.UIInsights
- Javascript UI library insights
- Discover which popular javascript UI libraries (React, Vue.js, Angular, etc.) are being used in your projects.
- org.openrewrite.nodejs.search.UtilityInsights
- Javascript utility library insights
- Discover which popular javascript utility libraries (Lodash, Moment.js, Date-fns, etc.) are being used in your projects.
rewrite-reactive-streams
- org.openrewrite.reactive.reactor.ReactorBestPractices
- Reactor Best Practices
- This recipe applies best practices for using Reactor.
- org.openrewrite.reactive.reactor.ReactorDoAfterSuccessOrErrorToTap
- Replace
doAfterSuccessOrErrorcalls withtapoperator - As of reactor-core 3.5 the
doAfterSuccessOrErrormethod is removed, this recipe replaces it with thetapoperator.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCacheToSinkRecipes
- Replace various
Processor.cachecalls with theirSinksequivalent - As of 3.5 Processors are deprecated and Sinks are preferred.
- Replace various
- org.openrewrite.reactive.reactor.ReactorProcessorCacheToSinkRecipes$ReplayProcessorCacheDefaultToSinkRecipe
- Replace
ReplayProcessor.cacheLast()withSinks.many().replay().latest() - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCacheToSinkRecipes$ReplayProcessorCacheToSinkRecipe
- Replace
ReplayProcessor.cacheLast()withSinks.many().replay().latest() - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes
- Replace various
Processor.createcalls with theirSinksequivalent - As of 3.5 Processors are deprecated and Sinks are preferred.
- Replace various
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$DirectProcessorCreateToSinkRecipe
- Replace
DirectProcessor.create()withSinks.many().multicast().directBestEffort() - As of 3.5 DirectProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$EmitterProcessorCreateBooleanToSinkRecipe
- Replace
EmitterProcessor.create(Boolean)withSinks.many().multicast().onBackpressureBuffer(Queues.SMALL_BUFFER_SIZE, Boolean) - As of 3.5 EmitterProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$EmitterProcessorCreateIntBooleanToSinkRecipe
- Replace
EmitterProcessor.create(int, Boolean)withSinks.many().multicast().onBackpressureBuffer(int, Boolean) - As of 3.5 EmitterProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$EmitterProcessorCreateIntToSinkRecipe
- Replace
EmitterProcessor.create(int)withSinks.many().multicast().onBackpressureBuffer(int) - As of 3.5 EmitterProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$EmitterProcessorCreateToSinkRecipe
- Replace
EmitterProcessor.create()withSinks.many().multicast().onBackpressureBuffer() - As of 3.5 EmitterProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$MonoProcessorCreateToSinkRecipe
- Replace
MonoProcessor.create()withSinks.one() - As of 3.5 MonoProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateIntLiteralFalseToSinkRecipe
- Replace
ReplayProcessor.create(int, false)withSinks.many().replay().limit(int) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateIntLiteralTrueToSinkRecipe
- Replace
ReplayProcessor.create(int, true)withSinks.many().replay().all(int) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateIntToSinkRecipe
- Replace
ReplayProcessor.create(int)withSinks.many().replay().limit(int) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateSizeAndTimeoutSchedulerToSinkRecipe
- Replace
ReplayProcessor.createSizeAndTimeout(int, Duration, Scheduler)withSinks.many().replay().limit(int, Duration, Scheduler) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateSizeAndTimeoutToSinkRecipe
- Replace
ReplayProcessor.createSizeAndTimeout(int, Duration)withSinks.many().replay().limit(int, duration) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateTimeoutSchedulerToSinkRecipe
- Replace
ReplayProcessor.createTimeout(Duration, Scheduler)withSinks.many().replay().limit(Duration, Scheduler) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateTimeoutToSinkRecipe
- Replace
ReplayProcessor.createTimeout(Duration)withSinks.many().replay().limit(duration) - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$ReplayProcessorCreateToSinkRecipe
- Replace
ReplayProcessor.create()withSinks.many().replay().all() - As of 3.5 ReplayProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$UnicastProcessorCreateQueueConsumerDisposableToSinkRecipe
- Replace
UnicastProcessor.create(Queue, Consumer, Disposable)withSinks.many().unicast().onBackpressureBuffer(Queue, Disposable) - As of 3.5 UnicastProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$UnicastProcessorCreateQueueDisposableToSinkRecipe
- Replace
UnicastProcessor.create(Queue, Disposable)withSinks.many().unicast().onBackpressureBuffer(Queue, Disposable) - As of 3.5 UnicastProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$UnicastProcessorCreateQueueToSinkRecipe
- Replace
UnicastProcessor.create(Queue)withSinks.many().unicast().onBackpressureBuffer(Queue) - As of 3.5 UnicastProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.ReactorProcessorCreateToSinkRecipes$UnicastProcessorCreateToSinkRecipe
- Replace
UnicastProcessor.create()withSinks.many().unicast().onBackpressureBuffer() - As of 3.5 UnicastProcessor is deprecated and Sinks are preferred.
- Replace
- org.openrewrite.reactive.reactor.UpgradeReactor_3_5
- Migrate to Reactor 3.5
- Adopt to breaking changes in Reactor 3.5.
rewrite-sql
- org.openrewrite.sql.ChangeFunctionName
- Change a SQL function name
- When migrating between dialects, often one name can be substituted for another. For example, Oracle's
NVLfunction can be replaced with PostgresCOALESCE.
- org.openrewrite.sql.ConvertDataType
- Convert SQL data type
- When migrating between SQL dialects, data types often need to be converted. For example, Oracle's
VARCHAR2can be replaced with PostgresVARCHAR, orNUMBERwithNUMERIC.
- org.openrewrite.sql.ConvertOracleDataTypesToPostgres
- Convert Oracle data types to PostgreSQL
- Replaces Oracle-specific data types with PostgreSQL equivalents.
- org.openrewrite.sql.ConvertOracleFunctionsToPostgres
- Convert Oracle functions to PostgreSQL
- Replaces Oracle-specific functions with PostgreSQL equivalents.
- org.openrewrite.sql.ConvertSqlServerDataTypesToPostgres
- Convert SQL Server data types to PostgreSQL
- Replaces SQL Server-specific data types with PostgreSQL equivalents.
- org.openrewrite.sql.ConvertSqlServerFunctionsToPostgres
- Convert SQL Server functions to PostgreSQL
- Replaces SQL Server-specific functions with PostgreSQL equivalents.
- org.openrewrite.sql.FindSql
- Find SQL in code and resource files
- Find SQL in code (e.g. in string literals) and in resources like those ending with
.sql.
- org.openrewrite.sql.FormatSql
- Format SQL in string text blocks
- Checks whether a text block may contain SQL, and if so, formats the text accordingly.
- org.openrewrite.sql.MigrateOracleToPostgres
- Migrate Oracle SQL to PostgreSQL
- Converts Oracle-specific SQL syntax and functions to PostgreSQL equivalents.
- org.openrewrite.sql.MigrateSqlServerToPostgres
- Migrate SQL Server to PostgreSQL
- Converts Microsoft SQL Server-specific SQL syntax and functions to PostgreSQL equivalents.
- org.openrewrite.sql.search.FindFunction
- Find SQL function
- Find SQL functions by name.
rewrite-struts
- org.openrewrite.java.struts.MigrateStrutsDtd
- Migrate DTD to a specific Struts version
- Update Struts DTD to reflect the specified version.
- org.openrewrite.java.struts.migrate2.MigrateActionClass
- Migrate Struts 1 Action to Struts 2 ActionSupport
- Migrates Struts 1.x Action classes to Struts 2.x ActionSupport, transforming the execute method signature and return statements.
- org.openrewrite.java.struts.migrate2.MigrateJspTaglib
- Migrate JSP taglib directives for Struts 2
- Update Struts 1 taglib directives to Struts 2 taglib.
- org.openrewrite.java.struts.migrate2.MigrateJspTags
- Migrate Struts 1 JSP tags to Struts 2
- Transforms Struts 1 JSP tags (
html:,bean:,logic:) to Struts 2 tags (s:).
- org.openrewrite.java.struts.migrate2.MigrateStruts2
- Migrate to Struts 2.x from Struts 1.x
- Comprehensive migration from Struts 1.x to Struts 2.x framework.
- org.openrewrite.java.struts.migrate2.MigrateStrutsConfig
- Migrate
struts-config.xmltostruts.xml - Transforms Struts 1.x
struts-config.xmlto Struts 2.xstruts.xmlformat.
- Migrate
- org.openrewrite.java.struts.migrate2.MigrateWebXml
- Migrate web.xml from Struts 1 to Struts 2
- Converts Struts 1 ActionServlet configuration to Struts 2 StrutsPrepareAndExecuteFilter.
- org.openrewrite.java.struts.migrate6.MigrateAwareInterfaces
- Migrate Struts 2.0 interceptors to action "aware" interfaces
- These types have moved to a new package in Struts 6.0 and their methods have been renamed from set* to with*.
- org.openrewrite.java.struts.migrate6.MigrateDateTagFormat
- Migrate Struts date tag format patterns
- Converts SimpleDateFormat patterns in
<s:date>tags to DateTimeFormatter-compatible patterns. Struts 6.0 uses DateTimeFormatter instead of SimpleDateFormat, which has different pattern letter meanings.
- org.openrewrite.java.struts.migrate6.MigrateDynamicMethodInvocation
- Migrate Dynamic Method Invocation to explicit action mappings
- Identifies Struts configurations using Dynamic Method Invocation (DMI) and marks them for migration, as DMI is disabled by default in Struts 6 for security reasons.
- org.openrewrite.java.struts.migrate6.MigrateOpenSymphonyClasses
- Migrate OpenSymphony classes to Struts 6.0
- Migrate classes from
com.opensymphony.xwork2to their replacements inorg.apache.struts2.
- org.openrewrite.java.struts.migrate6.MigrateStaticOgnlMethodAccess
- Migrate static OGNL method access to action wrapper methods
- Migrates OGNL expressions using static method access (e.g.,
@com.app.Util@makeCode()) to use action wrapper methods instead. Static method access is disabled by default in Struts 6 for security reasons.
- org.openrewrite.java.struts.migrate6.MigrateStruts6
- Migrate to Struts 6.0
- Migrate Struts 2.x to Struts 6.0.
- org.openrewrite.java.struts.migrate6.MigrateStruts6Constants
- Migrate to Struts 6.0 constants
- All Xwork constants had been already deprecated, with this version all of them have been removed and Struts constants have been used instead.
- org.openrewrite.java.struts.migrate6.MigrateValidatorDtd
- Migrate
xwork-validatorDTD to 1.0.4 - Update
xwork-validatorDTD from 1.0.3 to 1.0.4 for Struts 6 compatibility.
- Migrate
- org.openrewrite.java.struts.migrate6.RemoveFreemarkerHtmlBuiltin
- Remove deprecated Freemarker
?htmlbuilt-in - Removes the deprecated
?htmlbuilt-in from Freemarker templates. After migrating to Struts 6 with the latest Freemarker (which enables auto-escaping by default), the?htmlbuilt-in is no longer needed and should be removed. See the Struts 2.5 to 6.0 migration guide.
- Remove deprecated Freemarker
- org.openrewrite.java.struts.migrate6.UpgradeStruts6Dependencies
- Upgrade Struts 6.0 dependencies
- Upgrade Struts 2.x dependencies to Struts 6.0.
- org.openrewrite.java.struts.migrate7.MigrateStruts7
- Migrate to Struts 7.0
- Migrate Struts 6.x to Struts 7.x.
- org.openrewrite.java.struts.migrate7.RenameOpenSymphonyToStruts2
- Rename OpenSymphony / XWork classes to Struts 7 packages
- Updates classes moved from com.opensymphony.xwork2.* to their new org.apache.struts2.* packages in Struts 7.
- org.openrewrite.java.struts.migrate7.UpdateStruts7Constants
- Align Struts XML constants for Struts 7
- Updates Struts XML constants that were renamed or tightened in Struts 7.
- org.openrewrite.java.struts.search.FindStaticOgnlMethodAccess
- Find static OGNL method access
- Find OGNL expressions that use static method access (e.g.,
@com.app.Util@makeCode()), which is disabled by default in Struts 6 for security reasons. These expressions need to be migrated to use action instance methods instead.
- org.openrewrite.java.struts.search.FindStrutsActions
- Find Struts actions
- Find actions and their associated definitions.
rewrite-terraform
- org.openrewrite.terraform.AddConfiguration
- Add Terraform configuration
- If the configuration has a different value, leave it alone. If it is missing, add it.
- org.openrewrite.terraform.AddResourceNestedBlock
- Add a nested block to a Terraform resource
- Add a nested block (e.g.
parameter \{ ... \}) to a Terraform resource if no matching instance exists. WhenkeyMatchersis provided, the recipe deduplicates by attribute keys so it works correctly with repeatable blocks likeaws_db_parameter_group.parameter.
- org.openrewrite.terraform.ChangeResourceAttribute
- Change Terraform resource attribute
- Change the value of a Terraform resource attribute if it matches a given pattern.
- org.openrewrite.terraform.ChangeResourceNestedBlockAttribute
- Change a single attribute inside a Terraform resource's nested block
- Change the value of an attribute inside a specific instance of a nested block on a Terraform resource (e.g. set
value = "0"on theparameter \{ name = "local_infile" \}block of anaws_db_parameter_group). UsekeyMatchersto identify a single instance among repeatable blocks.
- org.openrewrite.terraform.MoveProviderVersionToRequiredProviders
- Move provider version to
required_providers - In Terraform 0.13+, version constraints should be specified in the
terraform \{ required_providers \{ ... \} \}block instead of theproviderblock. This recipe removes theversionattribute fromproviderblocks and adds it torequired_providers.
- Move provider version to
- org.openrewrite.terraform.SecureRandom
- Use a long enough byte length for
randomresources - Use a long enough byte length for
randomresources.
- Use a long enough byte length for
- org.openrewrite.terraform.UpgradeTerraformTo0_14
- Upgrade Terraform to 0.14
- Migrate Terraform configuration from 0.13 to 0.14. Moves version constraints from
providerblocks toterraform \{ required_providers \{ ... \} \}.
- org.openrewrite.terraform.aws.AWSBestPractices
- Best practices for AWS
- Securely operate on Amazon Web Services.
- org.openrewrite.terraform.aws.DisableInstanceMetadataServiceV1
- Disable Instance Metadata Service version 1
- As a request/response method IMDSv1 is prone to local misconfigurations.
- org.openrewrite.terraform.aws.EnableApiGatewayCaching
- Enable API gateway caching
- Enable caching for all methods of API Gateway.
- org.openrewrite.terraform.aws.EnableDynamoDbPITR
- Enable point-in-time recovery for DynamoDB
- DynamoDB Point-In-Time Recovery (PITR) is an automatic backup service for DynamoDB table data that helps protect your DynamoDB tables from accidental write or delete operations.
- org.openrewrite.terraform.aws.EnableECRScanOnPush
- Scan images pushed to ECR
- ECR Image Scanning assesses and identifies operating system vulnerabilities. Using automated image scans you can ensure container image vulnerabilities are found before getting pushed to production.
- org.openrewrite.terraform.aws.EncryptAuroraClusters
- Encrypt Aurora clusters
- Native Aurora encryption helps protect your cloud applications and fulfils compliance requirements for data-at-rest encryption.
- org.openrewrite.terraform.aws.EncryptCodeBuild
- Encrypt CodeBuild projects
- Build artifacts, such as a cache, logs, exported raw test report data files, and build results, are encrypted by default using CMKs for Amazon S3 that are managed by the AWS Key Management Service.
- org.openrewrite.terraform.aws.EncryptDAXStorage
- Encrypt DAX storage at rest
- DAX encryption at rest automatically integrates with AWS KMS for managing the single service default key used to encrypt clusters.
- org.openrewrite.terraform.aws.EncryptDocumentDB
- Encrypt DocumentDB storage
- The encryption feature available for Amazon DocumentDB clusters provides an additional layer of data protection by helping secure your data against unauthorized access to the underlying storage.
- org.openrewrite.terraform.aws.EncryptEBSSnapshots
- Encrypt EBS snapshots
- EBS snapshots should be encrypted, as they often include sensitive information, customer PII or CPNI.
- org.openrewrite.terraform.aws.EncryptEBSVolumeLaunchConfiguration
- Encrypt EBS volume launch configurations
- EBS volumes allow you to create encrypted launch configurations when creating EC2 instances and auto scaling. When the entire EBS volume is encrypted, data stored at rest on the volume, disk I/O, snapshots created from the volume, and data in-transit between EBS and EC2 are all encrypted.
- org.openrewrite.terraform.aws.EncryptEBSVolumes
- Encrypt EBS volumes
- Encrypting EBS volumes ensures that replicated copies of your images are secure even if they are accidentally exposed. AWS EBS encryption uses AWS KMS customer master keys (CMK) when creating encrypted volumes and snapshots. Storing EBS volumes in their encrypted state reduces the risk of data exposure or data loss.
- org.openrewrite.terraform.aws.EncryptEFSVolumesInECSTaskDefinitionsInTransit
- Encrypt EFS Volumes in ECS Task Definitions in transit
- Enable attached EFS definitions in ECS tasks to use encryption in transit.
- org.openrewrite.terraform.aws.EncryptElastiCacheRedisAtRest
- Encrypt ElastiCache Redis at rest
- ElastiCache for Redis offers default encryption at rest as a service.
- org.openrewrite.terraform.aws.EncryptElastiCacheRedisInTransit
- Encrypt ElastiCache Redis in transit
- ElastiCache for Redis offers optional encryption in transit. In-transit encryption provides an additional layer of data protection when transferring data over standard HTTPS protocol.
- org.openrewrite.terraform.aws.EncryptNeptuneStorage
- Encrypt Neptune storage
- Encryption of Neptune storage protects data and metadata against unauthorized access.
- org.openrewrite.terraform.aws.EncryptRDSClusters
- Encrypt RDS clusters
- Native RDS encryption helps protect your cloud applications and fulfils compliance requirements for data-at-rest encryption.
- org.openrewrite.terraform.aws.EncryptRedshift
- Encrypt Redshift storage at rest
- Redshift clusters should be securely encrypted at rest.
- org.openrewrite.terraform.aws.EnsureAWSCMKRotationIsEnabled
- Ensure AWS CMK rotation is enabled
- Ensure AWS CMK rotation is enabled.
- org.openrewrite.terraform.aws.EnsureAWSEFSWithEncryptionForDataAtRestIsEnabled
- Ensure AWS EFS with encryption for data at rest is enabled
- Ensure AWS EFS with encryption for data at rest is enabled.
- org.openrewrite.terraform.aws.EnsureAWSEKSClusterEndpointAccessIsPubliclyDisabled
- Ensure AWS EKS cluster endpoint access is publicly disabled
- Ensure AWS EKS cluster endpoint access is publicly disabled.
- org.openrewrite.terraform.aws.EnsureAWSElasticsearchDomainEncryptionForDataAtRestIsEnabled
- Ensure AWS Elasticsearch domain encryption for data at rest is enabled
- Ensure AWS Elasticsearch domain encryption for data at rest is enabled.
- org.openrewrite.terraform.aws.EnsureAWSElasticsearchDomainsHaveEnforceHTTPSEnabled
- Ensure AWS Elasticsearch domains have
EnforceHTTPSenabled - Ensure AWS Elasticsearch domains have
EnforceHTTPSenabled.
- Ensure AWS Elasticsearch domains have
- org.openrewrite.terraform.aws.EnsureAWSElasticsearchHasNodeToNodeEncryptionEnabled
- Ensure AWS Elasticsearch has node-to-node encryption enabled
- Ensure AWS Elasticsearch has node-to-node encryption enabled.
- org.openrewrite.terraform.aws.EnsureAWSIAMPasswordPolicyHasAMinimumOf14Characters
- Ensure AWS IAM password policy has a minimum of 14 characters
- Ensure AWS IAM password policy has a minimum of 14 characters.
- org.openrewrite.terraform.aws.EnsureAWSLambdaFunctionIsConfiguredForFunctionLevelConcurrentExecutionLimit
- Ensure AWS Lambda function is configured for function-level concurrent execution limit
- Ensure AWS Lambda function is configured for function-level concurrent execution limit.
- org.openrewrite.terraform.aws.EnsureAWSLambdaFunctionsHaveTracingEnabled
- Ensure AWS Lambda functions have tracing enabled
- Ensure AWS Lambda functions have tracing enabled.
- org.openrewrite.terraform.aws.EnsureAWSRDSDatabaseInstanceIsNotPubliclyAccessible
- Ensure AWS RDS database instance is not publicly accessible
- Ensure AWS RDS database instance is not publicly accessible.
- org.openrewrite.terraform.aws.EnsureAWSS3ObjectVersioningIsEnabled
- Ensure AWS S3 object versioning is enabled
- Ensure AWS S3 object versioning is enabled.
- org.openrewrite.terraform.aws.EnsureAmazonEKSControlPlaneLoggingEnabledForAllLogTypes
- Ensure Amazon EKS control plane logging enabled for all log types
- Ensure Amazon EKS control plane logging enabled for all log types.
- org.openrewrite.terraform.aws.EnsureCloudTrailLogFileValidationIsEnabled
- Ensure CloudTrail log file validation is enabled
- Ensure CloudTrail log file validation is enabled.
- org.openrewrite.terraform.aws.EnsureDataStoredInAnS3BucketIsSecurelyEncryptedAtRest
- Ensure data stored in an S3 bucket is securely encrypted at rest
- Ensure data stored in an S3 bucket is securely encrypted at rest.
- org.openrewrite.terraform.aws.EnsureDetailedMonitoringForEC2InstancesIsEnabled
- Ensure detailed monitoring for EC2 instances is enabled
- Ensure detailed monitoring for EC2 instances is enabled.
- org.openrewrite.terraform.aws.EnsureEC2IsEBSOptimized
- Ensure EC2 is EBS optimized
- Ensure EC2 is EBS optimized.
- org.openrewrite.terraform.aws.EnsureECRRepositoriesAreEncrypted
- Ensure ECR repositories are encrypted
- Ensure ECR repositories are encrypted.
- org.openrewrite.terraform.aws.EnsureEnhancedMonitoringForAmazonRDSInstancesIsEnabled
- Ensure enhanced monitoring for Amazon RDS instances is enabled
- Ensure enhanced monitoring for Amazon RDS instances is enabled.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyExpiresPasswordsWithin90DaysOrLess
- Ensure IAM password policy expires passwords within 90 days or less
- Ensure IAM password policy expires passwords within 90 days or less.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyPreventsPasswordReuse
- Ensure IAM password policy prevents password reuse
- Ensure IAM password policy prevents password reuse.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyRequiresAtLeastOneLowercaseLetter
- Ensure IAM password policy requires at least one lowercase letter
- Ensure IAM password policy requires at least one lowercase letter.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyRequiresAtLeastOneNumber
- Ensure IAM password policy requires at least one number
- Ensure IAM password policy requires at least one number.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyRequiresAtLeastOneSymbol
- Ensure IAM password policy requires at least one symbol
- Ensure IAM password policy requires at least one symbol.
- org.openrewrite.terraform.aws.EnsureIAMPasswordPolicyRequiresAtLeastOneUppercaseLetter
- Ensure IAM password policy requires at least one uppercase letter
- Ensure IAM password policy requires at least one uppercase letter.
- org.openrewrite.terraform.aws.EnsureKinesisStreamIsSecurelyEncrypted
- Ensure Kinesis Stream is securely encrypted
- Ensure Kinesis Stream is securely encrypted.
- org.openrewrite.terraform.aws.EnsureRDSDatabaseHasIAMAuthenticationEnabled
- Ensure RDS database has IAM authentication enabled
- Ensure RDS database has IAM authentication enabled.
- org.openrewrite.terraform.aws.EnsureRDSInstancesHaveMultiAZEnabled
- Ensure RDS instances have Multi-AZ enabled
- Ensure RDS instances have Multi-AZ enabled.
- org.openrewrite.terraform.aws.EnsureRespectiveLogsOfAmazonRDSAreEnabled
- Ensure respective logs of Amazon RDS are enabled
- Ensure respective logs of Amazon RDS are enabled.
- org.openrewrite.terraform.aws.EnsureTheS3BucketHasAccessLoggingEnabled
- Ensure the S3 bucket has access logging enabled
- Ensure the S3 bucket has access logging enabled.
- org.openrewrite.terraform.aws.EnsureVPCSubnetsDoNotAssignPublicIPByDefault
- Ensure VPC subnets do not assign public IP by default
- Ensure VPC subnets do not assign public IP by default.
- org.openrewrite.terraform.aws.ImmutableECRTags
- Make ECR tags immutable
- Amazon ECR supports immutable tags, preventing image tags from being overwritten. In the past, ECR tags could have been overwritten, this could be overcome by requiring users to uniquely identify an image using a naming convention.
- org.openrewrite.terraform.aws.UpgradeAwsAuroraMySqlToV3
- Upgrade AWS Aurora MySQL to version 3 (MySQL 8.0)
- Upgrade
engine_versionto Aurora MySQL version 3 (MySQL 8.0 compatible) onaws_rds_clusterresources and setallow_major_version_upgrade = trueto permit the major version change.
- org.openrewrite.terraform.aws.UpgradeAwsAuroraPostgresToV17
- Upgrade AWS Aurora PostgreSQL to 17
- Upgrade
engine_versionto Aurora PostgreSQL 17 onaws_rds_clusterresources and setallow_major_version_upgrade = trueto permit the major version change.
- org.openrewrite.terraform.aws.UpgradeAwsRdsMySqlToV8_4
- Upgrade AWS RDS MySQL to 8.4
- Upgrade
engine_versionto MySQL 8.4 onaws_db_instanceresources and setallow_major_version_upgrade = trueto permit the major version change.
- org.openrewrite.terraform.aws.UpgradeAwsRdsPostgresToV17
- Upgrade AWS RDS PostgreSQL to 17
- Upgrade
engine_versionto PostgreSQL 17 onaws_db_instanceresources and setallow_major_version_upgrade = trueto permit the major version change.
- org.openrewrite.terraform.aws.UseHttpsForCloudfrontDistribution
- Use HTTPS for Cloudfront distribution
- Secure communication by default.
- org.openrewrite.terraform.azure.AzureBestPractices
- Best practices for Azure
- Securely operate on Microsoft Azure.
- org.openrewrite.terraform.azure.DisableKubernetesDashboard
- Disable Kubernetes dashboard
- Disabling the dashboard eliminates it as an attack vector. The dashboard add-on is disabled by default for all new clusters created on Kubernetes 1.18 or greater.
- org.openrewrite.terraform.azure.EnableAzureStorageAccountTrustedMicrosoftServicesAccess
- Enable Azure Storage Account Trusted Microsoft Services access
- Certain Microsoft services that interact with storage accounts operate from networks that cannot be granted access through network rules. Using this configuration, you can allow the set of trusted Microsoft services to bypass those network rules.
- org.openrewrite.terraform.azure.EnableAzureStorageSecureTransferRequired
- Enable Azure Storage secure transfer required
- Microsoft recommends requiring secure transfer for all storage accounts.
- org.openrewrite.terraform.azure.EnableGeoRedundantBackupsOnPostgreSQLServer
- Enable geo-redundant backups on PostgreSQL server
- Ensure PostgreSQL server enables geo-redundant backups.
- org.openrewrite.terraform.azure.EncryptAzureVMDataDiskWithADECMK
- Encrypt Azure VM data disk with ADE/CMK
- Ensure Azure VM data disk is encrypted with ADE/CMK.
- org.openrewrite.terraform.azure.EnsureAKSPoliciesAddOn
- Ensure AKS policies add-on
- Azure Policy Add-on for Kubernetes service (AKS) extends Gatekeeper v3, an admission controller webhook for Open Policy Agent (OPA), to apply at-scale enforcements and safeguards on your clusters in a centralized, consistent manner.
- org.openrewrite.terraform.azure.EnsureAKVSecretsHaveAnExpirationDateSet
- Ensure AKV secrets have an expiration date set
- Ensure AKV secrets have an expiration date set.
- org.openrewrite.terraform.azure.EnsureASecurityContactPhoneNumberIsPresent
- Ensure a security contact phone number is present
- Ensure a security contact phone number is present.
- org.openrewrite.terraform.azure.EnsureActivityLogRetentionIsSetTo365DaysOrGreater
- Ensure activity log retention is set to 365 days or greater
- Ensure activity log retention is set to 365 days or greater.
- org.openrewrite.terraform.azure.EnsureAllKeysHaveAnExpirationDate
- Ensure all keys have an expiration date
- Ensure all keys have an expiration date.
- org.openrewrite.terraform.azure.EnsureAppServiceEnablesDetailedErrorMessages
- Ensure app service enables detailed error messages
- Ensure app service enables detailed error messages.
- org.openrewrite.terraform.azure.EnsureAppServiceEnablesFailedRequestTracing
- Ensure app service enables failed request tracing
- Ensure app service enables failed request tracing.
- org.openrewrite.terraform.azure.EnsureAppServiceEnablesHTTPLogging
- Ensure app service enables HTTP logging
- Ensure app service enables HTTP logging.
- org.openrewrite.terraform.azure.EnsureAppServicesUseAzureFiles
- Ensure app services use Azure files
- Ensure app services use Azure files.
- org.openrewrite.terraform.azure.EnsureAzureAppServiceWebAppRedirectsHTTPToHTTPS
- Ensure Azure App Service Web app redirects HTTP to HTTPS
- Ensure Azure App Service Web app redirects HTTP to HTTPS.
- org.openrewrite.terraform.azure.EnsureAzureApplicationGatewayHasWAFEnabled
- Ensure Azure application gateway has WAF enabled
- Ensure Azure application gateway has WAF enabled.
- org.openrewrite.terraform.azure.EnsureAzureKeyVaultIsRecoverable
- Ensure Azure key vault is recoverable
- Ensure Azure key vault is recoverable.
- org.openrewrite.terraform.azure.EnsureAzureNetworkWatcherNSGFlowLogsRetentionIsGreaterThan90Days
- Ensure Azure Network Watcher NSG flow logs retention is greater than 90 days
- Ensure Azure Network Watcher NSG flow logs retention is greater than 90 days.
- org.openrewrite.terraform.azure.EnsureAzurePostgreSQLDatabaseServerWithSSLConnectionIsEnabled
- Ensure Azure PostgreSQL database server with SSL connection is enabled
- Ensure Azure PostgreSQL database server with SSL connection is enabled.
- org.openrewrite.terraform.azure.EnsureAzureSQLServerAuditLogRetentionIsGreaterThan90Days
- Ensure Azure SQL server audit log retention is greater than 90 days
- Ensure Azure SQL server audit log retention is greater than 90 days.
- org.openrewrite.terraform.azure.EnsureAzureSQLServerSendAlertsToFieldValueIsSet
- Ensure Azure SQL server send alerts to field value is set
- Ensure Azure SQL server send alerts to field value is set.
- org.openrewrite.terraform.azure.EnsureAzureSQLServerThreatDetectionAlertsAreEnabledForAllThreatTypes
- Ensure Azure SQL Server threat detection alerts are enabled for all threat types
- Ensure Azure SQL Server threat detection alerts are enabled for all threat types.
- org.openrewrite.terraform.azure.EnsureFTPDeploymentsAreDisabled
- Ensure FTP Deployments are disabled
- Ensure FTP Deployments are disabled.
- org.openrewrite.terraform.azure.EnsureKeyVaultAllowsFirewallRulesSettings
- Ensure key vault allows firewall rules settings
- Ensure key vault allows firewall rules settings.
- org.openrewrite.terraform.azure.EnsureKeyVaultEnablesPurgeProtection
- Ensure key vault enables purge protection
- Ensure key vault enables purge protection.
- org.openrewrite.terraform.azure.EnsureKeyVaultKeyIsBackedByHSM
- Ensure key vault key is backed by HSM
- Ensure key vault key is backed by HSM.
- org.openrewrite.terraform.azure.EnsureKeyVaultSecretsHaveContentTypeSet
- Ensure key vault secrets have
content_typeset - Ensure key vault secrets have
content_typeset.
- Ensure key vault secrets have
- org.openrewrite.terraform.azure.EnsureLogProfileIsConfiguredToCaptureAllActivities
- Ensure log profile is configured to capture all activities
- Ensure log profile is configured to capture all activities.
- org.openrewrite.terraform.azure.EnsureMSSQLServersHaveEmailServiceAndCoAdministratorsEnabled
- Ensure MSSQL servers have email service and co-administrators enabled
- Ensure MSSQL servers have email service and co-administrators enabled.
- org.openrewrite.terraform.azure.EnsureManagedIdentityProviderIsEnabledForAppServices
- Ensure managed identity provider is enabled for app services
- Ensure managed identity provider is enabled for app services.
- org.openrewrite.terraform.azure.EnsureMySQLIsUsingTheLatestVersionOfTLSEncryption
- Ensure MySQL is using the latest version of TLS encryption
- Ensure MySQL is using the latest version of TLS encryption.
- org.openrewrite.terraform.azure.EnsureMySQLServerDatabasesHaveEnforceSSLConnectionEnabled
- Ensure MySQL server databases have Enforce SSL connection enabled
- Ensure MySQL server databases have Enforce SSL connection enabled.
- org.openrewrite.terraform.azure.EnsureMySQLServerDisablesPublicNetworkAccess
- Ensure MySQL server disables public network access
- Ensure MySQL server disables public network access.
- org.openrewrite.terraform.azure.EnsureMySQLServerEnablesGeoRedundantBackups
- Ensure MySQL server enables geo-redundant backups
- Ensure MySQL server enables geo-redundant backups.
- org.openrewrite.terraform.azure.EnsureMySQLServerEnablesThreatDetectionPolicy
- Ensure MySQL server enables Threat Detection policy
- Ensure MySQL server enables Threat Detection policy.
- org.openrewrite.terraform.azure.EnsurePostgreSQLServerDisablesPublicNetworkAccess
- Ensure PostgreSQL server disables public network access
- Ensure PostgreSQL server disables public network access.
- org.openrewrite.terraform.azure.EnsurePostgreSQLServerEnablesInfrastructureEncryption
- Ensure PostgreSQL server enables infrastructure encryption
- Ensure PostgreSQL server enables infrastructure encryption.
- org.openrewrite.terraform.azure.EnsurePostgreSQLServerEnablesThreatDetectionPolicy
- Ensure PostgreSQL server enables Threat Detection policy
- Ensure PostgreSQL server enables Threat Detection policy.
- org.openrewrite.terraform.azure.EnsurePublicNetworkAccessEnabledIsSetToFalseForMySQLServers
- Ensure public network access enabled is set to False for mySQL servers
- Ensure public network access enabled is set to False for mySQL servers.
- org.openrewrite.terraform.azure.EnsureSendEmailNotificationForHighSeverityAlertsIsEnabled
- Ensure Send email notification for high severity alerts is enabled
- Ensure Send email notification for high severity alerts is enabled.
- org.openrewrite.terraform.azure.EnsureSendEmailNotificationForHighSeverityAlertsToAdminsIsEnabled
- Ensure Send email notification for high severity alerts to admins is enabled
- Ensure Send email notification for high severity alerts to admins is enabled.
- org.openrewrite.terraform.azure.EnsureStandardPricingTierIsSelected
- Ensure standard pricing tier is selected
- Ensure standard pricing tier is selected.
- org.openrewrite.terraform.azure.EnsureStorageAccountUsesLatestTLSVersion
- Ensure storage account uses latest TLS version
- Communication between an Azure Storage account and a client application is encrypted using Transport Layer Security (TLS). Microsoft recommends using the latest version of TLS for all your Microsoft Azure App Service web applications.
- org.openrewrite.terraform.azure.EnsureTheStorageContainerStoringActivityLogsIsNotPubliclyAccessible
- Ensure the storage container storing activity logs is not publicly accessible
- Ensure the storage container storing activity logs is not publicly accessible.
- org.openrewrite.terraform.azure.EnsureWebAppHasIncomingClientCertificatesEnabled
- Ensure Web App has incoming client certificates enabled
- Ensure Web App has incoming client certificates enabled.
- org.openrewrite.terraform.azure.EnsureWebAppUsesTheLatestVersionOfHTTP
- Ensure Web App uses the latest version of HTTP
- Ensure Web App uses the latest version of HTTP.
- org.openrewrite.terraform.azure.EnsureWebAppUsesTheLatestVersionOfTLSEncryption
- Ensure Web App uses the latest version of TLS encryption
- Ensure Web App uses the latest version of TLS encryption.
- org.openrewrite.terraform.azure.SetAzureStorageAccountDefaultNetworkAccessToDeny
- Set Azure Storage Account default network access to deny
- Ensure Azure Storage Account default network access is set to Deny.
- org.openrewrite.terraform.gcp.EnablePodSecurityPolicyControllerOnGKEClusters
- Enable
PodSecurityPolicycontroller on Google Kubernetes Engine (GKE) clusters - Ensure
PodSecurityPolicycontroller is enabled on Google Kubernetes Engine (GKE) clusters.
- Enable
- org.openrewrite.terraform.gcp.EnableVPCFlowLogsAndIntranodeVisibility
- Enable VPC flow logs and intranode visibility
- Enable VPC flow logs and intranode visibility.
- org.openrewrite.terraform.gcp.EnableVPCFlowLogsForSubnetworks
- Enable VPC Flow Logs for subnetworks
- Ensure GCP VPC flow logs for subnets are enabled. Flow Logs capture information on IP traffic moving through network interfaces. This information can be used to monitor anomalous traffic and provide security insights.
- org.openrewrite.terraform.gcp.EnsureBinaryAuthorizationIsUsed
- Ensure binary authorization is used
- Ensure binary authorization is used.
- org.openrewrite.terraform.gcp.EnsureComputeInstancesLaunchWithShieldedVMEnabled
- Ensure compute instances launch with shielded VM enabled
- Ensure compute instances launch with shielded VM enabled.
- org.openrewrite.terraform.gcp.EnsureGCPCloudStorageBucketWithUniformBucketLevelAccessAreEnabled
- Ensure GCP cloud storage bucket with uniform bucket-level access are enabled
- Ensure GCP cloud storage bucket with uniform bucket-level access are enabled.
- org.openrewrite.terraform.gcp.EnsureGCPKubernetesClusterNodeAutoRepairConfigurationIsEnabled
- Ensure GCP Kubernetes cluster node auto-repair configuration is enabled
- Ensure GCP Kubernetes cluster node auto-repair configuration is enabled.
- org.openrewrite.terraform.gcp.EnsureGCPKubernetesEngineClustersHaveLegacyComputeEngineMetadataEndpointsDisabled
- Ensure GCP Kubernetes engine clusters have legacy compute engine metadata endpoints disabled
- Ensure GCP Kubernetes engine clusters have legacy compute engine metadata endpoints disabled.
- org.openrewrite.terraform.gcp.EnsureGCPVMInstancesHaveBlockProjectWideSSHKeysFeatureEnabled
- Ensure GCP VM instances have block project-wide SSH keys feature enabled
- Ensure GCP VM instances have block project-wide SSH keys feature enabled.
- org.openrewrite.terraform.gcp.EnsureIPForwardingOnInstancesIsDisabled
- Ensure IP forwarding on instances is disabled
- Ensure IP forwarding on instances is disabled.
- org.openrewrite.terraform.gcp.EnsurePrivateClusterIsEnabledWhenCreatingKubernetesClusters
- Ensure private cluster is enabled when creating Kubernetes clusters
- Ensure private cluster is enabled when creating Kubernetes clusters.
- org.openrewrite.terraform.gcp.EnsureSecureBootForShieldedGKENodesIsEnabled
- Ensure secure boot for shielded GKE nodes is enabled
- Ensure secure boot for shielded GKE nodes is enabled.
- org.openrewrite.terraform.gcp.EnsureShieldedGKENodesAreEnabled
- Ensure shielded GKE nodes are enabled
- Ensure shielded GKE nodes are enabled.
- org.openrewrite.terraform.gcp.EnsureTheGKEMetadataServerIsEnabled
- Ensure the GKE metadata server is enabled
- Ensure the GKE metadata server is enabled.
- org.openrewrite.terraform.gcp.GCPBestPractices
- Best practices for GCP
- Securely operate on Google Cloud Platform.
- org.openrewrite.terraform.search.FindRequiredProvider
- Find required providers
- Find
required_providersblocks in Terraform configuration files. Produces a data table of the provider names and their versions.
- org.openrewrite.terraform.search.FindResource
- Find Terraform resource
- Find a Terraform resource by resource type.
- org.openrewrite.terraform.terraform012.RemoveInterpolationOnlyExpressions
- Remove interpolation-only expressions
- Remove unnecessary interpolation expressions like
"$\{var.foo\}"in favor of first-class expression syntaxvar.foo, as supported in Terraform 0.12+.
- org.openrewrite.terraform.terraform012.ReplaceDeprecatedCollectionFunctions
- Replace deprecated
list()andmap()functions - In Terraform 0.12+, the
list()function is replaced by[...]tuple syntax and themap()function is replaced by\{...\}object syntax.
- Replace deprecated
- org.openrewrite.terraform.terraform012.UnquoteTypeConstraints
- Unquote variable type constraints
- In Terraform 0.12+, variable type constraints should be bare types instead of quoted strings. For example,
type = "string"becomestype = string.
- org.openrewrite.terraform.terraform012.UpgradeTerraformTo0_12
- Upgrade Terraform to 0.12
- Migrate Terraform configuration from 0.11 (HCL1) to 0.12 (HCL2) syntax. Removes interpolation-only expressions, unquotes type constraints, replaces deprecated collection functions, and fixes legacy index syntax.
- org.openrewrite.terraform.terraform013.UpgradeRequiredProvidersSyntax
- Upgrade
required_providersto object syntax - In Terraform 0.13+,
required_providersentries should use the object syntax with explicitsourceandversionattributes instead of a plain version string. For example,aws = "~> 3.0"becomesaws = \{ source = "hashicorp/aws", version = "~> 3.0" \}.
- Upgrade
- org.openrewrite.terraform.terraform013.UpgradeTerraformTo0_13
- Upgrade Terraform to 0.13
- Migrate Terraform configuration from 0.12 to 0.13 syntax. Upgrades
required_providersentries from shorthand version strings to the object syntax with explicitsourceandversionattributes.
- org.openrewrite.terraform.terraform015.FindRemovedProvisioners
- Find removed provisioners
- Find usage of provisioners that were removed in Terraform 0.15:
chef,habitat,puppet, andsalt-masterless.
- org.openrewrite.terraform.terraform015.UpgradeTerraformTo0_15
- Upgrade Terraform to 0.15
- Migrate Terraform configuration from 0.14 to 0.15. Finds usage of provisioners that were removed in Terraform 0.15:
chef,habitat,puppet, andsalt-masterless.