io.moderne.recipe
recipes-code-quality
License: Moderne Proprietary License
407 recipes
- OpenRewrite.Recipes.CSharp.CodeQuality.CodeQuality
- Code quality
- All C# code quality recipes, organized by category.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddNewLineAfterOpeningBrace
- Add newline after opening brace
- Add newline after opening brace so the first statement starts on its own line.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddNewLineBeforeReturn
- Add newline before return
- Add a blank line before return statements that follow other statements.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddParagraphToDocComment
- Add paragraph to documentation comment
- Format multi-line documentation comments with paragraph elements.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddParameterToDocComment
- Add parameter name to documentation comment
- Add missing param elements to XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddSummaryElementToDocComment
- Add summary to documentation comment
- Add summary text to documentation comments with empty summary elements.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddSummaryToDocComment
- Add summary element to documentation comment
- Add missing summary element to XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.AddTypeParamToDocComment
- Add 'typeparam' element to documentation comment
- Add missing 'typeparam' elements to XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.FixDocCommentTag
- Fix documentation comment tag
- Replace inline <code> elements with <c> elements in XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.FormatAccessorList
- Format accessor list
- Format property accessor list for consistent whitespace.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.FormatDocumentationSummary
- Format documentation summary
- Format XML documentation summary on a single line or multiple lines.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.FormatSwitchSection
- Format switch section
- Ensure consistent formatting of switch sections.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.FormattingCodeQuality
- Formatting code quality
- Code formatting recipes for C#.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.InvalidDocCommentReference
- Invalid reference in a documentation comment
- Find invalid cref or paramref references in XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.NormalizeWhitespace
- Normalize whitespace
- Normalize whitespace for consistent formatting.
- OpenRewrite.Recipes.CSharp.CodeQuality.Formatting.OrderDocCommentElements
- Order elements in documentation comment
- Order param/typeparam elements to match declaration order.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.CombineLinqMethods
- Combine LINQ methods
- Combine
.Where(predicate).First()and similar patterns into.First(predicate), and consecutive.Where().Where()calls into a single.Where()with a combined predicate. Eliminating intermediate LINQ calls improves readability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.FindOptimizeCountUsage
- Find Count() comparison that could be optimized
- Detect
Count(pred) == nandCount() > ncomparisons which could useWhere().Take(n+1).Count()orSkip(n).Any()for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.FindWhereBeforeOrderBy
- Use Where before OrderBy
- Place
.Where()before.OrderBy()to filter elements before sorting. This reduces the number of items that need to be sorted.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.LinqCodeQuality
- LINQ code quality
- Optimize LINQ method calls for better readability and performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqSelectAverage
- Optimize LINQ Select().Average()
- Replace
items.Select(selector).Average()withitems.Average(selector).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqSelectMax
- Optimize LINQ Select().Max()
- Replace
items.Select(selector).Max()withitems.Max(selector). Passing the selector directly toMaxavoids an intermediate iterator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqSelectMin
- Optimize LINQ Select().Min()
- Replace
items.Select(selector).Min()withitems.Min(selector). Passing the selector directly toMinavoids an intermediate iterator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqSelectSum
- Optimize LINQ Select().Sum()
- Replace
items.Select(selector).Sum()withitems.Sum(selector).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereAny
- Optimize LINQ Where().Any()
- Replace
items.Where(predicate).Any()withitems.Any(predicate). Passing the predicate directly toAnyavoids an intermediate iterator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereCount
- Optimize LINQ Where().Count()
- Replace
items.Where(predicate).Count()withitems.Count(predicate). Passing the predicate directly toCountavoids an intermediate iterator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereCountLong
- Optimize LINQ Where().LongCount()
- Replace
.Where(predicate).LongCount()with.LongCount(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereFirst
- Optimize LINQ Where().First()
- Replace
items.Where(predicate).First()withitems.First(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereFirstOrDefault
- Optimize LINQ Where().FirstOrDefault()
- Replace
items.Where(predicate).FirstOrDefault()withitems.FirstOrDefault(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereLast
- Optimize LINQ Where().Last()
- Replace
items.Where(predicate).Last()withitems.Last(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereLastOrDefault
- Optimize LINQ Where().LastOrDefault()
- Replace
.Where(predicate).LastOrDefault()with.LastOrDefault(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereSingle
- Optimize LINQ Where().Single()
- Replace
items.Where(predicate).Single()withitems.Single(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.OptimizeLinqWhereSingleOrDefault
- Optimize LINQ Where().SingleOrDefault()
- Replace
items.Where(predicate).SingleOrDefault()withitems.SingleOrDefault(predicate).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.RemoveUselessOrderBy
- Remove useless OrderBy call
- Replace
.OrderBy(a).OrderBy(b)with.OrderBy(b). A secondOrderBycompletely replaces the first sort, making the first call useless.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseAnyInsteadOfCount
- Use Any() instead of Count() > 0
- Replace
.Count() > 0with.Any().Any()short-circuits after the first match, whileCount()enumerates all elements.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseCastInsteadOfSelect
- Use Cast<T>() instead of Select with cast
- Replace
.Select(x => (T)x)with.Cast<T>(). TheCast<T>()method is more concise and clearly expresses the intent.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseOrderByDescendingThenByDescending
- Use OrderByDescending().ThenByDescending()
- Replace
.OrderByDescending(a).OrderByDescending(b)with.OrderByDescending(a).ThenByDescending(b).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseOrderByThenBy
- Use ThenBy instead of second OrderBy
- Replace
items.OrderBy(a).OrderBy(b)withitems.OrderBy(a).ThenBy(b). A secondOrderBydiscards the first sort;ThenBypreserves it as a secondary key.
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseOrderByThenByDescending
- Use OrderBy().ThenByDescending()
- Replace
.OrderBy(a).OrderByDescending(b)with.OrderBy(a).ThenByDescending(b).
- OpenRewrite.Recipes.CSharp.CodeQuality.Linq.UseOrderInsteadOfOrderBy
- Use Order() instead of OrderBy() with identity
- Replace
.OrderBy(x => x)with.Order(). TheOrder()method (available since .NET 7) is a cleaner way to sort elements in their natural order.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.AsyncMethodNameShouldEndWithAsync
- Async method name should end with Async
- Find async methods whose names don't end with 'Async' suffix.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.FindAttributeNameShouldEndWithAttribute
- Attribute name should end with 'Attribute'
- Classes that inherit from
System.Attributeshould have names ending with 'Attribute' by convention.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.FindEventArgsNameConvention
- EventArgs name should end with 'EventArgs'
- Classes that inherit from
System.EventArgsshould have names ending with 'EventArgs' by convention.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.FindExceptionNameShouldEndWithException
- Exception name should end with 'Exception'
- Classes that inherit from
System.Exceptionshould have names ending with 'Exception' by convention.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.FindFixTodoComment
- Find TODO/HACK/FIXME comments
- Detect TODO, HACK, UNDONE, and FIXME comments that indicate unfinished work.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.NamingCodeQuality
- Naming code quality
- Naming convention recipes for C# code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.NonAsyncMethodNameShouldNotEndWithAsync
- Non-async method should not end with Async
- Find non-async methods whose names end with 'Async' suffix.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.ParameterNameMatchesBase
- Parameter name should match base definition
- Ensure parameter names match the names used in base class or interface.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.RenameParameterAccordingToConvention
- Rename parameter to camelCase
- Detect parameters not following camelCase naming convention.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.RenamePrivateFieldAccordingToConvention
- Rename private field according to _camelCase convention
- Detect private fields not following _camelCase naming convention.
- OpenRewrite.Recipes.CSharp.CodeQuality.Naming.UseNameofOperator
- Use nameof operator
- Use nameof(parameter) instead of string literal for argument exception constructors.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.AvoidBoxingOfValueType
- Avoid boxing of value type
- Avoid boxing of value type by using generic overloads or ToString().
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.AvoidLockingOnPubliclyAccessible
- Avoid locking on publicly accessible instance
- Avoid lock(this), lock(typeof(T)), or lock on string literals which can cause deadlocks.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.AvoidNullReferenceException
- Avoid NullReferenceException
- Flag patterns that may throw NullReferenceException, such as using 'as' cast result without null check.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.BitOperationOnEnumWithoutFlags
- Bitwise operation on enum without Flags attribute
- Flag bitwise operations on enums that lack the Flags attribute.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.ConvertHasFlagToBitwiseOperation
- Convert HasFlag to bitwise operation
- Replace flags.HasFlag(value) with (flags & value) != 0.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.DoNotPassNonReadOnlyStructByReadOnlyRef
- Do not pass non-read-only struct by read-only reference
- Remove 'in' modifier from parameters of non-readonly struct type to avoid defensive copies.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindAsyncVoid
- Do not use async void
- Async void methods cannot be awaited and exceptions cannot be caught. Use
async Taskinstead, except for event handlers.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindAvoidClosureByUsingFactoryArg
- Find closure in GetOrAdd that could use factory argument
- Detect
ConcurrentDictionary.GetOrAddcalls with lambdas that capture variables. Use the overload with a factory argument parameter to avoid allocation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindAvoidClosureInConcurrentDictionary
- Avoid closure when using ConcurrentDictionary
- ConcurrentDictionary methods like
GetOrAddmay evaluate the factory even when the key exists. Use the overload with a factory argument to avoid closure allocation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindAvoidClosureInMethod
- Find closure in GetOrAdd/AddOrUpdate factory
- Detect closures in lambdas passed to
GetOrAddorAddOrUpdate. Use the factory overload that accepts a state argument to avoid allocations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindBlockingCallsInAsync
- Find blocking calls in async methods
- Detect
.Wait(),.Result, and.GetAwaiter().GetResult()calls in async methods. Blocking calls in async methods can cause deadlocks.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindDoNotUseBlockingCall
- Do not use blocking calls on tasks
- Avoid
.Wait(),.Result, and.GetAwaiter().GetResult()on tasks. These can cause deadlocks. Useawaitinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindDoNotUseToStringIfObject
- Do not use ToString on GetType result
- Using
.GetType().ToString()returns the full type name. Consider using.GetType().Nameor.GetType().FullNameinstead for clarity.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindEqualityComparerDefaultOfString
- Find EqualityComparer<string>.Default usage
- Detect
EqualityComparer<string>.Defaultwhich uses ordinal comparison. Consider using an explicitStringComparerinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindGetTypeOnSystemType
- Find GetType() called on System.Type
- Detect
typeof(T).GetType()which returnsSystem.RuntimeTypeinstead of the expectedSystem.Type. Usetypeof(T)directly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindImplicitCultureSensitiveMethods
- Find implicit culture-sensitive string methods
- Detect calls to
ToLower()andToUpper()without culture parameters. These methods use the current thread culture, which may cause unexpected behavior.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindImplicitCultureSensitiveToString
- Find implicit culture-sensitive ToString calls
- Detect
.ToString()calls without format arguments. On numeric and DateTime types, these use the current thread culture.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindLinqOnDirectMethods
- Find LINQ methods replaceable with direct methods
- Detect LINQ methods like
.Count()that could be replaced with direct collection properties. Direct access avoids enumeration overhead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindMakeMethodStatic
- Find methods that could be static
- Detect private methods that don't appear to use instance members and could be marked
staticfor clarity and performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindMissingCancellationToken
- Find methods not forwarding CancellationToken
- Detect calls to async methods that may have CancellationToken overloads but are called without one. Uses name-based heuristics.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindMissingStructLayout
- Find structs without StructLayout attribute
- Detect struct declarations without
[StructLayout]attribute. Adding[StructLayout(LayoutKind.Auto)]allows the CLR to optimize field layout for better memory usage.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindMissingTimeoutForRegex
- Add timeout to Regex
- Regex without a timeout can be vulnerable to ReDoS attacks. Specify a
TimeSpantimeout or useRegexOptions.NonBacktracking.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindMissingWithCancellation
- Find missing WithCancellation on async enumerables
- Detect async enumerable iteration without
.WithCancellation(). Async enumerables should forward CancellationToken via WithCancellation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindNaNComparison
- Do not use NaN in comparisons
- Comparing with
NaNusing==always returns false. Usedouble.IsNaN(x)instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindOptimizeEnumerableCountVsAny
- Find LINQ Count() on materialized collection
- Detect LINQ
Count()orAny()on types that have aCountorLengthproperty. Use the property directly for O(1) performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindOptimizeGuidCreation
- Find Guid.Parse with constant string
- Detect
Guid.Parse("...")with constant strings. Consider usingnew Guid("...")or a static readonly field for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindOptimizeStartsWith
- Use char overload for single-character string methods
- Convert string methods with single-character string literals to use char overloads for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindSequenceEqualForSpan
- Find Span<char> equality that should use SequenceEqual
- Detect
==and!=operators onSpan<char>orReadOnlySpan<char>which compare references. UseSequenceEqualfor content comparison.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindSimplifyStringCreate
- Find simplifiable string.Create calls
- Detect
string.Create(CultureInfo.InvariantCulture, ...)calls that could be simplified to string interpolation when all parameters are culture-invariant.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindStreamReadResultNotUsed
- Find unused Stream.Read return value
- Detect calls to
Stream.ReadorStream.ReadAsyncwhere the return value is discarded. The return value indicates how many bytes were actually read.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindStringCreateInsteadOfFormattable
- Find FormattableString that could use string.Create
- Detect
FormattableStringusage wherestring.Createwith anIFormatProvidercould be used for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindStringFormatShouldBeConstant
- String.Format format string should be constant
- The format string passed to
string.Formatshould be a compile-time constant to enable analysis and avoid runtime format errors.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindStringGetHashCode
- Find string.GetHashCode() without StringComparer
- Detect calls to
string.GetHashCode()without aStringComparer. The defaultGetHashCode()may produce different results across platforms.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindStructWithDefaultEqualsAsKey
- Find Dictionary/HashSet with struct key type
- Detect
DictionaryorHashSetusage with struct types as keys. Structs without overriddenEquals/GetHashCodeuse slow reflection-based comparison.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseAttributeIsDefined
- Find GetCustomAttributes that could use Attribute.IsDefined
- Detect
GetCustomAttributes().Any()or similar patterns whereAttribute.IsDefinedwould be more efficient.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseContainsKeyInsteadOfTryGetValue
- Use ContainsKey instead of TryGetValue with discard
- When only checking if a key exists, use
ContainsKeyinstead ofTryGetValuewith a discarded out parameter.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseExplicitCaptureRegexOption
- Use RegexOptions.ExplicitCapture
- Use
RegexOptions.ExplicitCaptureto avoid capturing unnamed groups, which improves performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseIndexerInsteadOfLinq
- Find LINQ methods replaceable with indexer
- Detect LINQ methods like
.First()and.Last()that could be replaced with direct indexer access for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseRegexSourceGenerator
- Find Regex that could use source generator
- Detect
new Regex(...)calls that could benefit from the[GeneratedRegex]source generator attribute for better performance (.NET 7+).
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseTimeProviderOverload
- Find calls that could use TimeProvider
- Detect
DateTime.UtcNow,DateTimeOffset.UtcNow, andTask.Delaycalls that could use aTimeProviderparameter for better testability (.NET 8+).
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.FindUseValuesContainsInsteadOfValues
- Find Values.Contains() instead of ContainsValue()
- Detect
.Values.Contains(value)on dictionaries. Use.ContainsValue(value)instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.MakeParameterRefReadOnly
- Make parameter ref read-only
- Use in parameter modifier for large struct parameters.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.OptimizeMethodCall
- Optimize method call
- Replace inefficient method calls with more optimal equivalents.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.OptimizeStringBuilderAppend
- Optimize StringBuilder.Append usage
- Optimize StringBuilder method calls: use char overloads for single-character strings, remove redundant ToString() calls, replace string.Format with AppendFormat, and split string concatenation into chained Append calls.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.PerformanceCodeQuality
- Performance code quality
- Performance optimization recipes for C# code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.ReplaceEnumToStringWithNameof
- Replace Enum.ToString() with nameof
- Replace
MyEnum.Value.ToString()withnameof(MyEnum.Value). Thenameofoperator is evaluated at compile time, avoiding runtime reflection.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.ReturnCompletedTask
- Return completed task instead of null
- Replace return null in Task-returning methods with return Task.CompletedTask.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.ThrowingNotImplementedException
- Throwing of new NotImplementedException
- Find code that throws new NotImplementedException, which may indicate unfinished implementation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UnnecessaryExplicitEnumerator
- Remove unnecessary explicit enumerator
- Use foreach instead of explicit enumerator pattern.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseArrayEmpty
- Use Array.Empty<T>() instead of new T[0]
- Use Array.Empty<T>() instead of allocating empty arrays.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseContainsKey
- Use ContainsKey instead of Keys.Contains
- Replace
.Keys.Contains(key)with.ContainsKey(key)on dictionaries for O(1) performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseCountProperty
- Use Count/Length property instead of Count()
- Replace collection.Count() with collection.Count when available.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseRegexIsMatch
- Use Regex.IsMatch
- Replace Regex.Match(s, p).Success with Regex.IsMatch(s, p).
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseStringBuilderAppendLine
- Use StringBuilder.AppendLine
- Replace
sb.Append("\n")withsb.AppendLine().
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseStringComparison
- Use StringComparison
- Replace case-insensitive string comparisons using
ToLower()/ToUpper()with overloads that acceptStringComparison.OrdinalIgnoreCase.
- OpenRewrite.Recipes.CSharp.CodeQuality.Performance.UseStringConcatInsteadOfJoin
- Use string.Concat instead of string.Join
- Replace
string.Join("", args)withstring.Concat(args).
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.AllBranchesIdentical
- Remove if/else with identical branches
- Replace an if/else chain where every branch has the same body with just the body, since the conditions have no effect on the outcome.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.FileContainsNoCode
- File contains no code
- Find files that contain no code, only using directives, comments, or whitespace.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.FindUnusedInternalType
- Find internal types that may be unused
- Detect
internal(non-public) classes that may be unused. Review these types and remove them if they are no longer needed.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RedundancyCodeQuality
- Redundancy code quality
- Remove redundant code from C# sources.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveArgumentListFromAttribute
- Remove argument list from attribute
- Remove empty argument list from attribute.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveBracesFromRecordDeclaration
- Remove braces from record declaration
- Remove unnecessary braces from record declarations with no body.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveDuplicateConditions
- Remove duplicate conditions
- Remove else-if branches whose condition duplicates an earlier branch in the same if/else-if chain, since the later branch is dead code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyCatchClause
- Find empty catch clause
- Find empty catch clauses that silently swallow exceptions without any logging or handling.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyDestructor
- Remove empty destructor
- Remove destructors (finalizers) with empty bodies.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyFinallyClause
- Remove empty finally clause
- Remove
finally \{ \}clauses that contain no statements. An empty finally block serves no purpose.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyForBody
- Flag empty for loop body
- Flag
forloops with empty bodies as potential dead code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyForEachBody
- Remove empty foreach body
- Remove
foreachloops with empty bodies, which iterate without effect.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptySyntax
- Find empty syntax
- Find empty namespace, class, struct, interface, and enum declarations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEmptyWhileBody
- Remove empty while body
- Remove
while (cond) \{ \}loops with empty bodies as they serve no purpose.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveEnumDefaultUnderlyingType
- Remove enum default underlying type
- Remove : int from enum declaration since int is the default.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveExplicitClassFromRecord
- Remove explicit 'class' from record
- Remove the redundant
classkeyword fromrecord classdeclarations. Records are reference types by default.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemovePartialModifierFromSinglePart
- Remove partial modifier from single-part type
- Remove
partialmodifier from types that have only one part.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantAsOperator
- Remove redundant as operator
- Remove redundant 'as' operator when the expression already has the target type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantAssignment
- Remove redundant assignment
- Remove assignments where the value is immediately returned.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantAsyncAwait
- Remove redundant async/await
- Remove redundant async/await when a Task can be returned directly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantAutoPropertyInit
- Remove redundant constructor
- Remove empty parameterless constructors that duplicate the implicit default.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantAutoPropertyInitialization
- Remove redundant auto-property initialization
- Remove auto-property initializers that assign the default value.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantBaseConstructorCall
- Remove redundant base constructor call
- Remove
: base()parameterless base constructor call since it's implicit.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantBaseInterface
- Remove redundant base interface
- Remove interface that is already inherited by another implemented interface.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantCast
- Remove redundant cast
- Remove unnecessary casts when the expression already has the target type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantCatchBlock
- Remove redundant catch block
- Remove try-catch blocks where every catch clause only rethrows the exception.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantComma
- Remove redundant comma
- Remove redundant trailing comma in enum declarations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantDefaultFieldInitialization
- Remove redundant default field initialization
- Remove field initializations that assign the default value (e.g.,
int x = 0,bool b = false,string s = null,object o = default).
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantDefaultSwitchSection
- Remove redundant default switch section
- Remove default switch section that only contains break.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantDelegateCreation
- Remove redundant delegate creation
- Remove unnecessary
new EventHandler(M)whenMcan be used directly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantDisposeOrClose
- Remove redundant Dispose/Close call
- Remove Dispose/Close calls on objects already in a using block.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantOverridingMember
- Remove redundant overriding member
- Remove overriding member that only calls the base implementation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantParentheses
- Remove redundant parentheses
- Remove unnecessary parentheses around expressions in return statements and assignments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantRegion
- Remove redundant region
- Remove #region/#endregion directives.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantSealedModifier
- Remove redundant sealed modifier
- Remove
sealedmodifier on members of sealed classes, since it's redundant.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantSealedModifierFromOverride
- Remove redundant 'sealed' modifier from override
- Remove redundant 'sealed' modifier from an overriding member in a sealed class.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantStatement
- Remove redundant statement
- Remove redundant
return;at end of void method orcontinue;at end of loop body.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantStringToCharArrayCall
- Remove redundant ToCharArray() call
- Remove
ToCharArray()calls in foreach loops where iterating over the string directly produces the same result.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveRedundantToStringCall
- Remove redundant ToString() call
- Remove
ToString()calls on expressions that are already strings.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveSelfAssignment
- Remove self-assignment
- Remove assignment statements where the variable is assigned to itself, such as
x = x. These have no effect and are likely copy-paste errors.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnconditionalValueOverwrite
- Remove unconditional value overwrite
- Remove consecutive assignments to the same collection key or index where the first value is immediately overwritten and never read.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnnecessaryCaseLabel
- Remove unnecessary case label
- Remove case labels from switch section that has default label.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnnecessaryElse
- Remove unnecessary else clause
- Remove
elseclause when theifbody always terminates withreturn,throw,break,continue, orgoto.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnnecessarySemicolon
- Remove unnecessary semicolon at end of declaration
- Remove unnecessary semicolon at the end of a declaration.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnusedDocCommentElement
- Unused element in documentation comment
- Remove unused param/typeparam elements from XML documentation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnusedMemberDeclaration
- Remove unused member declaration
- Remove member declarations that are never referenced.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.RemoveUnusedThisParameter
- Unused 'this' parameter
- Remove unused 'this' parameter from extension methods.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.ResourceCanBeDisposedAsynchronously
- Resource can be disposed asynchronously
- Use
await usinginstead ofusingwhen the resource implements IAsyncDisposable.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryEnumFlag
- Unnecessary enum flag
- Remove unnecessary enum flag value that is a combination of other flags.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryInterpolatedString
- Remove unnecessary interpolated string
- Replace interpolated strings with no interpolations with regular strings.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryInterpolation
- Unnecessary interpolation
- Remove unnecessary string interpolation, for example simplifying
$"\{x\}"tox.ToString().
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryNullCheck
- Remove unnecessary null check
- Remove null check that is unnecessary because the value is known to be non-null.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryNullForgivingOperator
- Remove unnecessary null-forgiving operator
- Remove ! operator where expression is already non-nullable.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryRawStringLiteral
- Remove unnecessary raw string literal
- Convert raw string literal to regular string when not needed.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryUnsafeContext
- Remove unnecessary unsafe context
- Remove unsafe blocks that do not contain unsafe code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UnnecessaryVerbatimStringLiteral
- Remove unnecessary verbatim string literal
- Remove @ prefix from string literals that do not contain escape sequences.
- OpenRewrite.Recipes.CSharp.CodeQuality.Redundancy.UseRethrow
- Use rethrow instead of throw ex
- Replace
throw ex;withthrow;inside catch clauses whenexis the caught exception variable. A barethrowpreserves the original stack trace.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.CombineWhereMethodChain
- Combine 'Enumerable.Where' method chain
- Combine consecutive Enumerable.Where method calls into a single call with a combined predicate.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.ConvertAnonymousMethodToLambda
- Convert anonymous method to lambda
- Convert anonymous method delegate syntax to lambda expression.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.ConvertIfToAssignment
- Convert 'if' to assignment
- Convert 'if' statement that assigns boolean literals to a simple assignment with the condition expression.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.ConvertInterpolatedStringToConcatenation
- Convert interpolated string to concatenation
- Detect string interpolations that could be simplified to concatenation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.ExpressionAlwaysTrueOrFalse
- Expression is always true or false
- Simplify
x == xtotrueandx != xtofalse.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.InlineLazyInitialization
- Inline lazy initialization
- Use null-coalescing assignment (??=) for lazy initialization.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.InlineLocalVariable
- Inline local variable
- Inline local variable that is assigned once and used once immediately.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.JoinStringExpressions
- Join string expressions
- Join consecutive string literal concatenations into a single literal.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.MergeElseWithNestedIf
- Merge else with nested if
- Merge
else \{ if (...) \{ \} \}intoelse if (...) \{ \}when the else block contains only a single if statement.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.MergeIdenticalBranches
- Merge identical branches
- Merge consecutive if/else-if branches that have identical bodies by combining their conditions with
||.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.MergeIfWithParentIf
- Merge if with parent if
- Merge
if (a) \{ if (b) \{ ... \} \}intoif (a && b) \{ ... \}when the outer if body contains only a single nested if without else.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.MergeSwitchSections
- Merge switch sections with equivalent content
- Merge switch case labels that have identical bodies.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.RemoveRedundantBooleanLiteral
- Remove redundant boolean literal
- Remove redundant
== truecomparison from boolean expressions.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.RemoveUnnecessaryBraces
- Remove unnecessary braces
- Remove braces from single-statement blocks where they are optional.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplificationCodeQuality
- Simplification code quality
- Simplify expressions and patterns in C# code.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyArgumentNullCheck
- Simplify argument null check
- Use ArgumentNullException.ThrowIfNull(arg) instead of manual null check.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyBooleanComparison
- Simplify boolean comparison
- Simplify
true == xtox,false == xto!x,true != xto!x, andfalse != xtox.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyCoalesceExpression
- Simplify coalesce expression
- Simplify x ?? x to x.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyCodeBranching
- Simplify code branching
- Simplify code branching patterns such as empty if-else, while(true) with break, and trailing return/continue in if-else.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyConditionalExpression
- Simplify conditional expression
- Simplify
cond ? true : falsetocondandcond ? false : trueto!cond.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyDoWhileToWhile
- Simplify do-while(true) to while(true)
- Convert
do \{ ... \} while (true)towhile (true) \{ ... \}.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyLazyInitialization
- Simplify lazy initialization
- Simplify lazy initialization using ??= operator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyLogicalNegation
- Simplify logical negation
- Simplify negated comparison expressions. For example,
!(x == y)becomesx != y.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyNegatedIsNull
- Simplify negated is null pattern
- Simplify
!(x is null)tox is not nulland!(x is not null)tox is null.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyNestedUsingStatement
- Simplify nested using statement
- Merge nested
usingstatements into a singleusingdeclaration.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyNullableHasValue
- Simplify Nullable<T>.HasValue
- Replace
x.HasValuewithx != nulland!x.HasValuewithx == null.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyNullableToShorthand
- Simplify Nullable<T> to T?
- Use T? shorthand instead of Nullable<T>.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyNumericComparison
- Simplify numeric comparison
- Simplify
x - y > 0tox > y,x - y < 0tox < y,x - y >= 0tox >= y, andx - y <= 0tox <= y.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyRedundantLogicalExpression
- Simplify redundant logical expression
- Simplify
x && xtox,x || xtox, and similarly for&and|, where both sides of a logical or bitwise operator are identical.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.SimplifyRedundantWhereWhere
- Merge consecutive Where calls
- Detect consecutive
.Where(p).Where(q)calls that could be merged.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UnconstrainedTypeParamNullCheck
- Unconstrained type parameter checked for null
- Find null checks on unconstrained type parameters, which may not be reference types.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UnnecessaryOperator
- Operator is unnecessary
- Remove unnecessary operators such as unary plus.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseAnonymousFunctionOrMethodGroup
- Use anonymous function or method group
- Convert a lambda expression to a method group where appropriate.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseCoalesceExpression
- Use coalesce expression
- Replace
x != null ? x : yandx == null ? y : xwithx ?? y.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseCoalesceExpressionInsteadOfIf
- Use coalesce expression instead of 'if'
- Replace
if (x == null) x = y;withx ??= y.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseCompoundAssignment
- Use compound assignment
- Replace
x = x op ywithx op= yfor arithmetic, bitwise, shift, and null-coalescing operators.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseConditionalAccess
- Use conditional access
- Transform null-check patterns to use conditional access (?.).
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseConditionalAccessInsteadOfIf
- Use conditional access instead of conditional expression
- Transform ternary null-check expressions to use conditional access (?.) with null-coalescing (??) where needed.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseConditionalExpressionForDeclaration
- Use conditional expression in declaration
- Convert
int x; if (cond) x = a; else x = b;toint x = cond ? a : b;.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseConditionalExpressionForReturn
- Use conditional return expression
- Convert
if (c) return a; return b;toreturn c ? a : b;.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseConditionalExpressionForThrow
- Use conditional throw expression
- Detect
if (x == null) throw ...patterns that could usex ?? throw ....
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseDateTimeOffsetUnixEpoch
- Use DateTimeOffset.UnixEpoch
- Replace
new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)withDateTimeOffset.UnixEpoch. Available since .NET 8,DateTimeOffset.UnixEpochis more readable.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseDateTimeUnixEpoch
- Use DateTime.UnixEpoch
- Replace
new DateTime(1970, 1, 1)withDateTime.UnixEpoch. Available since .NET 8,DateTime.UnixEpochis more readable and avoids magic numbers.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseDefaultLiteral
- Use default literal
- Simplify default(T) expressions to default. Note: in rare cases where the type cannot be inferred (e.g., overload resolution), manual review may be needed.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseExceptionFilter
- Use exception filter
- Detect catch blocks with if/throw pattern that could use a when clause.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseExpressionBodiedLambda
- Use expression-bodied lambda
- Convert block-body lambdas with a single statement to expression-body lambdas.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseForInsteadOfWhile
- Use for statement instead of while
- Convert while loops with counter to for loops.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseGuidEmpty
- Use Guid.Empty
- Replace
new Guid()withGuid.Empty. The staticGuid.Emptyfield avoids unnecessary allocations and clearly expresses intent.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseIsOperatorInsteadOfAs
- Use 'is' operator instead of 'as' operator
- Replace 'as' operator followed by null check with 'is' operator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseIsPatternInsteadOfSequenceEqual
- Use 'is' pattern instead of SequenceEqual
- Replace
span.SequenceEqual("str")withspan is "str". Pattern matching with string constants is more concise for span comparisons.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseNotPattern
- Use 'not' pattern instead of negation
- Detect
!(x is Type)patterns that can usex is not Type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingForEquality
- Use pattern matching for equality comparison
- Replace
x == constantwithx is constantfor improved readability using C# pattern matching.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingForInequality
- Use pattern matching for inequality comparison
- Replace
x != constantwithx is not constantfor improved readability using C# pattern matching.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingInsteadOfAs
- Use pattern matching instead of as
- Use pattern matching instead of as. Note: Needs type resolution.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingInsteadOfHasValue
- Use pattern matching instead of HasValue
- Replace
nullable.HasValuewithnullable is not null. Pattern matching is more idiomatic in modern C#. Note: this recipe uses name-based matching and may match non-Nullable types with aHasValueproperty.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingInsteadOfIs
- Use pattern matching instead of is
- Use pattern matching instead of is. Note: Needs type resolution.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePatternMatchingNullCheck
- Use pattern matching for null check
- Replace
x == nullwithx is nullandx != nullwithx is not null.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UsePostfixIncrement
- Use postfix increment/decrement
- Replace
x = x + 1withx++andx = x - 1withx--.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseRangeOperator
- Use range operator
- Detect Substring calls that could use C# 8 range syntax.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseShortCircuitOperator
- Use short-circuit operator
- Replace bitwise
&with&&and|with||in boolean contexts.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseStringEndsWith
- Use string.EndsWith
- Detect substring comparison patterns that could use EndsWith.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseStringEquals
- Use string.Equals instead of == for string comparison
- Replace
==string comparisons withstring.Equals(a, b, StringComparison.Ordinal)for explicit comparison semantics.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseStringInterpolation
- Use string interpolation instead of string.Format
- Replace simple
string.Format("\{0\}", x)calls with$"\{x\}".
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseStringInterpolationInsteadOfConcat
- Use string interpolation instead of concatenation
- Replace string.Concat with string interpolation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseStringStartsWith
- Use string.StartsWith instead of IndexOf comparison
- Replace
s.IndexOf(x) == 0withs.StartsWith(x).
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseSwitchExpression
- Use switch expression
- Convert simple switch statements to switch expressions (C# 8+).
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseThrowExpression
- Use throw expression
- Convert null-check-then-throw patterns to throw expressions.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseTimeSpanZero
- Use TimeSpan.Zero
- Replace
new TimeSpan(0)andTimeSpan.FromX(0)withTimeSpan.Zero. The staticTimeSpan.Zerofield is more readable and avoids unnecessary object creation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Simplification.UseXorForBooleanInequality
- Use ^ operator for boolean inequality
- Replace a != b with a ^ b when both operands are boolean.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AbstractTypeShouldNotHavePublicConstructors
- Abstract type should not have public constructors
- Change public constructors of abstract types to protected.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AddParenthesesForClarity
- Add parentheses for clarity
- Add parentheses to expressions where operator precedence might be unclear to improve readability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AddParenthesesToConditionalExpression
- Add parentheses to conditional expression condition
- Add or remove parentheses from the condition in a conditional operator.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AddRemoveTrailingComma
- Add trailing comma to last enum member
- Add trailing comma to the last member of enum declarations for cleaner diffs when adding new members.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AddStaticToMembersOfStaticClass
- Add static modifier to all members of static class
- Ensure all members of a static class are also declared static.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AddTrailingComma
- Add trailing comma
- Add trailing commas to multi-line initializers and enum declarations for cleaner diffs.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AvoidChainOfAssignments
- Avoid chain of assignments
- Flag chained assignment expressions like a = b = c = value.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.AvoidNestingTernary
- Avoid nested ternary operator
- Replace nested ternary expressions with if/else chains for clarity.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.CallExtensionMethodAsInstance
- Call extension method as instance method
- Use instance method syntax instead of static extension method call.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.CompositeEnumContainsUndefinedFlag
- Composite enum value contains undefined flag
- Find composite enum values that contain a flag which is not defined in the enum type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ConstantValuesOnRightSide
- Place constant values on right side of comparisons
- Move constant values (literals, null) from the left side of comparisons to the right side for consistency and readability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ConvertCommentToDocComment
- Convert comment to documentation comment
- Convert single-line or multi-line comments above declarations to XML documentation comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareEachAttributeSeparately
- Declare each attribute separately
- Declare each attribute in a separate attribute list.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareEachTypeInSeparateFile
- Declare each type in separate file
- Declare each type in a separate file.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareEachTypeSeparately
- Declare each type in separate file
- Flag files containing multiple top-level type declarations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareEnumMemberWithZeroValue
- Declare enum member with zero value
- Ensure [Flags] enums have a member explicitly assigned the value 0.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareEnumValueAsCombination
- Declare enum value as combination of names
- Declare Flags enum values as combinations of named values.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DeclareUsingDirectiveOnTopLevel
- Declare using directive on top level
- Move using directives outside of namespace declarations to the top level of the file.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DefaultLabelShouldBeLast
- Default label should be last
- Move default label to the last position in switch statement.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DuplicateEnumValue
- Flag duplicate enum value
- Flag enum members that have the same underlying value.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.DuplicateWordInComment
- Duplicate word in a comment
- Find and fix duplicate consecutive words in comments.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.EnumShouldDeclareExplicitValues
- Enum should declare explicit values
- Add explicit values to enum members that do not have them.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindArgumentExceptionParameterName
- ArgumentException should specify argument name
- When throwing
ArgumentExceptionor derived types, specify the parameter name usingnameof().
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindAsyncMethodReturnsNull
- Find async void method
- Detect
async voidmethods. Useasync Taskinstead so callers can await and exceptions propagate correctly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindAsyncVoidDelegate
- Find async void delegate
- Detect async lambdas used as delegates where the return type is void. Use
Func<Task>instead ofActionfor async delegates.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindAvoidAnonymousDelegateForUnsubscribe
- Do not use anonymous delegates to unsubscribe from events
- Unsubscribing from events using anonymous delegates or lambdas has no effect because each lambda creates a new delegate instance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindAwaitTaskBeforeDisposing
- Find unawaited task return in using block
- Detect
returnof a Task inside ausingblock withoutawait. The resource may be disposed before the task completes.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindBothConditionSidesIdentical
- Find binary expression with identical sides
- Detect binary expressions where both sides are identical, e.g.
x == xora && a. This is likely a copy-paste bug.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindClassWithEqualsButNoIEquatable
- Find class with Equals(T) but no IEquatable<T>
- Detect classes that define
Equals(T)but do not implementIEquatable<T>. Implementing the interface ensures consistency and enables value-based equality.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindCompareToWithoutIComparable
- Find CompareTo without IComparable
- Detect classes that provide a
CompareTomethod but do not implementIComparable<T>.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDangerousThreadingMethods
- Do not use dangerous threading methods
- Avoid
Thread.Abort(),Thread.Suspend(), andThread.Resume(). These methods are unreliable and can corrupt state.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDefaultParameterValueNeedsOptional
- Find [DefaultParameterValue] without [Optional]
- Detect parameters with
[DefaultParameterValue]that are missing[Optional]. Both attributes are needed for COM interop default parameter behavior.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotCallVirtualMethodInConstructor
- Find virtual method call in constructor
- Detect calls to virtual or abstract methods within constructors. Derived classes may not be fully initialized when these methods execute.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotCompareWithNaN
- Find comparison with NaN
- Detect comparisons with
NaNusing==or!=. Usedouble.IsNaN()orfloat.IsNaN()instead, asx == NaNis always false.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotCreateTypeWithBCLName
- Find type with BCL name
- Detect class declarations that use names from well-known BCL types like
Task,Action,String, which can cause confusion.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotDeclareStaticMembersOnGenericTypes
- Find static members on generic types
- Detect static members declared on generic types. Static members on generic types require specifying type arguments at the call site, reducing discoverability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotOverwriteParameterValue
- Find overwritten parameter values
- Detect assignments to method parameters, which can mask the original argument and lead to confusion.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotPassNullForCancellationToken
- Find null passed for CancellationToken
- Detect
nullordefaultpassed forCancellationTokenparameters. UseCancellationToken.Noneinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotRaiseApplicationException
- Do not raise ApplicationException
- Avoid throwing
ApplicationException. Use a more specific exception type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotRaiseNotImplementedException
- Do not throw NotImplementedException
- Throwing
NotImplementedExceptionindicates incomplete implementation. Implement the functionality or throw a more specific exception.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotRaiseReservedExceptionType
- Do not raise reserved exception types
- Avoid throwing
Exception,SystemException, orApplicationException. Use more specific exception types.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotThrowFromFinalizer
- Find throw statements in finalizer
- Detect
throwstatements inside finalizer/destructor methods. Throwing from a finalizer can terminate the process.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotThrowFromFinallyBlock
- Do not throw from finally block
- Throwing from a
finallyblock can mask the original exception and make debugging difficult.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseCertificateValidationCallback
- Do not write custom certificate validation
- Custom certificate validation callbacks can introduce security vulnerabilities by accidentally accepting invalid certificates.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseEqualityComparerDefaultOfString
- Find EqualityComparer<string>.Default
- Detect
EqualityComparer<string>.Defaultwhich may use different comparison semantics across platforms. Use an explicitStringComparer.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseGetHashCodeForString
- Find GetType() on Type instance
- Detect
.GetType()called on an object that is already aSystem.Type. Usetypeof()directly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseObjectToString
- Find ToString on object-typed parameter
- Detect
.ToString()calls onobject-typed parameters. The defaultobject.ToString()returns the type name, which is rarely the intended behavior.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseSleep
- Find Thread.Sleep usage
- Detect
Thread.Sleep()which blocks the thread. Useawait Task.Delay()in async contexts instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindDoNotUseStringGetHashCode
- Find string.GetHashCode() usage
- Detect
string.GetHashCode()which is not stable across runs. UseStringComparer.GetHashCode()orstring.GetHashCode(StringComparison)instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindEmbedCaughtExceptionAsInner
- Embed caught exception as inner exception
- When rethrowing a different exception in a catch block, pass the original exception as the inner exception to preserve the stack trace.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindEnumDefaultValueZero
- Find explicit zero initialization in enum
- Detect enum members explicitly initialized to
0. The default value of an enum is already0.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindEqualsWithoutNotNullWhen
- Find Equals without [NotNullWhen(true)]
- Detect
Equals(object?)overrides that are missing[NotNullWhen(true)]on the parameter, which helps nullable analysis.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindEventArgsSenderNotNull
- Find event raised with null EventArgs
- Detect event invocations that pass
nullfor EventArgs. UseEventArgs.Emptyinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindFlowCancellationTokenInAwaitForEach
- Find await foreach without CancellationToken
- Detect
await foreachloops that don't pass aCancellationTokenviaWithCancellation()when one is available in the enclosing method.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindIComparableWithoutComparisonOperators
- Find IComparable without comparison operators
- Detect classes that implement
IComparable<T>but do not override comparison operators (<,>,<=,>=).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindIComparableWithoutIEquatable
- Find IComparable<T> without IEquatable<T>
- Detect classes that implement
IComparable<T>but notIEquatable<T>. Both interfaces should be implemented together for consistent comparison semantics.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindIEquatableWithoutEquals
- Find IEquatable<T> without Equals(object) override
- Detect classes that implement
IEquatable<T>but do not overrideEquals(object), which can lead to inconsistent equality behavior.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindILoggerTypeMismatch
- Find ILogger<T> type parameter mismatch
- Detect
ILogger<T>fields or parameters whereTdoesn't match the containing type name.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindIfElseBranchesIdentical
- Find if/else with identical branches
- Detect
if/elsestatements where both branches contain identical code. This is likely a copy-paste bug.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindImplementNonGenericInterface
- Find missing non-generic interface implementation
- Detect types implementing
IComparable<T>withoutIComparable, orIEquatable<T>without proper Equals override.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindImplicitCultureSensitiveToStringDirect
- Find implicit culture-sensitive ToString in concatenation
- Detect string concatenation with numeric types that implicitly call culture-sensitive
ToString(). Use an explicit format orCultureInfo.InvariantCulture.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindImplicitDateTimeOffsetConversion
- Find implicit DateTime to DateTimeOffset conversion
- Detect implicit conversion from
DateTimetoDateTimeOffsetwhich uses the local time zone and can produce unexpected results.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindInterpolatedStringWithoutParameters
- Find interpolated string without parameters
- Detect interpolated strings (
$"...") that contain no interpolation expressions. Use a regular string literal instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindInvalidAttributeArgumentType
- Find potentially invalid attribute argument type
- Detect attribute arguments that use types not valid in attribute constructors (only primitives, string, Type, enums, and arrays of these are allowed).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMethodReturningIAsyncEnumerable
- Find IAsyncEnumerable method without Async suffix
- Detect methods returning
IAsyncEnumerable<T>that don't end withAsync.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMethodTooLong
- Find method that is too long
- Detect methods with more than 60 statements. Long methods are harder to understand and maintain.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMissingCancellationTokenOverload
- Find async call missing CancellationToken
- Detect async method calls that don't pass a
CancellationTokenwhen the enclosing method has one available as a parameter.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMissingNamedParameter
- Find boolean literal arguments without parameter name
- Detect method calls passing
trueorfalseliterals as arguments. Using named parameters improves readability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMissingParamsInOverride
- Find override method missing params keyword
- Detect override methods that may be missing the
paramskeyword on array parameters that the base method declares asparams.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMissingStringComparison
- Find string method missing StringComparison
- Detect string methods like
Equals,Contains,StartsWith,EndsWithcalled without an explicitStringComparisonparameter.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMissingStringEqualityComparer
- Find missing string equality comparer
- Detect
Dictionary<string, T>andHashSet<string>created without an explicitStringComparer. Without a comparer, the default ordinal comparison is used.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindMultiLineXmlComment
- Find multi-line XML doc comments
- Detect
/** */style XML documentation comments that could use the///single-line syntax for consistency.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindNonConstantStaticFieldsVisible
- Non-constant static fields should not be visible
- Public static fields that are not
constorreadonlycan be modified by any code, breaking encapsulation. Make themreadonlyor use a property.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindNonDeterministicEndOfLine
- Find non-deterministic end-of-line in strings
- Detect string literals containing
\nthat may behave differently across platforms. Consider usingEnvironment.NewLineinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindNonFlagsEnumWithFlagsAttribute
- Find non-flags enum with [Flags]
- Detect enums marked with
[Flags]whose values are not powers of two, indicating they are not truly flags enums.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindNotNullIfNotNullAttribute
- Find missing NotNullIfNotNull attribute
- Detect methods with nullable return types depending on nullable parameters that lack
[NotNullIfNotNull]attribute.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindObserveAsyncResult
- Find unobserved async call result
- Detect calls to async methods where the returned Task is not awaited, assigned, or otherwise observed. Unobserved tasks may silently swallow exceptions.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindObsoleteWithoutMessage
- Obsolete attribute should include explanation
- The
[Obsolete]attribute should include a message explaining why the member is obsolete and what to use instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindOverrideChangesParameterDefaults
- Find overrides that change parameter defaults
- Detect
overridemethods with default parameter values. Overrides should not change defaults from the base method as this causes confusing behavior depending on the reference type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindPreferCollectionAbstraction
- Find concrete collection in public API
- Detect public method parameters or return types that use concrete collection types like
List<T>instead ofIList<T>orIEnumerable<T>.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindPrimaryConstructorReadonly
- Find reassigned primary constructor parameter
- Detect primary constructor parameters that are reassigned in the class body. Primary constructor parameters should be treated as readonly.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindRawStringImplicitEndOfLine
- Find raw string with implicit end of line
- Detect raw string literals (
"""...""") that contain implicit end-of-line characters which may behave differently across platforms.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindReadOnlyStructMembers
- Find struct member that could be readonly
- Detect struct methods and properties that don't modify state and could be marked
readonlyto prevent defensive copies.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindRedundantArgumentValue
- Find redundant default argument values
- Detect named arguments that explicitly pass a default value. Removing them simplifies the call.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindSenderNullForStaticEvents
- Find static event with non-null sender
- Detect static event invocations that pass
thisas the sender. Static events should usenullas the sender.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindSingleLineXmlComment
- Find multi-line XML doc comment style
- Detect
/** ... */style XML doc comments. Use///single-line style instead for consistency.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindSpanEqualityOperator
- Find equality operator on Span<T>
- Detect
==or!=operators onSpan<T>orReadOnlySpan<T>. UseSequenceEqualinstead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindStreamReadIgnored
- Find Stream.Read() return value ignored
- Detect
Stream.Read()calls where the return value (bytes read) is not used. This can lead to incomplete reads.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindStringFormatConstant
- Find non-constant string.Format format string
- Detect non-constant format strings passed to
string.Format. Use a constant to prevent format string injection.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindTaskInUsing
- Find unawaited task in using statement
- Detect
usingstatements where a Task is not awaited, which can cause premature disposal before the task completes.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindThreadStaticOnInstanceField
- Do not use ThreadStatic on instance fields
[ThreadStatic]only works on static fields. Using it on instance fields has no effect.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindThrowIfNullWithNonNullable
- Find ThrowIfNull with value type argument
- Detect
ArgumentNullException.ThrowIfNullcalled with value type parameters that can never be null.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindTypeNameMatchesNamespace
- Find type name matching namespace
- Detect type names that match their containing namespace, which can cause ambiguous references.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindTypeShouldNotExtendApplicationException
- Types should not extend ApplicationException
- Do not create custom exceptions that inherit from
ApplicationException. Inherit fromExceptionor a more specific exception type.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseCallerArgumentExpression
- Find redundant nameof with CallerArgumentExpression
- Detect
nameof(param)passed to parameters marked with[CallerArgumentExpression]. The attribute fills the value automatically.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseDateTimeOffsetInsteadOfDateTime
- Find DateTime.Now/UtcNow usage
- Detect
DateTime.NowandDateTime.UtcNowusage. UseDateTimeOffsetinstead for unambiguous time representation across time zones.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseDebuggerDisplayAttribute
- Find ToString override without DebuggerDisplay
- Detect classes that override
ToString()but lack[DebuggerDisplay]attribute for debugger integration.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseDefaultParameterValue
- Find [DefaultValue] on parameter
- Detect
[DefaultValue]on method parameters. Use[DefaultParameterValue]instead, as[DefaultValue]is for component model metadata only.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseElementAccessInsteadOfLinq
- Find ElementAt() that could use indexer
- Detect LINQ
.ElementAt(index)calls that could be replaced with direct indexer access[index].
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseEqualsMethodInsteadOfOperator
- Find == comparison that should use Equals()
- Detect
==comparisons on reference types that overrideEquals. Using==may compare references instead of values.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseExplicitEnumValue
- Find integer 0 used instead of named enum value
- Detect usage of integer literal
0where a named enum member should be used for clarity.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseFormatProviderInToString
- Find Parse/ToString without IFormatProvider
- Detect calls to culture-sensitive methods like
int.Parse,double.Parsewithout an explicitIFormatProviderorCultureInfo.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseIFormatProvider
- Find Parse/TryParse without IFormatProvider
- Detect
int.Parse(str)and similar calls without anIFormatProviderparameter. UseCultureInfo.InvariantCulturefor culture-independent parsing.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseLangwordInXmlComment
- Find missing langword in XML comment
- Detect XML doc comments that reference
null,true,falseas plain text instead of using<see langword="..."/>.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseLazyInitializerEnsureInitialize
- Find Interlocked.CompareExchange lazy init pattern
- Detect
Interlocked.CompareExchange(ref field, new T(), null)pattern. UseLazyInitializer.EnsureInitializedfor cleaner lazy initialization.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseListPatternMatching
- Find collection emptiness check
- Detect
.Length == 0or.Count == 0checks that could use list patterns likeis []in C# 11+.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseNamedParameter
- Find boolean literal argument without name
- Detect boolean literal arguments (
true/false) passed without named parameters. Named arguments improve readability.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseOperatingSystemMethods
- Use OperatingSystem methods instead of RuntimeInformation
- Use
OperatingSystem.IsWindows()and similar methods instead ofRuntimeInformation.IsOSPlatform(). The OperatingSystem methods are more concise and can be optimized by the JIT.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseProcessStartWithStartInfo
- Find Process.Start with string argument
- Detect
Process.Start("filename")which should use theProcessStartInfooverload for explicit control overUseShellExecuteand other settings.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseRecordClassExplicitly
- Find implicit record class declaration
- Detect
recorddeclarations that should userecord classexplicitly to clarify that they are reference types.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseRegexOptions
- Find Regex without ExplicitCapture option
- Detect
new Regex()orRegex.IsMatch()withoutRegexOptions.ExplicitCapture. Using this option avoids unnecessary unnamed captures.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseShellExecuteFalseWhenRedirecting
- Find redirect without UseShellExecute=false
- Detect
ProcessStartInfothat setsRedirectStandard*without explicitly settingUseShellExecute = false.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseShellExecuteNotSet
- Find ProcessStartInfo without UseShellExecute
- Detect
new ProcessStartInfo()without explicitly settingUseShellExecute. The default changed between .NET Framework (true) and .NET Core (false).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseStringComparer
- Find Dictionary/HashSet without StringComparer
- Detect
Dictionary<string, T>orHashSet<string>created without an explicitStringComparer. UseStringComparer.OrdinalorStringComparer.OrdinalIgnoreCase.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseStringCreateInsteadOfConcat
- Find FormattableString usage
- Detect
FormattableStringusage. Consider usingString.Createon .NET 6+ for better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseStringEqualsInsteadOfIsPattern
- Find 'is' pattern with string literal
- Detect
x is "literal"patterns that should usestring.Equalswith explicitStringComparisonfor culture-aware or case-insensitive comparisons.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseSystemThreadingLock
- Use System.Threading.Lock instead of object for locking
- In .NET 9+, use
System.Threading.Lockinstead ofobjectfor lock objects. The dedicated Lock type provides better performance.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseTaskUnwrap
- Find double await pattern
- Detect
await awaitpattern which can be replaced with.Unwrap()for clarity.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindUseTimeProviderInsteadOfCustom
- Find custom time abstraction
- Detect interfaces or abstract classes that appear to be custom time providers. Use
System.TimeProvider(available in .NET 8+) instead.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.FindValidateArgumentsBeforeYield
- Find argument validation in iterator method
- Detect iterator methods that validate arguments after
yield return. Argument validation in iterators is deferred until enumeration begins.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ImplementExceptionConstructors
- Implement exception constructors
- Ensure custom exception classes implement standard constructors.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ImplementNonGenericCounterpart
- Implement non-generic counterpart
- Implement non-generic interface when implementing generic counterpart.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.InvalidArgumentNullCheck
- Fix invalid argument null check
- Fix invalid argument null check patterns.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MakeClassSealed
- Make class sealed
- A class that has only private constructors should be marked as sealed.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MakeClassStatic
- Make class static
- Make classes that contain only static members static.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MakeFieldReadOnly
- Make field read-only
- Make field read-only when it is only assigned in the constructor or initializer.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MakeMethodExtensionMethod
- Make method an extension method
- Convert a static method to an extension method where appropriate.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MarkLocalVariableAsConst
- Mark local variable as const
- Mark local variable as const when its value never changes.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MarkTypeWithDebuggerDisplay
- Mark type with DebuggerDisplay attribute
- Add DebuggerDisplay attribute to publicly visible types to improve debugging experience.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.MergePreprocessorDirectives
- Merge preprocessor directives
- Merge consecutive preprocessor directives that can be combined into a single directive.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.NormalizeEnumFlagValue
- Normalize format of enum flag value
- Normalize the format of Flags enum values.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.OrderModifiers
- Order modifiers
- Reorder modifiers to the canonical C# order: access, new, abstract/virtual/override/sealed, static, readonly, extern, unsafe, volatile, async, partial, const.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.OrderNamedArguments
- Order named arguments by parameters
- Reorder named arguments to match parameter order.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.OrderTypeParameterConstraints
- Order type parameter constraints
- Order type parameter constraints consistently.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.OverridingMemberShouldNotChangeParams
- Overriding member should not change 'params' modifier
- An overriding member should not add or remove the 'params' modifier compared to its base declaration.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ParameterNameDiffersFromBase
- Parameter name differs from base
- Rename parameter to match base class or interface definition.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ParenthesizeNotPattern
- Parenthesize not pattern for clarity
- Add parentheses to
not A or B→(not A) or Bto clarify thatnotbinds tighter thanor.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.PreferNullCheckOverTypeCheck
- Prefer null check over type check
- Replace
x is objectwithx is not nullfor clarity.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.SimplifyBooleanLogic
- Simplify boolean logic with constants
- Simplify
x || truetotrue,x && falsetofalse,x || falsetox, andx && truetox.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.SortEnumMembers
- Sort enum members
- Sort enum members by their resolved constant value.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.SplitVariableDeclaration
- Split variable declaration
- Split multi-variable declarations into separate declarations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.StaticMemberInGenericType
- Static member in generic type should use a type parameter
- Find static members in generic types that do not use any of the type's type parameters.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.StyleCodeQuality
- Style code quality
- Code style modernization recipes for C#.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UnusedParameter
- Remove unused parameter
- Rename unused lambda parameters to discard (_).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UnusedTypeParameter
- Remove unused type parameter
- Flag type parameters that are not used.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseAsyncAwait
- Use async/await when necessary
- Add async/await to methods that return Task but don't use await.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseAttributeUsageAttribute
- Use AttributeUsageAttribute
- Add AttributeUsage to custom attribute classes.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseAutoProperty
- Use auto property
- Use auto property instead of property with backing field.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseBlockBodyOrExpressionBody
- Use block body or expression body
- Convert between block body and expression body for members.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseCoalesceExpressionFromNullCheck
- Use coalesce expression
- Convert null-check conditional to null-coalescing expression.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseCollectionExpression
- Use collection expression
- Replace array/list creation with collection expressions (C# 12).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseConstantInsteadOfField
- Use constant instead of field
- Convert
static readonlyfields with literal initializers toconst.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseElementAccess
- Use element access
- Use indexer instead of First()/Last()/ElementAt() when the collection supports indexer access.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseEnumFieldExplicitly
- Use enum field explicitly
- Use named enum field instead of cast integer value.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseEventArgsEmpty
- Use EventArgs.Empty
- Replace
new EventArgs()withEventArgs.Empty. The staticEventArgs.Emptyfield avoids unnecessary allocations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseEventArgsEmptyForNull
- Use EventArgs.Empty instead of null
- Replace
nullwithEventArgs.Emptywhen raising events. Passingnullfor EventArgs can cause NullReferenceException in event handlers.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseEventHandlerT
- Use EventHandler<T>
- Use generic EventHandler<T> instead of custom delegate types.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseExplicitTypeInsteadOfVar
- Use explicit type instead of var
- Use explicit type instead of
varwhen the type is not evident.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseExplicitlyTypedArray
- Use explicitly typed array
- Use explicitly or implicitly typed array.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseFileScopedNamespace
- Use file-scoped namespace
- Detect block-scoped namespace declarations that could use file-scoped syntax (C# 10).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseMethodChaining
- Use method chaining
- Chain consecutive method calls on the same receiver into a fluent chain.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseMethodGroupConversion
- Use method group conversion
- Replace
x => Foo(x)withFoowhere method group conversion applies.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UsePredefinedType
- Use predefined type
- Use predefined type keyword (e.g., int instead of Int32).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UsePrimaryConstructor
- Use primary constructor
- Convert classes with a single constructor into primary constructor syntax (C# 12).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseReadOnlyAutoProperty
- Use read-only auto property
- Use read-only auto property when the setter is never used.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseStringContains
- Use string.Contains instead of IndexOf comparison
- Replace
s.IndexOf(x) >= 0withs.Contains(x)ands.IndexOf(x) == -1with!s.Contains(x).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseStringIsNullOrEmpty
- Use string.IsNullOrEmpty method
- Replace
s == null || s == ""ands == null || s.Length == 0withstring.IsNullOrEmpty(s).
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseStringLengthComparison
- Use string.Length instead of comparison with empty string
- Replace
s == ""withs.Length == 0ands != ""withs.Length != 0.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseThisForEventSender
- Use 'this' for event sender
- Replace
nullwiththisas the sender argument when raising instance events. The sender should be the object raising the event.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseUsingDeclaration
- Use using declaration
- Convert using statement to using declaration.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseVarInForEach
- Use var instead of explicit type in foreach
- Replace explicit type in foreach with var when type is evident.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.UseVarOrExplicitType
- Use 'var' or explicit type
- Enforce consistent use of 'var' or explicit type in local variable declarations.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ValidateArgumentsCorrectly
- Validate arguments correctly
- Ensure argument validation in iterator methods runs immediately by flagging iterator methods that contain argument validation.
- OpenRewrite.Recipes.CSharp.CodeQuality.Style.ValueTypeIsNeverEqualToNull
- Value type is never equal to null
- Replace null with default in comparisons of value types.
recipes-kotlin
License: Moderne Proprietary License
1011 recipes
- 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
License: Moderne Proprietary License
96 recipes
- 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.UpgradeSbtVersion
- Upgrade sbt version
- Update the
sbt.versionproperty inproject/build.propertiesto the specified version. Only modifies files at**/project/build.properties.
- 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
License: Moderne Proprietary License
3 recipes
- 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
License: Moderne Proprietary License
123 recipes
- 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
License: Moderne Proprietary License
17 recipes
- 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-cve-2026-22732
License: Moderne Proprietary License
3 recipes
- io.moderne.recipe.cve202622732.FindHttpResponseContentLengthHeader
- Find
Content-Lengthheader writes onHttpServletResponse(CVE-2026-22732) - Detects
HttpServletResponse.setHeader,setIntHeader, oraddIntHeadercalls whose first argument resolves (directly or via local variable) to the literalContent-Length(case-insensitive). These three overloads are NOT overridden by Spring Security'sOnCommittedResponseWrapper, soonResponseCommitted()never fires and the lazy-added security headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, etc.) are silently dropped — CVE-2026-22732.addHeaderis intentionally excluded: the wrapper special-cases it. Also covers WebFluxHttpHeaders.set/addforContent-Length. In addition to marking Java sinks, attaches a {@code SearchResult} marker to every source file in the affected project so this recipe can be used as a declarative precondition for build-level recipes.
- Find
- io.moderne.recipe.cve202622732.FindHttpResponseContentLengthOrFlushBuffer
- Find unconditional WebFlux response commit calls (CVE-2026-22732)
- Detects WebFlux calls that commit a
ServerHttpResponseoutside the lazy header-writing path:writeWith(..),writeAndFlushWith(..),setComplete(), andHttpHeaders.setContentLength(long). Under CVE-2026-22732 these patterns cause Spring Security's lazy-added security headers to be dropped. The sibling recipeFindHttpResponseContentLengthHeadercovers the servletsetHeader/setIntHeader/addIntHeadercase. In addition to marking Java sinks, attaches a {@code SearchResult} marker to every source file in the affected project so this recipe can be used as a declarative precondition for build-level recipes.
- io.moderne.recipe.cve202622732.FindSpringSecurityHeaderSuppression
- Find CVE-2026-22732 (Spring Security header suppression)
- Detects code susceptible to CVE-2026-22732, where setting
Content-LengthviaHttpServletResponse.setHeader/setIntHeader/addIntHeader(or the WebFlux equivalents) bypasses Spring Security'sOnCommittedResponseWrapper, letting the container commit the response before the lazy header-writing filter runs and silently dropping security headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, etc.). Also emits one data-table row per project recording the resolved Spring Security version.
rewrite-devcenter
License: Moderne Source Available License
36 recipes
- 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
License: Moderne Proprietary License
26 recipes
- 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.bundle.MigrateMultiPartBundle
- Migrate Dropwizard
MultiPartBundleto Spring multipart configuration - Removes
bootstrap.addBundle(new MultiPartBundle())and its import, and addsspring.servlet.multipartconfiguration (enabled, unlimited sizes) to the module's Spring configuration, creatingapplication.ymlif none exists. Spring Boot enables multipart support automatically. Only modules that actually registeredMultiPartBundleare configured.
- Migrate Dropwizard
- 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
License: Moderne Proprietary License
11 recipes
- 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
License: Moderne Proprietary License
38 recipes
- 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
License: Moderne Proprietary License
6 recipes
- 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
License: Moderne Proprietary License
17 recipes
- 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
License: Moderne Proprietary License
32 recipes
- 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
License: Moderne Proprietary License
110 recipes
- 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, unittest.TestCase subclasses, and behave/pytest-bdd/lettuce BDD step definitions, 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
License: Moderne Proprietary License
25 recipes
- 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.FixXssVulnerabilityJava
- Fix XSS vulnerabilities in Java sources
- Wraps tainted arguments flowing into HTML output sinks with an HTML-escape helper. Reuses
FindXssVulnerability's taint spec so the fix's source/sink/sanitizer coverage stays in sync with the detector. The escape helper is picked perJavaProjectbased on which dependency is declared (direct or transitive) in the project's Maven or Gradle build, preferring SpringHtmlUtils(org.springframework:spring-web), then OWASPEncode(org.owasp.encoder:encoder), then Commons Text (org.apache.commons:commons-text), then deprecated Commons Lang3 (org.apache.commons:commons-lang3). Projects with no recognised helper dependency are skipped; arguments already wrapped in a recognised sanitizer are also skipped. For detection without remediation, useFindXssVulnerabilitydirectly.
- 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
License: Moderne Proprietary License
51 recipes
- 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
License: Moderne Proprietary License
6 recipes
- 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
License: Moderne Proprietary License
181 recipes
- 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.batch.AddJobRegistryToTaskExecutorJobOperator
- Add
setJobRegistry(..)to manually configuredTaskExecutorJobOperator - Spring Batch 6 replaced
TaskExecutorJobLauncherwithTaskExecutorJobOperator, which requires bothsetJobRepository(..)andsetJobRegistry(..)to be called beforeafterPropertiesSet(). When aTaskExecutorJobOperatoris constructed and initialized manually (typically in a@Beanfactory method) without asetJobRegistry(..)call, add aJobRegistryparameter to the enclosing method and callsetJobRegistry(..)so the operator is fully configured.
- Add
- 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_0
- Migrate to Spring Boot 3.0 (Moderne Edition)
- Migrate applications to the latest Spring Boot 3.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 that are required as part of the migration to Spring Boot 3.0, including the Tomcat 10.1 upgrade which removes
LegacyCookieProcessor.
- 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.MigrateAwspringSqsMessageConverter
- Migrate awspring SQS default converter
setObjectMapperto constructor injection - In spring-cloud-aws 4.0
AbstractMessagingMessageConverter.setObjectMapper(...)was removed and theJsonMapperis supplied through theSqsMessagingMessageConverterconstructor. RewritesSqsTemplate.builder().configureDefaultConverter(c -> c.setObjectMapper(mapper))toSqsTemplate.builder().messageConverter(new SqsMessagingMessageConverter(mapper)), or adds a TODO comment when the configurer does more than set the object mapper.
- Migrate awspring SQS default converter
- 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.UpgradeAwspringCloud_4_0
- Migrate Spring Cloud AWS (awspring) to 4.0
- Upgrade
io.awspring.clouddependencies to 4.0.x and migrate code for the breaking API changes in Spring Cloud AWS 4.0. Spring Cloud AWS 4.0 aligns with Spring Boot 4 / Spring Framework 7 and adopts Jackson 3 by default; this recipe moves usages off the deprecated Jackson 2 variants to their Jackson 3 replacements and migrates the SQS default-convertersetObjectMapperconfigurer. Run after the Jackson 2 to 3 migration so user mappers are alreadytools.jacksonJsonMappers.
- 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.MigrateChannelInterceptorAdapter
- Replace
ChannelInterceptorAdapterwithChannelInterceptor - As of 5.0
ChannelInterceptorhas default methods (made possible by a Java 8 baseline) and can be implemented directly without the need for this adapter.
- Replace
- 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_4_0
- Migrate to Spring Framework 4.0
- Migrate applications to the latest Spring Framework 4.0 release. This composite focuses on dependency upgrades and the mechanical package moves that accompanied the 3.x to 4.0 transition. Removed APIs that do not have a 1:1 replacement (for example
JpaTemplate, theAbstractCommandControllerfamily, Hibernate 3 support classes) still require code changes that this recipe does not perform.
- io.moderne.java.spring.framework.UpgradeSpringFramework_5_0
- Migrate to Spring Framework 5.0 (Moderne Edition)
- Migrate applications to Spring Framework 5.0, layering proprietary Moderne recipes on top of the OSS
org.openrewrite.java.spring.framework.UpgradeSpringFramework_5_0. Chains throughUpgradeSpringFramework_4_0(and transitively_3_0) so a customer on Spring 3.x lands on a 5.0 baseline after one composite run.
- 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.UpgradeSpringFramework_6_0
- Migrate to Spring Framework 6.0 (Moderne Edition)
- Migrate applications to the latest Spring Framework 6.0 release. Chains through
UpgradeSpringFramework_5_3(and transitively_5_0/_4_0/_3_0) and layers Spring Integration XML attribute migrations on top of the OSS Spring Framework 6.0 upgrade. The OSS recipe handles theorg.springframework:*version bump and Jakarta EE 10 package moves; this composite additionally bumpsorg.springframework.security:*to 6.0.x (Spring Security tracks Spring's major) and cleans up Spring Integration XML configurations.
- 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.MigrateAbstractClientHttpResponse
- Migrate
AbstractClientHttpResponsetoClientHttpResponse - Spring Framework 6.0 removed
org.springframework.http.client.AbstractClientHttpResponse. This recipe rewritesextends AbstractClientHttpResponsetoimplements ClientHttpResponse, flags anysuper.*()calls inside the converted class with a TODO comment (those calls no longer compile), and renames remaining type references (variables, parameters, fields, casts, generics, return types) to theClientHttpResponseinterface.
- Migrate
- 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.integration.MigrateSpringFramework6DeprecatedIntegrationXmlAttributes
- Migrate Spring Integration XML attributes deprecated by Spring Integration 6.x
- Renames or removes Spring Integration XML attributes that were deprecated or removed between Spring Integration 5.x and 6.x. Scoped to XML files using the Spring Integration namespace.
- 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.kotlin.ReplaceKotlinPropertyAssignmentWithSetterCall
- Replace Kotlin property assignment with setter call
- Rewrites a Kotlin property-style assignment (
obj.prop = value) to an explicit setter invocation (obj.setProp(value)). Use when a Java library adopts JSpecify@NullMarkedand a previously-varsynthetic property is demoted toval: Kotlin requires the getter's return type and the setter's parameter type to share the same nullability, and once they diverge the assignment stops compiling.
- 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.MigrateDaoAuthenticationProviderConstructor
- Use constructor injection for
DaoAuthenticationProvider - Spring Security 7.0 removed the no-arg
DaoAuthenticationProvider()constructor and thesetUserDetailsService(UserDetailsService)setter;UserDetailsServiceis now a required constructor argument. This recipe foldssetUserDetailsService(x)into the constructor (new DaoAuthenticationProvider(x)) and removes the setter when the provider is created with the no-arg constructor in the same block, for both Java and Kotlin sources.setPasswordEncoder(...)and other configuration are preserved. When the setter cannot be safely folded, a TODO comment with migration guidance is added instead.
- Use constructor injection for
- 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
License: Moderne Proprietary License
11 recipes
- 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
License: Moderne Proprietary License
1 recipe
- 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.