Sample

int-b5d74d8f1670-I13

Lower every eligible classic and enhanced for loop to a while loop

Matched original source

Lines112

Scores

MethodScoreScale
Posnett00–1; higher is more readable
Scalabrino0.5040–1; higher is more readable
Dorn0.3030–1; higher is more readable
Mi0.4670–1; higher is more readable
LLOC41Logical lines; fewer is more readable
DeepSeek V4 Pro15.330–20; mean of three runs
GPT-6.1 Sol160–20; mean of three runs
BTTF0.4910–1; higher is more readable

Views

Source code

package org.springframework.cache.jcache.interceptor; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import javax.cache.annotation.CacheInvocationParameter; import javax.cache.annotation.CacheKeyGenerator; import javax.cache.annotation.CacheKeyInvocationContext; import org.jspecify.annotations.Nullable; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** * Spring's {@link KeyGenerator} implementation that either delegates to a standard JSR-107 * {@link javax.cache.annotation.CacheKeyGenerator}, or wrap a standard {@link KeyGenerator} * so that only relevant parameters are handled. * * @author Stephane Nicoll * @author Juergen Hoeller * @since 4.1 */ class KeyGeneratorAdapter implements KeyGenerator { private final JCacheOperationSource cacheOperationSource; private @Nullable KeyGenerator keyGenerator; private @Nullable CacheKeyGenerator cacheKeyGenerator; /** * Create an instance with the given {@link KeyGenerator} so that {@link javax.cache.annotation.CacheKey} * and {@link javax.cache.annotation.CacheValue} are handled according to the spec. */ public KeyGeneratorAdapter(JCacheOperationSource cacheOperationSource, KeyGenerator target) { Assert.notNull(cacheOperationSource, "JCacheOperationSource must not be null"); Assert.notNull(target, "KeyGenerator must not be null"); this.cacheOperationSource = cacheOperationSource; this.keyGenerator = target; } /** * Create an instance used to wrap the specified {@link javax.cache.annotation.CacheKeyGenerator}. */ public KeyGeneratorAdapter(JCacheOperationSource cacheOperationSource, CacheKeyGenerator target) { Assert.notNull(cacheOperationSource, "JCacheOperationSource must not be null"); Assert.notNull(target, "CacheKeyGenerator must not be null"); this.cacheOperationSource = cacheOperationSource; this.cacheKeyGenerator = target; } /** * Return the target key generator to use in the form of either a {@link KeyGenerator} * or a {@link CacheKeyGenerator}. */ public Object getTarget() { if (this.cacheKeyGenerator != null) { return this.cacheKeyGenerator; } Assert.state(this.keyGenerator != null, "No key generator"); return this.keyGenerator; } @Override public Object generate(Object target, Method method, @Nullable Object... params) { JCacheOperation<?> operation = this.cacheOperationSource.getCacheOperation(method, target.getClass()); if (!(operation instanceof AbstractJCacheKeyOperation)) { throw new IllegalStateException("Invalid operation, should be a key-based operation " + operation); } CacheKeyInvocationContext<?> invocationContext = createCacheKeyInvocationContext(target, operation, params); if (this.cacheKeyGenerator != null) { return this.cacheKeyGenerator.generateCacheKey(invocationContext); } else { Assert.state(this.keyGenerator != null, "No key generator"); return doGenerate(this.keyGenerator, invocationContext); } } private static Object doGenerate(KeyGenerator keyGenerator, CacheKeyInvocationContext<?> context) { List<Object> parameters = new ArrayList<>(); { CacheInvocationParameter[] loopArray = context.getKeyParameters(); int loopIndex = 0; while (loopIndex < loopArray.length) { CacheInvocationParameter param = loopArray[loopIndex++]; Object value = param.getValue(); if (param.getParameterPosition() == context.getAllParameters().length - 1 && context.getMethod().isVarArgs()) { parameters.addAll(CollectionUtils.arrayToList(value)); } else { parameters.add(value); } } } return keyGenerator.generate(context.getTarget(), context.getMethod(), parameters.toArray()); } @SuppressWarnings("unchecked") private CacheKeyInvocationContext<?> createCacheKeyInvocationContext( Object target, JCacheOperation<?> operation, @Nullable Object[] params) { AbstractJCacheKeyOperation<Annotation> keyCacheOperation = (AbstractJCacheKeyOperation<Annotation>) operation; return new DefaultCacheKeyInvocationContext<>(keyCacheOperation, target, params); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.3956.243−130.556
Source linesThe number of non-empty source lines.112+44.8
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.937−7.405

