Skip to content

SONARJAVA-6442 Introduce SpringContextModelGatherer and SpringContextModelSensor#5654

Merged
leonardo-pilastri-sonarsource merged 7 commits into
epic-SONARJAVA-6237from
lp/draft-spring-context-gatherers
Jun 5, 2026
Merged

SONARJAVA-6442 Introduce SpringContextModelGatherer and SpringContextModelSensor#5654
leonardo-pilastri-sonarsource merged 7 commits into
epic-SONARJAVA-6237from
lp/draft-spring-context-gatherers

Conversation

@leonardo-pilastri-sonarsource
Copy link
Copy Markdown
Contributor

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource commented Jun 4, 2026

SpringContextModel is now a ScannerSide component living across modules and plugged into the DefaultModuleScannerContext (for gathering data) and the SpringContextModelSensor (for issue reporting, after all modules)

Added SpringContextModelGatherer abstract class that allows subclasses to visit the AST and to gather spring-related data at the end of a module analysis, inside the SpringContextModel.


Summary by Gitar

  • New Testing Rules:
    • Added S8714: Identifies try-catch blocks with fail() calls that should be replaced by assertThrows or assertDoesNotThrow.
    • Added S8715: Prohibits the use of JUnit 4 assertions within JUnit 5 test classes to ensure consistency and correct failure message handling.
    • Added S8745: Enforces that classes contain at most one lifecycle method per annotation type (@BeforeEach, @AfterEach, etc.) to guarantee predictable execution.
  • Refactoring & Infrastructure:
    • Improved UnitTestUtils to better identify JUnit 5 annotations and fail-method invocations, and updated SuppressWarningFilter to handle lowercase rule names.
    • Updated test suites across the project to replace manual try-catch-fail blocks with AssertJ's assertThatThrownBy and assertThatCode for more robust testing.

This will update automatically on new commits.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 4, 2026

Agentic Analysis: Early Results

Agentic Analysis and Context Augmentation are available on your project. Here are some issues that could have been prevented. Follow the links to learn how to put them into action.

2 issue(s) found across 2 file(s):

Rule File Line Message
java:S107 sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java 77 Constructor has 8 parameters, which is greater than 7 authorized.
java:S1068 sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java 29 Remove this unused "springContextModel" private field.

Analyzed by SonarQube Agentic Analysis in 4.2 s

@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Introduce SpringContextModelGatherer and SpringContextModelSensor SONARJAVA-6442 Introduce SpringContextModelGatherer and SpringContextModelSensor Jun 4, 2026
@hashicorp-vault-sonar-prod
Copy link
Copy Markdown
Contributor

hashicorp-vault-sonar-prod Bot commented Jun 4, 2026

SONARJAVA-6442

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from 89ad9fe to b7d2953 Compare June 4, 2026 13:08
gitar-bot[bot]

This comment was marked as resolved.

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from b7d2953 to cff1689 Compare June 4, 2026 14:06
@gitar-bot gitar-bot Bot dismissed their stale review June 4, 2026 14:07

✅ Code review updated (blocking issues remain unresolved).

Configure merge blocking

/**
* Method called at the end of the analysis of a module, allowing to store gathered data in the SpringContextModel.
*/
public abstract void gatherSpringContextData(SpringContextModel springContextModel);
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.

Add parameter: ModuleScannerContext context

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from 7931bd5 to 572961e Compare June 5, 2026 10:08
Comment thread java-frontend/src/main/java/org/sonar/java/SonarComponents.java
Copy link
Copy Markdown
Contributor

@asya-vorobeva asya-vorobeva left a comment

Choose a reason for hiding this comment

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

