Skip to content

SONARJAVA-6945: Implemented rule S9385 - Copy constructors should initialize all fields - #6116

Draft
romainbrenguier wants to merge 1 commit into
masterfrom
romain/new-rule-s9385-sonarjava-6945
Draft

romainbrenguier wants to merge 1 commit into
masterfrom
romain/new-rule-s9385-sonarjava-6945

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

This rule detects copy constructors that leave eligible instance fields uninitialized.

A copy constructor is a constructor with a single parameter of the same type as the enclosing class. The rule reports issues for constructors that fail to explicitly initialize eligible fields (instance fields that are not static, not transient, and not initialized at declaration time).

Test cases cover:

  • Basic copy constructor omissions
  • Foreign assignments (assigning to parameter instead of this)
  • Shadowed fields
  • Compound assignments and increment/decrement operations
  • Constructor delegation chains
  • Helper method resolution
  • Deferred assignments in lambdas and inner classes
  • Qualified 'this' references
  • Type casting on 'this'

…tialize all fields

This rule detects copy constructors that leave eligible instance fields
uninitialized. A copy constructor is a constructor with a single parameter
of the same type as the enclosing class.

The rule reports one issue on the constructor's simple name, with secondary
locations on each uninitialized field declaration. Eligible fields are
instance fields that are not static, not transient, and not initialized
at declaration time.

The analysis follows assignment paths through:
- Direct field assignments
- Compound assignments and increment/decrement operations
- Constructor delegation chains
- Instance helper method calls

Deferred assignments in lambdas, local classes, and anonymous classes
are not followed.
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6945

@datadog-sonarsource

datadog-sonarsource Bot commented Sep 11, 2026

Copy link
Copy Markdown

Pipelines

⚠️ Warnings

Your PR has failed checks. Please review the issues below and take necessary action before merging.

🚦 6 Pipeline jobs failed

Build | Ruling QA (warp-custom-ubuntu-24-04, without-sonarqube-project, LATEST_RELEASE) — 🔧 Needs a code fix, caused by this PR

View in Datadog · View in GitHub Actions

Server startup failure due to missing rule with key 'java:S9365'.

Build | Plugin QA (LATEST_RELEASE, false)

View in Datadog · View in GitHub Actions

Server startup failure due to missing rule with key 'java:S9365'.

Build | Ruling QA (warp-custom-ubuntu-24-04, only-sonarqube-project, LATEST_RELEASE)

View in Datadog · View in GitHub Actions

Server startup failure due to missing rule 'java:S9365' in SonarQube configuration.

View all 6 failed jobs.

📋 Copy fix prompt
CI on my pull request is failing. Help me find and fix the root cause of each failing job below — they were flagged as caused by changes in this PR, so focus on the diff. For each job, explain the failure and propose a fix.

Before you start, set up the Datadog software-delivery tooling so you can
query the CI data yourself:

1. Check whether you already have the Datadog software-delivery MCP tools
   (e.g. a `search_datadog_ci_pipeline_events` tool) and the `unblock-pr` skill.
2. If either is missing, STOP and ask me for permission before installing
   anything. Do not install or run anything until I have said yes.
3. Only with my explicit approval, set up the Datadog software-delivery MCP
   server and skills by following:
     https://docs.datadoghq.com/getting_started/software_delivery_mcp_tools/
   then restart so the skill is picked up.
4. If I decline, skip all of the above and work from the context below alone.

Then run /unblock-pr — it will pull the CI data itself. The job context below is what we already know.

If /unblock-pr is not available — because I declined the setup above, or it did not install — work from the context below instead.

Datadog has already classified this failure as caused by changes in this PR.
Take that as given and work the fix:

1. Locate the change. Diff this branch against its base and find the change
   that produces this error. Explain the mechanism, don't just name a file:
     git fetch origin && git diff $(git merge-base origin/master HEAD)...HEAD
2. Reproduce it locally. Run the failing job's command or test before
   proposing anything.
3. Propose the smallest fix that addresses the root cause — not a workaround,
   not a broadened assertion, not a disabled or skipped test.
4. Re-run the same command to confirm, and say exactly what you ran.
5. If the failure turns out to be intermittent rather than deterministic, say
   so plainly instead of "fixing" it — that is a flaky test, and patching it
   hides the problem.

If the right move is to re-run the job rather than change code, use the job
link in the context below. For GitHub Actions: `gh run rerun <run-id> --failed`,
where the run ID is the number after `/runs/` in that URL (not the trailing
number, which is the job ID).

Branch: romain/new-rule-s9385-sonarjava-6945

