Skip to content

SONARJAVA-6823: Implemented rule S9356 "continue" should not be used in loops - #5989

Open
romainbrenguier wants to merge 4 commits into
masterfrom
romain/new-rule-s9356-sonarjava-6823
Open

SONARJAVA-6823: Implemented rule S9356 "continue" should not be used in loops#5989
romainbrenguier wants to merge 4 commits into
masterfrom
romain/new-rule-s9356-sonarjava-6823

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

Summary

  • Implemented rule S9356 that flags every use of the continue statement inside loops (for, for-each, while, do-while), whether labeled or unlabeled
  • The rule is a CODE_SMELL with MEDIUM impact on MAINTAINABILITY — loops should use inverted conditional logic instead of continue
  • Simple IssuableSubscriptionVisitor subscribing to CONTINUE_STATEMENT

Test plan

  • Unit test ContinueInLoopCheckTest passes
  • CI passes (ruling tests may need baseline updates)
  • Verify no false positives on ruling projects

🤖 Generated with Claude Code

…in loops

Detect every use of the continue statement inside loops (for, for-each,
while, do-while), whether labeled or unlabeled. The rule flags continue
as a code smell that reduces readability — loops should use inverted
conditional logic instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6823

@@ -0,0 +1,67 @@
<p>This rule raises an issue when a statement that skips the rest of the current loop iteration and proceeds to the next iteration is used in a loop,
including both simple and labeled forms.</p>
<p>In Java, this specifically refers to the <code>continue</code> statement.</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Duplicated sentence in S9356.html rule description

The sentence stating that in Java this refers to the continue statement appears twice: line 3 ("In Java, this specifically refers to the continue statement.") and line 20 ("In Java, this refers to the continue statement."). The second occurrence is redundant and should be removed for cleaner documentation.

Was this helpful? React with 👍 / 👎

@datadog-sonarsource

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5992

Please review and merge it into your branch.