Generally LGTM, please fix QG failures before merge. And rebase to master to fix broken CI (was fixed in https://github.com/SonarSource/sonar-java/pull/5658/changes).

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch 2 times, most recently from 12dd139 to b2feb69 Compare June 5, 2026 14:38
@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from b2feb69 to 6bbc6af Compare June 5, 2026 14:41
@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from 6bbc6af to f434514 Compare June 5, 2026 14:51
@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource force-pushed the lp/draft-spring-context-gatherers branch from f434514 to 6f2b7c8 Compare June 5, 2026 15:04
@sonarqube-next
Copy link
Copy Markdown

sonarqube-next Bot commented Jun 5, 2026

Quality Gate failed Quality Gate failed

Failed conditions
84.6% Coverage on New Code (required ≥ 90%)

See analysis details on SonarQube

@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource merged commit 9251ba1 into epic-SONARJAVA-6237 Jun 5, 2026
14 of 15 checks passed
@leonardo-pilastri-sonarsource leonardo-pilastri-sonarsource deleted the lp/draft-spring-context-gatherers branch June 5, 2026 16:07
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Jun 5, 2026

Code Review ✅ Approved 6 resolved / 6 findings

Introduces SpringContextModelGatherer and SpringContextModelSensor for cross-module data analysis, but mutable state leaks in the scanner component currently prevent correct behavior in SonarLint.

✅ 6 resolved
Bug: SpringContextModel is @ScannerSide-only but required by JavaSensor in SonarLint

📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java:33 📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java:88 📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java:120 📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java:77-91
SpringContextModel is annotated only with @ScannerSide (SpringContextModel.java:33) and registered in the common section of JavaPlugin.define() (JavaPlugin.java:88), which executes for both SonarQube and SonarLint runtimes. However, JavaSensor — which runs in SonarLint — now has constructors that take a mandatory SpringContextModel parameter (JavaSensor.java:79-85) and the value is injected by the dependency-injection container.

In a SonarLint runtime, the component container only loads components annotated with @SonarLintSide. Because SpringContextModel lacks @SonarLintSide, it will not be available for injection, so the container will be unable to satisfy the SpringContextModel dependency of JavaSensor. This will prevent JavaSensor from being instantiated in SonarLint, effectively breaking Java analysis in the IDE.

Fix: annotate SpringContextModel with @SonarLintSide (in addition to @ScannerSide) so it is available in both runtimes, matching how SonarComponents is annotated with both @ScannerSide and @SonarLintSide. Note: making the constructor parameter @Nullable alone is not sufficient, since the pico container fails on an unregistered dependency rather than passing null.

Bug: Sample gatherer accumulates state across modules without reset

📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java:28 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java:37 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java:41-44
Gatherers are instantiated once via SpringContextModelGatherers.getAllGatherers() and added to commonVisitors, so a single instance is reused across all files and modules for the whole scan. SampleSpringContextModelGatherer.collectedData is never cleared, while gatherSpringContextData() is invoked at every module's endOfAnalysis. As a result, each module's endOfAnalysis re-adds the cumulative list of all filenames seen so far (including from previously analyzed modules), rather than only the current module's data. The same instance is also shared between the main/test/generated scanners. This is a sample/placeholder, but real gatherers extending this base class will hit the same lifecycle trap; consider clearing per-module state after gatherSpringContextData or documenting the reset requirement on SpringContextModelGatherer.

Quality: New gatherer/sensor functionality has no test coverage

📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java:27-41 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java:29-41
The new SpringContextModelGatherer (end-of-analysis wiring, cast to DefaultModuleScannerContext) and SpringContextModelSensor have no dedicated tests. The only test changes are mechanical constructor-signature updates in JavaSensorTest passing null for the new SpringContextModel parameter. Add tests verifying that gatherers run during scanning and that data lands in the shared SpringContextModel after the POST-phase sensor executes, to lock in the cross-module lifecycle before more gatherers are added on top of this base class.

Quality: New test files missing SonarSource license header

📄 java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java:1 📄 java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelTest.java:1
Both new test files start directly with the package declaration and lack the SonarSource SSALv1 license header that is present in essentially every other source/test file in the repo (64+ files in this same package alone include the SonarQube Java header). The build configures the com.mycila:license-maven-plugin and defines the <license.title>SonarQube Java</license.title> property in the root pom, so the license:check goal will fail on these headerless files and break CI. Add the standard license header block to the top of both files (e.g. run mvn license:format).

Quality: Debug System.out.println left in production sensor

📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java:42
SpringContextModelSensor.execute() calls System.out.println(springContextModel). This is a debug leftover that will print to stdout on every project analysis (both SonarQube and SonarLint, since the sensor is registered in all contexts). SpringContextModel does not override toString(), so this emits an unhelpful object identity string and pollutes scanner/build logs. Replace it with proper logging guarded by debug level, or remove it before this leaves draft. If kept, use an SLF4J logger at debug level instead of stdout.

...and 1 more resolved from earlier reviews

Options

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

Comment with these commands to change:

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

Was this helpful? React with 👍 / 👎 | Gitar

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