Build | Ruling QA (warp-custom-ubuntu-24-04, without-sonarqube-project, LATEST_RELEASE)
Commit: f0740289845be0c3cda482843427942c8a273d56
Error (code / build):
Server startup failure due to missing rule with key 'java:S9365'.
CI job: https://github.com/SonarSource/sonar-java/actions/runs/34604163306/job/103279140369

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f074028 | Docs | View more details | Give us feedback!

@sonarqube-next

Copy link
Copy Markdown
Contributor

import org.sonar.plugins.java.api.tree.VariableTree;

@Rule(key = "S9365")
@Rule(key = "S9385")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 Bug: Rule key renamed S9365→S9385 but old rule resources kept

The base commit already shipped this check as @Rule(key = "S9365") with matching resources (S9365.html, S9365.json, profiles/Sonar_way/S9365). This commit changes the annotation to S9385 and adds S9385.html (byte-identical to S9365.html) plus S9385.json (differs from S9365.json only in sqKey) and profiles/Sonar_way/S9385, while leaving all three S9365 files in place. ProfileJsonGenerator.collectRuleKeys turns every marker file into a rule key, so the generated Sonar_way_profile.json now activates both java:S9365 and java:S9385, but no check class declares key S9365 any more — the built-in profile activates a rule that does not exist in the java repository, and the repository ends up with two identical rule descriptions. GeneratedCheckListTest only walks from check classes to metadata, so it will not catch the orphan. Either revert the key to S9365 (matching the untouched ruleSpecification: "RSPEC-9365") and drop the three new S9385 files, or complete the rename by deleting S9365.html, S9365.json and profiles/Sonar_way/S9365.

Fix 1: Keep the already-released key S9365 and delete the newly added S9385.html, S9385.json and profiles/Sonar_way/S9385 files.
@Rule(key = "S9365")
  • Apply fix
Fix 2: Alternative: finish the rename by removing the S9365 html, json and Sonar_way marker so only S9385 remains.
// keep @Rule(key = "S9385") and remove the stale resources:
//   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.html
//   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.json
//   git rm sonar-java-plugin/src/main/resources/profiles/Sonar_way/S9365
  • Apply fix

Check a box to apply a fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment on lines +13 to +14
"ruleSpecification": "RSPEC-9365",
"sqKey": "S9385",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: S9385.json points at ruleSpecification RSPEC-9365

S9385.json was copied from S9365.json with only sqKey updated, so it still declares "ruleSpecification": "RSPEC-9365" while "sqKey": "S9385". Every other rule metadata file in this directory keeps the two in sync (e.g. S6912 → RSPEC-6912), so the new rule links its documentation and traceability to a different RSPEC id. If S9385 is the intended key, update the field; if RSPEC-9365 is correct, the key change itself is the mistake.

Align ruleSpecification with the new sqKey.:

"ruleSpecification": "RSPEC-9385",
"sqKey": "S9385",
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

private boolean enabled;