Comment on lines 27 to 32
void test() {
CheckVerifier.newVerifier()
.onFile(mainCodeSourcesPath("checks/IntegerSubtractionInComparisonCheckSample.java"))
.withCheck(new IntegerSubtractionInComparisonCheck())
.onFile(mainCodeSourcesPath("checks/ContinueInLoopCheckSample.java"))
.withCheck(new ContinueInLoopCheck())
.verifyIssues();
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also have a test withoutSemantic

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

Detected changes in 5 rule files: 0 issues removed, 421 issues added.

S9356 (java) on commons-beanutils - 0 issues removed, 13 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanUtilsBean.java (line 276)

       271 |             final PropertyDescriptor[] origDescriptors =
       272 |                 getPropertyUtils().getPropertyDescriptors(orig);
       273 |             for (final PropertyDescriptor origDescriptor : origDescriptors) {
       274 |                 final String name = origDescriptor.getName();
       275 |                 if ("class".equals(name)) {
>>>    276 |                     continue; // No point in trying to set an object's class
       277 |                 }
       278 |                 if (getPropertyUtils().isReadable(orig, name) &&
       279 |                     getPropertyUtils().isWriteable(dest, name)) {
       280 |                     try {
       281 |                         final Object value =

Added src/main/java/org/apache/commons/beanutils2/BeanUtilsBean.java (line 819)

       814 |         // Loop through the property name/value pairs to be set
       815 |         for(final Map.Entry<String, ? extends Object> entry : properties.entrySet()) {
       816 |             // Identify the property name and value(s) to be assigned
       817 |             final String name = entry.getKey();
       818 |             if (name == null) {
>>>    819 |                 continue;
       820 |             }
       821 | 
       822 |             // Perform the assignment for this property
       823 |             setProperty(bean, name, entry.getValue());
       824 | 

Added src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (line 346)

       341 |         // So we start with the given class and walk up the superclass chain.
       342 |         for (Class<?> clazz = initial; clazz != null; clazz = clazz.getSuperclass()) {
       343 |             final Method[] methods = clazz.getDeclaredMethods();
       344 |             for (final Method method : methods) {
       345 |                 if (method == null) {
>>>    346 |                     continue;
       347 |                 }
       348 |                 // skip static methods.
       349 |                 final int mods = method.getModifiers();
       350 |                 if (!Modifier.isPublic(mods) ||
       351 |                     Modifier.isStatic(mods)) {

Added src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (line 352)

       347 |                 }
       348 |                 // skip static methods.
       349 |                 final int mods = method.getModifiers();
       350 |                 if (!Modifier.isPublic(mods) ||
       351 |                     Modifier.isStatic(mods)) {
>>>    352 |                     continue;
       353 |                 }
       354 |                 if (method.getName().equals(methodName) &&
       355 |                         method.getParameterTypes().length == parameterCount) {
       356 |                     return method;
       357 |                 }

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 880)

       875 |             final Class<?>[] interfaces = clazz.getInterfaces();
       876 |             for (int i = 0; i < interfaces.length; i++) {
       877 | 
       878 |                 // Is this interface public?
       879 |                 if (!Modifier.isPublic(interfaces[i].getModifiers())) {
>>>    880 |                     continue;
       881 |                 }
       882 | 
       883 |                 // Does the method exist on this interface?
       884 |                 try {
       885 |                     method = interfaces[i].getDeclaredMethod(methodName,

Added src/test/java/org/apache/commons/beanutils2/PropertyUtilsTestCase.java (line 3998)

      3993 |                 PropertyUtils.getPropertyDescriptors(bean);
      3994 |         for (final String propertie : properties) {
      3995 | 
      3996 |             // Identify the property descriptor for this property
      3997 |             if (propertie.equals("intIndexed")) {
>>>   3998 |                 continue;
      3999 |             }
      4000 |             if (propertie.equals("stringIndexed")) {
      4001 |                 continue;
      4002 |             }
      4003 |             if (propertie.equals("writeOnlyProperty")) {

Added src/test/java/org/apache/commons/beanutils2/PropertyUtilsTestCase.java (line 4001)

      3996 |             // Identify the property descriptor for this property
      3997 |             if (propertie.equals("intIndexed")) {
      3998 |                 continue;
      3999 |             }
      4000 |             if (propertie.equals("stringIndexed")) {
>>>   4001 |                 continue;
      4002 |             }
      4003 |             if (propertie.equals("writeOnlyProperty")) {
      4004 |                 continue;
      4005 |             }
      4006 |             int n = -1;

Added src/test/java/org/apache/commons/beanutils2/PropertyUtilsTestCase.java (line 4004)

      3999 |             }
      4000 |             if (propertie.equals("stringIndexed")) {
      4001 |                 continue;
      4002 |             }
      4003 |             if (propertie.equals("writeOnlyProperty")) {
>>>   4004 |                 continue;
      4005 |             }
      4006 |             int n = -1;
      4007 |             for (int j = 0; j < pd.length; j++) {
      4008 |                 if (propertie.equals(pd[j].getName())) {
      4009 |                     n = j;
S9356 (java) on eclipse-jetty - 0 issues removed, 237 issues added - new ruling file

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 88)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 102)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 109)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java (line 196)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java (line 252)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java (line 168)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java (line 1325)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 846)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java (line 872)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java (line 894)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 841)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 888)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 923)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java (line 433)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java (line 439)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java)
S9356 (java) on eclipse-jetty-similar-to-main - 0 issues removed, 125 issues added - new ruling file

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 88)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 102)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java (line 109)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/CookieCutter.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java (line 196)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java (line 252)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/GZIPContentDecoder.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java (line 168)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java (line 1325)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 846)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java (line 872)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java (line 894)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 841)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 888)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java (line 923)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java (line 433)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java (line 439)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java)
S9356 (java) on guava - 0 issues removed, 36 issues added - new ruling file

Added src/com/google/common/base/Ascii.java (line 647)

       642 |     }
       643 |     for (int i = 0; i < length; i++) {
       644 |       char c1 = s1.charAt(i);
       645 |       char c2 = s2.charAt(i);
       646 |       if (c1 == c2) {
>>>    647 |         continue;
       648 |       }
       649 |       int alphaIndex = getAlphaIndex(c1);
       650 |       // This was also benchmarked using '&' to avoid branching (but always evaluate the rhs),
       651 |       // however this showed no obvious improvement.
       652 |       if (alphaIndex < 26 && alphaIndex == getAlphaIndex(c2)) {

Added src/com/google/common/base/Ascii.java (line 653)

       648 |       }
       649 |       int alphaIndex = getAlphaIndex(c1);
       650 |       // This was also benchmarked using '&' to avoid branching (but always evaluate the rhs),
       651 |       // however this showed no obvious improvement.
       652 |       if (alphaIndex < 26 && alphaIndex == getAlphaIndex(c2)) {
>>>    653 |         continue;
       654 |       }
       655 |       return false;
       656 |     }
       657 |     return true;
       658 |   }

Added src/com/google/common/base/Splitter.java (line 191)

       186 | 
       187 |                 positions:
       188 |                 for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
       189 |                   for (int i = 0; i < separatorLength; i++) {
       190 |                     if (toSplit.charAt(i + p) != separator.charAt(i)) {
>>>    191 |                       continue positions;
       192 |                     }
       193 |                   }
       194 |                   return p;
       195 |                 }
       196 |                 return -1;

