SONARJAVA-6411 Implement Visitor for collecting packages scanned by Spring#5662
SONARJAVA-6411 Implement Visitor for collecting packages scanned by Spring#5662asya-vorobeva wants to merge 18 commits into
Conversation
Introduce the springcontext package with BeanDefinitionHolder, BeanDefinitionRegistry, BeanLocation, EntityClassToPropertiesIndex, ProjectPackageScan, SpringContextModel, and TypeToBeanNamesIndex. All classes include Javadoc documentation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ONARJAVA-6237 # Conflicts: # its/scanner-integration-tests/pom.xml # java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java
- Add ComponentScanPackageCollector visitor in spring/context package: collects @componentscan and @SpringBootApplication scanned packages per module and writes them to ProjectPackageScan in the shared SpringContextModel. Supports incremental analysis via cache. This visitor's usage will replace existing SpringBeansShouldBeAccessible visitor in future PRs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-frontend - Move SpringUtils and UnitTestUtils from java-checks helpers to java-frontend model package - Rename ComponentScanPackageCollector to ComponentScanPackageGatherer - Add SpringContextModel provisioning support to CheckVerifier - Add unit tests for ComponentScanPackageGatherer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add test verifying SpringContextModel is filled with ProjectPackageScan after JavaFrontend.scan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and CheckVerifier#getSpringContextModel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… scan annotations
When a file has no scan annotations, an empty string was written to cache.
Reading it back via String#split(";") incorrectly produced [""] instead of an empty list,
causing a blank package name to be registered in ProjectPackageScan.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…path Implement DependencyVersionAware in SpringContextModelGatherer so all gatherers are automatically skipped on modules without spring-context on the classpath. Add integration test verifying the gatherer produces no output when spring-context is removed from the classpath. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reimplements all non-caching tests using VisitorsBridge + JParserTestUtils directly in java-frontend, closing the coverage gap caused by the class living in java-frontend while its tests previously lived in java-checks. Test resource files that were only needed for non-caching tests are moved from java-checks-test-sources to java-frontend/src/test/files/springcontext/. The java-checks ComponentScanPackageGathererTest retains only caching tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extend SpringContextModelGatherer from IssuableSubscriptionVisitor instead of SubscriptionVisitor so that leaveFile is called by IssuableSubscriptionVisitorsRunner, enabling per-file cache writes and fixing incremental analysis performance (eclipse_jetty_incremental) - Move all ComponentScanPackageGatherer tests to java-frontend using VisitorsBridge + JParserTestUtils; caching tests use mocked ReadCache/WriteCache injected via SensorContextTester - Remove getSpringContextModel() from CheckVerifier interface and both implementations — no longer needed now tests live in java-frontend Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Anonymous class: visitNode returns early when simpleName() is null - Blank scanBasePackages entry: resolvePackage falls through to Optional.empty() for blank strings, which are silently ignored Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
38722f0 to
eb5b5bb
Compare
leonardo-pilastri-sonarsource
left a comment
There was a problem hiding this comment.
Great work, especially with the tests and the cache implementation 🚀
I left a couple of things we should look at before merging
| * along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
| */ | ||
| package org.sonar.java.checks.helpers; | ||
| package org.sonar.java.model; |
There was a problem hiding this comment.
I feel like this is not the best package to contain this class, maybe we can put it under org.sonar.java.utils
c8dedf3 to
1bee570
Compare
| public void gatherSpringContextData(ModuleScannerContext context, SpringContextModel springContextModel) { | ||
| springContextModel.getProjectPackageScan().addPackages(context.getModuleKey(), collectedPackages); | ||
| } |
There was a problem hiding this comment.
💡 Quality: gatherSpringContextData registers empty module entries
gatherSpringContextData always calls springContextModel.getProjectPackageScan().addPackages(moduleKey, collectedPackages), and addPackages uses computeIfAbsent(module, ...).addAll(...). When collectedPackages is empty (a module on which spring-context is in the classpath but no @ComponentScan/@SpringBootApplication scan packages were found), this still creates an empty Set entry for the module. As a result getModules() will return modules that have zero scanned packages, which may mislead downstream consumers that iterate getModules() expecting only modules with actual scan configuration.
Note endOfAnalysis runs twice per module (the same gatherer instance is registered in both the main and test scanners in JavaFrontend), so the entry is created even from the empty test-scope pass. There are no production consumers of getModules() yet, so impact is currently low, but it is worth guarding against. Suggested fix: skip the write when collectedPackages is empty.
Avoid creating empty module entries in ProjectPackageScan.:
@Override
public void gatherSpringContextData(ModuleScannerContext context, SpringContextModel springContextModel) {
if (collectedPackages.isEmpty()) {
return;
}
springContextModel.getProjectPackageScan().addPackages(context.getModuleKey(), collectedPackages);
}
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
1bee570 to
72affd0
Compare
72affd0 to
52f9e4d
Compare
leonardo-pilastri-sonarsource
left a comment
There was a problem hiding this comment.
Looks good, but I think the its/sources submodule slipped through, if you can remove that, then it's good to go
- Test isCompatibleWithDependencies for all four trigger dependencies (spring-context, spring-beans, spring-boot-starter, spring-boot-starter-web) and for the none-present case using a parameterized test - Move SpringUtils and UnitTestUtils from java-frontend model package to java-frontend utils package; update all import sites in java-checks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52f9e4d to
7e9f7af
Compare
|
CI failed: The build failed due to an integration test regression in `JavaRulingTest.eclipse_jetty_incremental`, where the analyzer produced a larger output than the current test baseline.OverviewA single integration test failure was identified in the FailuresJavaRulingTest.eclipse_jetty_incremental (confidence: high)
Summary
Code Review 👍 Approved with suggestions 6 resolved / 7 findingsImplements 💡 Quality: gatherSpringContextData registers empty module entries📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/ComponentScanPackageGatherer.java:112-114 📄 java-frontend/src/main/java/org/sonar/java/model/springcontext/ProjectPackageScan.java:51-53
Note Avoid creating empty module entries in ProjectPackageScan.✅ 6 resolved✅ Edge Case: Unresolved basePackageClasses symbol yields empty-string package
✅ Quality: @VisibleForTesting on a private field is contradictory
✅ Edge Case: @SpringBootApplication own-package fallback uses file-level, not class-level state
✅ Edge Case: Own-package fallback can register a blank package name
✅ Quality: Javadoc still says gatherers skipped unless spring-context present
...and 1 more resolved from earlier reviews 🤖 Prompt for agentsTip Comment OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |



See SONARJAVA-6411.
Summary by Gitar
ComponentScanPackageGathererto collect packages configured via@ComponentScanand@SpringBootApplication.SpringContextModelto track Spring configuration across project modules.SpringUtilsandUnitTestUtilstojava-frontendto centralize model-related utilities.ComponentScanPackageGathererTestand extendedCheckVerifierto support asserting onSpringContextModeldata.SpringContextModelGatherervisitors whenspring-contextis missing from the classpath usingDependencyVersionAware.This will update automatically on new commits.