Basic(Basic other) { // Noncompliant {{This copy constructor leaves eligible fields uninitialized; initialize them explicitly to distinguish omissions from intentional resets.}} [[secondary=10,11,12]]
Basic(Basic other) { // Noncompliant

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: Sample drops message and secondary-location assertions

All 17 // Noncompliant comments lose their [[secondary=...]] assertions and the primary {{...}} message assertion. CheckVerifier.verifyIssues() only compares secondaries and messages when the comment declares them, so the tests still pass but nothing now covers the secondary locations the check builds in visitNode — the very behaviour the rule description advertises ("The declarations of the omitted fields are identified as secondary locations"). The previously asserted values were correct (e.g. Basic eligible fields are lines 9-12 with name assigned, giving secondaries 10,11,12), so restoring at least the message assertion plus secondaries on a couple of representative cases keeps that behaviour under test.

Restore the message and secondary assertions on at least the representative cases (Basic, Generic, DeferredAssignments).:

Basic(Basic other) { // Noncompliant {{This copy constructor leaves eligible fields uninitialized; initialize them explicitly to distinguish omissions from intentional resets.}} [[secondary=10,11,12]]
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment on lines 136 to 137
private static AnalysisResult analyzeMethod(MethodTree method, Symbol.TypeSymbol owner, Set<Symbol> eligibleFields,
Set<Symbol.MethodSymbol> activeMethods) {

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: Documentation removed from the check's complex methods

The commit strips the javadoc from analyzeMethod and from the AssignmentCollector class, which documented the non-obvious contracts of the analysis: what activeMethods is for (recursion detection in the current call chain) and what complete means (no issue is raised unless every followed initialization path resolved). Those contracts are not derivable from the signatures and are exactly the "documentation for complex functions" the project guidelines ask for, so keeping the javadoc on these two elements is preferable to removing it along with the inline comments.

Restore the javadoc on analyzeMethod (and equivalently on AssignmentCollector).:

/**
 * Analyzes explicit field writes performed by a constructor or helper method, including writes reached through
 * resolvable calls on the current instance. Active methods form the current call chain and prevent infinite recursion.
 */
private static AnalysisResult analyzeMethod(MethodTree method, Symbol.TypeSymbol owner, Set<Symbol> eligibleFields,
  Set<Symbol.MethodSymbol> activeMethods) {
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
CI failed: Integration tests failed due to a missing rule definition for 'java:S9365', causing SonarQube startup failure, which subsequently caused artifact-dependent notification steps to fail.

Overview

1 unique failure pattern and 1 cascading notification failure found across 6 analyzed logs. The primary issue is a test failure caused by a missing rule key in SonarQube's built-in quality profiles loader during integration tests, which also prevented ruling artifacts from being generated for downstream notification jobs.

Failures

SonarQube Startup Failure due to Missing Rule Definition (confidence: high)

  • Type: test
  • Affected jobs: 103279140499, 103279140536
  • Related to change: yes
  • Root cause: During SonarQube startup in integration tests (JavaRulingTest), the built-in quality profile loader attempted to load rule key 'java:S9365', but it could not be found, causing a BeanCreationException and subsequent server startup failure.
  • Suggested fix: Ensure that the rule 'S9365' is properly registered and defined in the plugin's rule repository and JSON/HTML resources, or update the quality profiles to reference the correct rule key.

Missing Ruling Artifacts in Notification Job (confidence: high)

  • Type: infrastructure
  • Affected jobs: 103281359000
  • Related to change: yes
  • Root cause: The workflow expected ruling artifacts to be generated and available from the integration test run, but because the tests failed to start SonarQube, no artifacts were uploaded, causing the artifact synchronization step to fail.
  • Suggested fix: Fix the underlying integration test/rule registration failure so that artifacts are successfully generated and uploaded.

Summary

  • Change-related failures: 2 failures (1 test failure causing SonarQube startup error, 1 cascading infrastructure failure due to missing artifacts)
  • Infrastructure/flaky failures: 0 infrastructure-only failures
  • Recommended action: Register the missing rule 'java:S9365' in the plugin definitions to fix the integration tests and allow the full build and ruling workflow to complete successfully.
Code Review 🚫 Blocked 0 resolved / 4 findings

Implements rule S9385 to detect copy constructors that fail to initialize eligible fields, with comprehensive test coverage. The change is blocked by three issues: the rule key was renamed from S9365 to S9385 but old S9365 resources remain in the repository, causing both rule keys to be activated in the generated profile while S9365 no longer exists in code; S9385.json still references RSPEC-9365 instead of updating to match the new key; and the test samples dropped all message and secondary-location assertions, leaving the rule's advertised behavior (identifying omitted field declarations as secondary locations) uncovered by tests. Additionally, javadoc was removed from analyzeMethod and AssignmentCollector that documented non-obvious analysis contracts.

🚨 Bug: Rule key renamed S9365→S9385 but old rule resources kept

📄 java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:48 📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9385.json:13-14

The base commit already shipped this check as @Rule(key = "S9365") with matching resources (S9365.html, S9365.json, profiles/Sonar_way/S9365). This commit changes the annotation to S9385 and adds S9385.html (byte-identical to S9365.html) plus S9385.json (differs from S9365.json only in sqKey) and profiles/Sonar_way/S9385, while leaving all three S9365 files in place. ProfileJsonGenerator.collectRuleKeys turns every marker file into a rule key, so the generated Sonar_way_profile.json now activates both java:S9365 and java:S9385, but no check class declares key S9365 any more — the built-in profile activates a rule that does not exist in the java repository, and the repository ends up with two identical rule descriptions. GeneratedCheckListTest only walks from check classes to metadata, so it will not catch the orphan. Either revert the key to S9365 (matching the untouched ruleSpecification: "RSPEC-9365") and drop the three new S9385 files, or complete the rename by deleting S9365.html, S9365.json and profiles/Sonar_way/S9365.

Keep the already-released key S9365 and delete the newly added S9385.html, S9385.json and profiles/Sonar_way/S9385 files.
@Rule(key = "S9365")
Alternative: finish the rename by removing the S9365 html, json and Sonar_way marker so only S9385 remains.
// keep @Rule(key = "S9385") and remove the stale resources:
//   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.html
//   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.json
//   git rm sonar-java-plugin/src/main/resources/profiles/Sonar_way/S9365
⚠️ Bug: S9385.json points at ruleSpecification RSPEC-9365

📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9385.json:13-14

S9385.json was copied from S9365.json with only sqKey updated, so it still declares "ruleSpecification": "RSPEC-9365" while "sqKey": "S9385". Every other rule metadata file in this directory keeps the two in sync (e.g. S6912 → RSPEC-6912), so the new rule links its documentation and traceability to a different RSPEC id. If S9385 is the intended key, update the field; if RSPEC-9365 is correct, the key change itself is the mistake.

Align ruleSpecification with the new sqKey.
"ruleSpecification": "RSPEC-9385",
"sqKey": "S9385",
💡 Quality: Sample drops message and secondary-location assertions

📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:14 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:48 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:56 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:64 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:104 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:139 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:151 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:163 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:187 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:207 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:222 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:351 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:361 📄 java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:381 📄 java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:97-107

All 17 // Noncompliant comments lose their [[secondary=...]] assertions and the primary {{...}} message assertion. CheckVerifier.verifyIssues() only compares secondaries and messages when the comment declares them, so the tests still pass but nothing now covers the secondary locations the check builds in visitNode — the very behaviour the rule description advertises ("The declarations of the omitted fields are identified as secondary locations"). The previously asserted values were correct (e.g. Basic eligible fields are lines 9-12 with name assigned, giving secondaries 10,11,12), so restoring at least the message assertion plus secondaries on a couple of representative cases keeps that behaviour under test.

Restore the message and secondary assertions on at least the representative cases (Basic, Generic, DeferredAssignments).
Basic(Basic other) { // Noncompliant {{This copy constructor leaves eligible fields uninitialized; initialize them explicitly to distinguish omissions from intentional resets.}} [[secondary=10,11,12]]
💡 Quality: Documentation removed from the check's complex methods

📄 java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:136-137 📄 java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:148

The commit strips the javadoc from analyzeMethod and from the AssignmentCollector class, which documented the non-obvious contracts of the analysis: what activeMethods is for (recursion detection in the current call chain) and what complete means (no issue is raised unless every followed initialization path resolved). Those contracts are not derivable from the signatures and are exactly the "documentation for complex functions" the project guidelines ask for, so keeping the javadoc on these two elements is preferable to removing it along with the inline comments.

Restore the javadoc on analyzeMethod (and equivalently on AssignmentCollector).
/**
 * Analyzes explicit field writes performed by a constructor or helper method, including writes reached through
 * resolvable calls on the current instance. Active methods form the current call chain and prevent infinite recursion.
 */
private static AnalysisResult analyzeMethod(MethodTree method, Symbol.TypeSymbol owner, Set<Symbol> eligibleFields,
  Set<Symbol.MethodSymbol> activeMethods) {
🤖 Prompt for agents
Code Review: Implements rule S9385 to detect copy constructors that fail to initialize eligible fields, with comprehensive test coverage. The change is blocked by three issues: the rule key was renamed from S9365 to S9385 but old S9365 resources remain in the repository, causing both rule keys to be activated in the generated profile while S9365 no longer exists in code; `S9385.json` still references `RSPEC-9365` instead of updating to match the new key; and the test samples dropped all message and secondary-location assertions, leaving the rule's advertised behavior (identifying omitted field declarations as secondary locations) uncovered by tests. Additionally, javadoc was removed from `analyzeMethod` and `AssignmentCollector` that documented non-obvious analysis contracts.

1. 🚨 Bug: Rule key renamed S9365→S9385 but old rule resources kept
   Files: java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:48, sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9385.json:13-14

   The base commit already shipped this check as `@Rule(key = "S9365")` with matching resources (`S9365.html`, `S9365.json`, `profiles/Sonar_way/S9365`). This commit changes the annotation to `S9385` and adds `S9385.html` (byte-identical to `S9365.html`) plus `S9385.json` (differs from `S9365.json` only in `sqKey`) and `profiles/Sonar_way/S9385`, while leaving all three S9365 files in place. `ProfileJsonGenerator.collectRuleKeys` turns every marker file into a rule key, so the generated `Sonar_way_profile.json` now activates both `java:S9365` and `java:S9385`, but no check class declares key S9365 any more — the built-in profile activates a rule that does not exist in the java repository, and the repository ends up with two identical rule descriptions. `GeneratedCheckListTest` only walks from check classes to metadata, so it will not catch the orphan. Either revert the key to S9365 (matching the untouched `ruleSpecification: "RSPEC-9365"`) and drop the three new S9385 files, or complete the rename by deleting `S9365.html`, `S9365.json` and `profiles/Sonar_way/S9365`.

   Fix (Keep the already-released key S9365 and delete the newly added S9385.html, S9385.json and profiles/Sonar_way/S9385 files.):
   @Rule(key = "S9365")

   Fix (Alternative: finish the rename by removing the S9365 html, json and Sonar_way marker so only S9385 remains.):
   // keep @Rule(key = "S9385") and remove the stale resources:
   //   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.html
   //   git rm sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9365.json
   //   git rm sonar-java-plugin/src/main/resources/profiles/Sonar_way/S9365

2. ⚠️ Bug: S9385.json points at ruleSpecification RSPEC-9365
   Files: sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9385.json:13-14

   `S9385.json` was copied from `S9365.json` with only `sqKey` updated, so it still declares `"ruleSpecification": "RSPEC-9365"` while `"sqKey": "S9385"`. Every other rule metadata file in this directory keeps the two in sync (e.g. S6912 → RSPEC-6912), so the new rule links its documentation and traceability to a different RSPEC id. If S9385 is the intended key, update the field; if RSPEC-9365 is correct, the key change itself is the mistake.

   Fix (Align ruleSpecification with the new sqKey.):
   "ruleSpecification": "RSPEC-9385",
   "sqKey": "S9385",

3. 💡 Quality: Sample drops message and secondary-location assertions
   Files: java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:14, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:48, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:56, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:64, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:104, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:139, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:151, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:163, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:187, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:207, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:222, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:351, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:361, java-checks-test-sources/default/src/main/java/checks/CopyConstructorMissesFieldCheckSample.java:381, java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:97-107

   All 17 `// Noncompliant` comments lose their `[[secondary=...]]` assertions and the primary `{{...}}` message assertion. `CheckVerifier.verifyIssues()` only compares secondaries and messages when the comment declares them, so the tests still pass but nothing now covers the secondary locations the check builds in `visitNode` — the very behaviour the rule description advertises ("The declarations of the omitted fields are identified as secondary locations"). The previously asserted values were correct (e.g. `Basic` eligible fields are lines 9-12 with `name` assigned, giving secondaries 10,11,12), so restoring at least the message assertion plus secondaries on a couple of representative cases keeps that behaviour under test.

   Fix (Restore the message and secondary assertions on at least the representative cases (Basic, Generic, DeferredAssignments).):
   Basic(Basic other) { // Noncompliant {{This copy constructor leaves eligible fields uninitialized; initialize them explicitly to distinguish omissions from intentional resets.}} [[secondary=10,11,12]]

4. 💡 Quality: Documentation removed from the check's complex methods
   Files: java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:136-137, java-checks/src/main/java/org/sonar/java/checks/CopyConstructorMissesFieldCheck.java:148

   The commit strips the javadoc from `analyzeMethod` and from the `AssignmentCollector` class, which documented the non-obvious contracts of the analysis: what `activeMethods` is for (recursion detection in the current call chain) and what `complete` means (no issue is raised unless every followed initialization path resolved). Those contracts are not derivable from the signatures and are exactly the "documentation for complex functions" the project guidelines ask for, so keeping the javadoc on these two elements is preferable to removing it along with the inline comments.

   Fix (Restore the javadoc on analyzeMethod (and equivalently on AssignmentCollector).):
   /**
    * Analyzes explicit field writes performed by a constructor or helper method, including writes reached through
    * resolvable calls on the current instance. Active methods form the current call chain and prevent infinite recursion.
    */
   private static AnalysisResult analyzeMethod(MethodTree method, Symbol.TypeSymbol owner, Set<Symbol> eligibleFields,
     Set<Symbol.MethodSymbol> activeMethods) {

Implementation Status ✅ 1 of 1 objectives covered
SONARJAVA-6945 - 1 of 1 objectives covered

This PR implements rule S9385, which ensures copy constructors initialize all fields.

✅ 1 covered here
  • ✅ Create rule S9385: Copy constructors should copy all fields

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Counting what did not apply, without listing it.
Unblock → Override a blocking verdict and allow merging.

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

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

Was this helpful? React with 👍 / 👎 | Gitar

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ This PR is blocked due to unresolved code review findings.

Comment gitar unblock to override this block and allow merging.

Configure merge blocking · Maintainers can dismiss this review.

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.

1 participant