Added src/com/google/common/base/Splitter.java (line 606)

       601 |            */
       602 |           offset++;
       603 |           if (offset >= toSplit.length()) {
       604 |             offset = -1;
       605 |           }
>>>    606 |           continue;
       607 |         }
       608 | 
       609 |         while (start < end && trimmer.matches(toSplit.charAt(start))) {
       610 |           start++;
       611 |         }

Added src/com/google/common/base/Splitter.java (line 619)

       614 |         }
       615 | 
       616 |         if (omitEmptyStrings && start == end) {
       617 |           // Don't include the (unused) separator in next split string.
       618 |           nextStart = offset;
>>>    619 |           continue;
       620 |         }
       621 | 
       622 |         if (limit == 1) {
       623 |           // The limit has been reached, return the rest of the string as the
       624 |           // final item.  This is tested after empty string removal so that

Added src/com/google/common/cache/LocalCache.java (line 2713)

      2708 | 
      2709 |     @Nullable
      2710 |     ReferenceEntry<K, V> getEntry(Object key, int hash) {
      2711 |       for (ReferenceEntry<K, V> e = getFirst(hash); e != null; e = e.getNext()) {
      2712 |         if (e.getHash() != hash) {
>>>   2713 |           continue;
      2714 |         }
      2715 | 
      2716 |         K entryKey = e.getKey();
      2717 |         if (entryKey == null) {
      2718 |           tryDrainReferenceQueues();

Added src/com/google/common/cache/LocalCache.java (line 2719)

      2714 |         }
      2715 | 
      2716 |         K entryKey = e.getKey();
      2717 |         if (entryKey == null) {
      2718 |           tryDrainReferenceQueues();
>>>   2719 |           continue;
      2720 |         }
      2721 | 
      2722 |         if (map.keyEquivalence.equivalent(key, entryKey)) {
      2723 |           return e;
      2724 |         }

Added src/com/google/common/cache/LocalCache.java (line 2819)

      2814 |           int length = table.length();
      2815 |           for (int i = 0; i < length; ++i) {
      2816 |             for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
      2817 |               V entryValue = getLiveValue(e, now);
      2818 |               if (entryValue == null) {
>>>   2819 |                 continue;
      2820 |               }
      2821 |               if (map.valueEquivalence.equivalent(value, entryValue)) {
      2822 |                 return true;
      2823 |               }
      2824 |             }

Added src/com/google/common/cache/Striped64.java (line 224)

       219 |                             } finally {
       220 |                                 busy = 0;
       221 |                             }
       222 |                             if (created)
       223 |                                 break;
>>>    224 |                             continue;           // Slot is now non-empty
       225 |                         }
       226 |                     }
       227 |                     collide = false;
       228 |                 }
       229 |                 else if (!wasUncontended)       // CAS already known to fail

Added src/com/google/common/cache/Striped64.java (line 249)

       244 |                         }
       245 |                     } finally {
       246 |                         busy = 0;
       247 |                     }
       248 |                     collide = false;
>>>    249 |                     continue;                   // Retry with expanded table
       250 |                 }
       251 |                 h ^= h << 13;                   // Rehash
       252 |                 h ^= h >>> 17;
       253 |                 h ^= h << 5;
       254 |                 hc[0] = h;                      // Record index for next time

Added src/com/google/common/collect/Collections2.java (line 644)

       639 | 
       640 |       while (true) {
       641 |         int q = c[j] + o[j];
       642 |         if (q < 0) {
       643 |           switchDirection();
>>>    644 |           continue;
       645 |         }
       646 |         if (q == j + 1) {
       647 |           if (j == 0) {
       648 |             break;
       649 |           }

Added src/com/google/common/collect/Collections2.java (line 652)

       647 |           if (j == 0) {
       648 |             break;
       649 |           }
       650 |           s++;
       651 |           switchDirection();
>>>    652 |           continue;
       653 |         }
       654 | 
       655 |         Collections.swap(list, j - c[j] + s, j - q + s);
       656 |         c[j] = q;
       657 |         break;

Added src/com/google/common/collect/ComputingConcurrentHashMap.java (line 165)

       160 |           if (value != null) {
       161 |             recordRead(e);
       162 |             return value;
       163 |           }
       164 |           // else computing thread will clearValue
>>>    165 |           continue outer;
       166 |         }
       167 |       } finally {
       168 |         postReadCleanup();
       169 |       }
       170 |     }