Intercept 8.87 + feature contributions = -84.291 (log-odds).
Score = sigmoid(-84.291) = 0.

Score0.504

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.113−2.965
Indentation frequencyHow rapidly indentation changes from line to line.96+2.583
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.96−1.782
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.111.876+1.154
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.111.929−1.076
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.110.938+0.985
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.077+0.196

Intercept 0.07 + feature contributions = -0.834 (log-odds).
Score = sigmoid(-0.834) = 0.303.

Score0.467
Score41
Run 1

The code is generally well-structured with clear class organization, imports, and documentation. It uses nullable annotations and assertions appropriately. Most methods are flat and follow a natural reading flow. However, the doGenerate method has an unnecessary block scope and a manual while-loop for array iteration, which disrupts the flow and adds complexity. The mixed use of loop styles (manual indexing vs enhanced for-loop) reduces clarity. The if-else in generate() is straightforward, but the exception message concatenation and conditional logic are slightly verbose. Overall it's readable and maintainable, but could be improved by simplifying the loop logic and removing the redundant block.

Run 2

The code is generally well-structured with clear class purpose, good constructor overloads, and meaningful method names. The main readability issue is the `doGenerate` method: it uses a manual while-loop with an explicit index and a redundant block scope, making it more verbose and harder to follow than an enhanced for-loop. The varargs handling adds complexity but is reasonably documented. Nesting is minimal, and actions are mostly one per line. The `generate` method has a clear flow but could extract the operation validation for clarity. Overall, the code is maintainable and understandable, with only minor inefficiencies in the loop logic.

Run 3

The code is generally well-structured with clear class-level documentation, logical field declarations, and two distinct constructors that are easy to follow. It uses Spring idioms like Assert.notNull consistently and separates actions across lines appropriately. The method generate() has clear branching logic. However, readability is reduced by the `doGenerate` method's loop, which uses an unusual manual while-loop instead of a for-each, adds an unnecessary block scope, and duplicates a null-check assertion that already exists in generate(). The createCacheKeyInvocationContext method includes an unchecked cast and suppression without a clear local explanation. Overall, the code is readable but could be improved with a more idiomatic loop and slightly simpler control flow.

Run 1

Code Structure: Well organized into constructors, delegation methods, parameter processing, and context creation. Nesting: Generally shallow, but doGenerate adds an unnecessary block around a while loop and conditional. Clarity of intent: Descriptive names, documentation, and assertions explain the adapter's purpose; mutually exclusive nullable generator fields and an unchecked cast add some cognitive overhead. Code length: Mostly appropriate, though duplicated constructor validation and explicit loop bookkeeping introduce avoidable verbosity. Action granularity: Most lines perform one action, but indexing and incrementing in loopArray[loopIndex++] combine operations. Reading flow: Delegation and early validation are easy to follow, while inconsistent indentation and the artificial loop scope interrupt an otherwise natural flow. An enhanced for loop would make parameter processing clearer.

Run 2

Code Structure: Well-organized adapter with distinct constructors, delegation logic, and context creation helpers. Nesting: Mostly shallow, but doGenerate adds an unnecessary scope block around a while loop and conditional. Clarity of intent: Descriptive names, documentation, and assertions clearly explain generator selection and parameter handling; nullable alternative fields and the unchecked cast require some interpretation. Code length: Generally concise, though manual array indexing is more verbose than an enhanced for loop. Action granularity: Most lines perform one action, but loopArray[loopIndex++] combines indexing and mutation. Reading flow: Methods follow a logical sequence, with early validation and clear delegation paths. Inconsistent indentation inside doGenerate, redundant else branches after returns, and the artificial loop structure slightly disrupt otherwise natural reading.

Run 3

Code Structure: The class is logically organized into constructors, delegation methods, and focused helpers. Nesting: Most methods are shallow, but doGenerate adds an unnecessary scope block around a while loop and conditional. Clarity of intent: Descriptive names, documentation, and assertions make the adapter's purpose clear; the two nullable generator fields require some mental tracking. Code length: Generally concise, although explicit array indexing and loop bookkeeping are more verbose than an enhanced for loop. Action granularity: Most lines perform one action, but loopArray[loopIndex++] combines access and index mutation. Reading flow: Delegation and early validation are easy to follow, while inconsistent indentation in doGenerate, the redundant else after a return, and repeated context queries slightly interrupt the flow.