Added src/com/google/common/collect/MapMakerInternalMap.java (line 2406)

      2401 | 
      2402 |     ReferenceEntry<K, V> getEntry(Object key, int hash) {
      2403 |       if (count != 0) { // read-volatile
      2404 |         for (ReferenceEntry<K, V> e = getFirst(hash); e != null; e = e.getNext()) {
      2405 |           if (e.getHash() != hash) {
>>>   2406 |             continue;
      2407 |           }
      2408 | 
      2409 |           K entryKey = e.getKey();
      2410 |           if (entryKey == null) {
      2411 |             tryDrainReferenceQueues();

Added src/com/google/common/collect/MapMakerInternalMap.java (line 2412)

      2407 |           }
      2408 | 
      2409 |           K entryKey = e.getKey();
      2410 |           if (entryKey == null) {
      2411 |             tryDrainReferenceQueues();
>>>   2412 |             continue;
      2413 |           }
      2414 | 
      2415 |           if (map.keyEquivalence.equivalent(key, entryKey)) {
      2416 |             return e;
      2417 |           }
S9356 (java) on sonar-server - 0 issues removed, 10 issues added - new ruling file

Added src/main/java/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStep.java (line 208)

(source file not found at this revision: src/main/java/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStep.java)

Added src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java (line 103)

(source file not found at this revision: src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java)

Added src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java (line 112)

(source file not found at this revision: src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java)

Added src/main/java/org/sonar/server/computation/task/projectanalysis/step/QualityGateMeasuresStep.java (line 179)

(source file not found at this revision: src/main/java/org/sonar/server/computation/task/projectanalysis/step/QualityGateMeasuresStep.java)

Added src/main/java/org/sonar/server/rule/RegisterRules.java (line 117)

(source file not found at this revision: src/main/java/org/sonar/server/rule/RegisterRules.java)

Added src/main/java/org/sonar/server/rule/RegisterRules.java (line 354)

(source file not found at this revision: src/main/java/org/sonar/server/rule/RegisterRules.java)

Added src/main/java/org/sonar/server/rule/RegisterRules.java (line 363)

(source file not found at this revision: src/main/java/org/sonar/server/rule/RegisterRules.java)

Added src/main/java/org/sonar/server/user/UserUpdater.java (line 344)

(source file not found at this revision: src/main/java/org/sonar/server/user/UserUpdater.java)

Added src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepositoryTest.java (line 184)

(source file not found at this revision: src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepositoryTest.java)

Added src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImplTest.java (line 241)

(source file not found at this revision: src/test/java/org/sonar/server/computation/task/projectanalysis/measure/MeasureRepositoryImplTest.java)

@github-actions

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5994

Please review and merge it into your branch.

Prompt: Add a test withoutSemantic for the new rule

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5994

Please review and merge it into your branch.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@gitar-bot

gitar-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 0 resolved / 1 findings

Implements rule S9356 to flag 'continue' statements in loops using an issuable subscription visitor with comprehensive test coverage. Consider removing the duplicated sentence in the S9356.html rule description.

💡 Quality: Duplicated sentence in S9356.html rule description

📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9356.html:3 📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9356.html:20

The sentence stating that in Java this refers to the continue statement appears twice: line 3 ("In Java, this specifically refers to the continue statement.") and line 20 ("In Java, this refers to the continue statement."). The second occurrence is redundant and should be removed for cleaner documentation.

🤖 Prompt for agents
Code Review: Implements rule S9356 to flag 'continue' statements in loops using an issuable subscription visitor with comprehensive test coverage. Consider removing the duplicated sentence in the S9356.html rule description.

1. 💡 Quality: Duplicated sentence in S9356.html rule description
   Files: sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9356.html:3, sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9356.html:20

   The sentence stating that in Java this refers to the `continue` statement appears twice: line 3 ("In Java, this specifically refers to the `continue` statement.") and line 20 ("In Java, this refers to the `continue` statement."). The second occurrence is redundant and should be removed for cleaner documentation.

Implementation Status ✅ 1 / 1 issues implemented
SONARJAVA-6823 — 1 / 1 objectives

The PR successfully implements rule S9356 'continue should not be used in loops' along with its associated tests, metadata, documentation, and ruling results.

✅ 1 complete
  • ✅ Implement rule S9356 'continue' should not be used in loops
Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next

Copy link
Copy Markdown
Contributor

@romainbrenguier
romainbrenguier marked this pull request as ready for review August 24, 2026 11:26

@nathsou nathsou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a duplicate of S909 which is already implemented in C, JS and PLSQL.
Please reuse this rule id instead of S9356.

Apart from that, LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants