From 743955aa51fce8abe5fff6e9be996da5ddf39a80 Mon Sep 17 00:00:00 2001 From: lpilastri Date: Thu, 4 Jun 2026 14:38:08 +0200 Subject: [PATCH 1/7] Introduce SpringContextModelGatherer and SpringContextModelSensor --- .../java/org/sonar/java/JavaFrontend.java | 4 ++ .../java/org/sonar/java/SonarComponents.java | 44 ++++++++++------- .../model/DefaultModuleScannerContext.java | 4 ++ .../springcontext/SpringContextModel.java | 14 +++++- .../SpringContextModelGatherer.java | 42 +++++++++++++++++ .../SpringContextModelGatherers.java | 36 ++++++++++++++ .../SampleSpringContextModelGatherer.java | 47 +++++++++++++++++++ .../org/sonar/plugins/java/JavaPlugin.java | 3 ++ .../org/sonar/plugins/java/JavaSensor.java | 11 +++-- .../java/SpringContextModelSensor.java | 44 +++++++++++++++++ .../sonar/plugins/java/JavaPluginTest.java | 6 +-- .../sonar/plugins/java/JavaSensorTest.java | 17 +++---- 12 files changed, 239 insertions(+), 33 deletions(-) create mode 100644 java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java create mode 100644 java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java create mode 100644 java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java create mode 100644 sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java diff --git a/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java b/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java index 08530df3dea..b315122b452 100644 --- a/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java +++ b/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java @@ -42,6 +42,7 @@ import org.sonar.java.filters.SonarJavaIssueFilter; import org.sonar.java.model.JParserConfig; import org.sonar.java.model.VisitorsBridge; +import org.sonar.java.model.springcontext.SpringContextModelGatherers; import org.sonar.java.telemetry.Telemetry; import org.sonar.java.telemetry.TelemetryKey; import org.sonar.plugins.java.api.JavaCheck; @@ -82,6 +83,9 @@ public JavaFrontend(JavaVersion javaVersion, SonarComponents sonarComponents, Me List commonVisitors = new ArrayList<>(); commonVisitors.add(javaResourceLocator); commonVisitors.add(new Java25FeaturesTelemetryVisitor(telemetry)); + if (sonarComponents.getSpringContextModel() != null) { + commonVisitors.addAll(SpringContextModelGatherers.getAllGatherers()); + } if (postAnalysisIssueFilter != null) { commonVisitors.add(postAnalysisIssueFilter); } diff --git a/java-frontend/src/main/java/org/sonar/java/SonarComponents.java b/java-frontend/src/main/java/org/sonar/java/SonarComponents.java index e12c282caa6..014f230a1df 100644 --- a/java-frontend/src/main/java/org/sonar/java/SonarComponents.java +++ b/java-frontend/src/main/java/org/sonar/java/SonarComponents.java @@ -66,6 +66,7 @@ import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JProblem; import org.sonar.java.model.LineUtils; +import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.reporting.AnalyzerMessage; import org.sonar.java.reporting.JavaIssue; import org.sonar.java.utils.ModuleMetadataUtils; @@ -136,12 +137,13 @@ public class SonarComponents extends CheckRegistrar.RegistrarContext { private SensorContext context; private UnaryOperator> checkFilter = UnaryOperator.identity(); private final Set additionalAutoScanCompatibleRuleKeys; + private SpringContextModel springContextModel; private boolean alreadyLoggedSkipStatus = false; public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, - CheckFactory checkFactory, ActiveRules activeRules) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, + CheckFactory checkFactory, ActiveRules activeRules) { this(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, checkFactory, activeRules, null, null, null); } @@ -149,8 +151,8 @@ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSyst * Can be called in SonarLint context when custom rules are present. */ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, - ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, + ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars) { this(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, checkFactory, activeRules, checkRegistrars, null, null); } @@ -164,8 +166,8 @@ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSyst * Thus, for this constructor, we can also assume the presence of {@code CheckRegistrar} instances. */ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, - ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, SonarLintCache sonarLintCache) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, + ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, SonarLintCache sonarLintCache) { this(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, checkFactory, activeRules, checkRegistrars, null, sonarLintCache); } @@ -174,8 +176,8 @@ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSyst * May be called in some SonarLint contexts, but not others, since ProjectDefinition might not be available. */ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, - ActiveRules activeRules, @Nullable ProjectDefinition projectDefinition) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, + ActiveRules activeRules, @Nullable ProjectDefinition projectDefinition) { this(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, checkFactory, activeRules, null, projectDefinition, null); } @@ -183,9 +185,9 @@ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSyst * May be called in some SonarLint contexts, but not others, since ProjectDefinition might not be available. */ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, - ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, - @Nullable ProjectDefinition projectDefinition) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, + ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, + @Nullable ProjectDefinition projectDefinition) { this( fileLinesContextFactory, fs, @@ -208,9 +210,9 @@ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSyst * (because ProjectDefinition can be available in recent SonarLint versions, and DBD provides a CheckRegistrar.) */ public SonarComponents(FileLinesContextFactory fileLinesContextFactory, FileSystem fs, - ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, - ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, - @Nullable ProjectDefinition projectDefinition, @Nullable SonarLintCache sonarLintCache) { + ClasspathForMain javaClasspath, ClasspathForTest javaTestClasspath, CheckFactory checkFactory, + ActiveRules activeRules, @Nullable CheckRegistrar[] checkRegistrars, + @Nullable ProjectDefinition projectDefinition, @Nullable SonarLintCache sonarLintCache) { this.fileLinesContextFactory = fileLinesContextFactory; this.fs = fs; this.javaClasspath = javaClasspath; @@ -293,7 +295,7 @@ public void registerMainChecks(String repositoryKey, Collection javaCheckClas } @Override - public void registerMainChecks(Checks checks, Collection javaCheckClassesAndInstances){ + public void registerMainChecks(Checks checks, Collection javaCheckClassesAndInstances) { registerCheckClasses(mainChecks, checks, javaCheckClassesAndInstances); } @@ -339,7 +341,7 @@ private boolean hasAtLeastOneActiveRule(Collection ruleKeys) { return ruleKeys.stream().anyMatch(ruleKey -> activeRules.find(ruleKey) != null); } - private Checks getCreatedCheckFromFactory(String repositoryKey, Collection javaCheckClassesAndInstances){ + private Checks getCreatedCheckFromFactory(String repositoryKey, Collection javaCheckClassesAndInstances) { return checkFactory.create(repositoryKey).addAnnotatedChecks(javaCheckClassesAndInstances); } @@ -646,7 +648,7 @@ private void logUndefinedTypes(int maxLines) { } private static void logParserMessages(Stream>> messages, int maxProblems, String warningMessage, - String debugMessage) { + String debugMessage) { String problemDelimiter = System.lineSeparator() + "- "; List> messagesList = messages .sorted(Comparator.comparing(entry -> entry.getKey().toString())) @@ -692,4 +694,12 @@ public Configuration getConfiguration() { return context.config(); } + public void setSpringContextModel(SpringContextModel springContextModel) { + this.springContextModel = springContextModel; + } + + public SpringContextModel getSpringContextModel() { + return springContextModel; + } + } diff --git a/java-frontend/src/main/java/org/sonar/java/model/DefaultModuleScannerContext.java b/java-frontend/src/main/java/org/sonar/java/model/DefaultModuleScannerContext.java index 96b33879f2a..4f55991212e 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/DefaultModuleScannerContext.java +++ b/java-frontend/src/main/java/org/sonar/java/model/DefaultModuleScannerContext.java @@ -25,6 +25,7 @@ import org.sonar.api.config.Configuration; import org.sonar.java.SonarComponents; import org.sonar.java.caching.CacheContextImpl; +import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.reporting.AnalyzerMessage; import org.sonar.plugins.java.api.JavaCheck; import org.sonar.plugins.java.api.JavaVersion; @@ -115,5 +116,8 @@ public Configuration getConfiguration() { return sonarComponents.getConfiguration(); } + public SpringContextModel getSpringContextModel() { + return sonarComponents.getSpringContextModel(); + } } diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java index d9ee0e64cce..d2810ad899a 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java @@ -16,6 +16,9 @@ */ package org.sonar.java.model.springcontext; +import org.sonar.api.scanner.ScannerSide; +import org.sonarsource.api.sonarlint.SonarLintSide; + /** * Aggregates all Spring context information collected during project scanning. * @@ -28,6 +31,8 @@ *
  • {@link EntityClassToPropertiesIndex} — JPA {@code @Entity} class properties
  • * */ +@ScannerSide +@SonarLintSide public class SpringContextModel { /** Registry of all bean definitions discovered during scanning. */ private BeanDefinitionRegistry beanDefinitionRegistry; @@ -41,6 +46,13 @@ public class SpringContextModel { /** Index of properties associated with Spring Data / Hibernate {@code @Entity} classes. */ private EntityClassToPropertiesIndex entityClassToPropertiesIndex; + public SpringContextModel() { + this.beanDefinitionRegistry = new BeanDefinitionRegistry(); + this.projectPackageScan = new ProjectPackageScan(); + this.typeToBeanNamesIndex = new TypeToBeanNamesIndex(); + this.entityClassToPropertiesIndex = new EntityClassToPropertiesIndex(); + } + public BeanDefinitionRegistry getBeanDefinitionRegistry() { return beanDefinitionRegistry; } @@ -72,4 +84,4 @@ public EntityClassToPropertiesIndex getEntityClassToPropertiesIndex() { public void setEntityClassToPropertiesIndex(EntityClassToPropertiesIndex entityClassToPropertiesIndex) { this.entityClassToPropertiesIndex = entityClassToPropertiesIndex; } -} \ No newline at end of file +} diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java new file mode 100644 index 00000000000..265f89806cb --- /dev/null +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java @@ -0,0 +1,42 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.java.model.springcontext; + +import org.sonar.java.ast.visitors.SubscriptionVisitor; +import org.sonar.java.model.DefaultModuleScannerContext; +import org.sonar.plugins.java.api.ModuleScannerContext; +import org.sonar.plugins.java.api.internal.EndOfAnalysis; + +/** + * Base class for visitors that need to gather data in the SpringContextModel at the end of the analysis. + * Extending classes will have to implement the AST visitor pattern, gather relevant spring-related data, and store it + * in the SpringContextModel at the of a module analysis. + */ +public abstract class SpringContextModelGatherer extends SubscriptionVisitor implements EndOfAnalysis { + + @Override + public final void endOfAnalysis(ModuleScannerContext context) { + var defaultModuleContext = (DefaultModuleScannerContext) context; + gatherSpringContextData(defaultModuleContext.getSpringContextModel()); + } + + /** + * 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); + +} diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java new file mode 100644 index 00000000000..bcfe0298974 --- /dev/null +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java @@ -0,0 +1,36 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.java.model.springcontext; + +import org.sonar.java.model.springcontext.gatherers.SampleSpringContextModelGatherer; +import org.sonar.plugins.java.api.JavaCheck; + +import java.util.List; + +public class SpringContextModelGatherers { + + private SpringContextModelGatherers() { + // utility class, should not be instantiated + } + + public static List getAllGatherers() { + return List.of( + new SampleSpringContextModelGatherer() + ); + } + +} diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java new file mode 100644 index 00000000000..5cc70a64857 --- /dev/null +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java @@ -0,0 +1,47 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.java.model.springcontext.gatherers; + +import org.sonar.java.model.springcontext.SpringContextModel; +import org.sonar.java.model.springcontext.SpringContextModelGatherer; +import org.sonar.plugins.java.api.tree.Tree; + +import java.util.ArrayList; +import java.util.List; + +public class SampleSpringContextModelGatherer extends SpringContextModelGatherer { + + private final List collectedData = new ArrayList<>(); + + @Override + public List nodesToVisit() { + return List.of(Tree.Kind.COMPILATION_UNIT); + } + + @Override + public void visitNode(Tree tree) { + collectedData.add(context.getInputFile().filename()); + } + + @Override + public void gatherSpringContextData(SpringContextModel springContextModel) { + for (String data : collectedData) { + springContextModel.getProjectPackageScan().addPackage(data, data); + } + } + +} diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java index f013d3e1f67..ed36a74d000 100644 --- a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java +++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java @@ -37,6 +37,7 @@ import org.sonar.java.classpath.ClasspathProperties; import org.sonar.java.filters.PostAnalysisIssueFilter; import org.sonar.java.jsp.Jasper; +import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.telemetry.NoOpTelemetry; import org.sonar.java.telemetry.DefaultTelemetry; import org.sonar.plugins.java.api.JavaVersion; @@ -84,6 +85,7 @@ public void define(Context context) { .onConfigScopes(Set.of(PropertyDefinition.ConfigScope.PROJECT)) .build(), JavaRulesDefinition.class, + SpringContextModel.class, SonarComponents.class, DefaultJavaResourceLocator.class, PropertyDefinition.builder(JavaVersion.ENABLE_PREVIEW) @@ -116,6 +118,7 @@ public void define(Context context) { .defaultValue("False") .build(), JavaSensor.class, + SpringContextModelSensor.class, PostAnalysisIssueFilter.class)); list.add(AnalysisWarningsWrapper.class); diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java index 1bd10a5ac60..0358cc1d842 100644 --- a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java +++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java @@ -43,6 +43,7 @@ import org.sonar.java.jsp.Jasper; import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JavaVersionImpl; +import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.telemetry.Telemetry; import org.sonar.plugins.java.api.JavaCheck; import org.sonar.plugins.java.api.JavaResourceLocator; @@ -74,13 +75,14 @@ public class JavaSensor implements Sensor { private final Telemetry telemetry; public JavaSensor(SonarComponents sonarComponents, FileSystem fs, JavaResourceLocator javaResourceLocator, - Configuration settings, NoSonarFilter noSonarFilter, PostAnalysisIssueFilter postAnalysisIssueFilter, Telemetry telemetry) { - this(sonarComponents, fs, javaResourceLocator, settings, noSonarFilter, postAnalysisIssueFilter, null, telemetry); + Configuration settings, NoSonarFilter noSonarFilter, PostAnalysisIssueFilter postAnalysisIssueFilter, + Telemetry telemetry, SpringContextModel springContextModel) { + this(sonarComponents, fs, javaResourceLocator, settings, noSonarFilter, postAnalysisIssueFilter, null, telemetry, springContextModel); } public JavaSensor(SonarComponents sonarComponents, FileSystem fs, JavaResourceLocator javaResourceLocator, - Configuration settings, NoSonarFilter noSonarFilter, - PostAnalysisIssueFilter postAnalysisIssueFilter, @Nullable Jasper jasper, Telemetry telemetry) { + Configuration settings, NoSonarFilter noSonarFilter, PostAnalysisIssueFilter postAnalysisIssueFilter, + @Nullable Jasper jasper, Telemetry telemetry, SpringContextModel springContextModel) { this.noSonarFilter = noSonarFilter; this.sonarComponents = sonarComponents; this.fs = fs; @@ -91,6 +93,7 @@ public JavaSensor(SonarComponents sonarComponents, FileSystem fs, JavaResourceLo this.telemetry = telemetry; this.sonarComponents.registerMainChecks(GeneratedCheckList.REPOSITORY_KEY, GeneratedCheckList.getJavaChecks()); this.sonarComponents.registerTestChecks(GeneratedCheckList.REPOSITORY_KEY, GeneratedCheckList.getJavaTestChecks()); + this.sonarComponents.setSpringContextModel(springContextModel); } @Override diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java new file mode 100644 index 00000000000..fdea34540fc --- /dev/null +++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java @@ -0,0 +1,44 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.plugins.java; + +import org.sonar.api.batch.Phase; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.scanner.sensor.ProjectSensor; +import org.sonar.java.jsp.Jasper; +import org.sonar.java.model.springcontext.SpringContextModel; + +@Phase(name = Phase.Name.POST) +public class SpringContextModelSensor implements ProjectSensor { + + private final SpringContextModel springContextModel; + + public SpringContextModelSensor(SpringContextModel springContextModel) { + this.springContextModel = springContextModel; + } + + @Override + public void describe(SensorDescriptor descriptor) { + descriptor.onlyOnLanguages(Java.KEY, Jasper.JSP_LANGUAGE_KEY).name("Java SpringContextModelSensor"); + } + + @Override + public void execute(SensorContext context) { + System.out.println(springContextModel); + } +} diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java index 40dc64634bb..7f36b04670f 100644 --- a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java +++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java @@ -40,7 +40,7 @@ void sonarLint_9_9_extensions() { Plugin.Context context = new Plugin.Context(runtime); javaPlugin.define(context); assertThat(context.getExtensions()) - .hasSize(20) + .hasSize(22) .contains(SonarLintCache.class); } @@ -51,7 +51,7 @@ void sonarqube_9_9_extensions() { Plugin.Context context = new Plugin.Context(sqCommunity); javaPlugin.define(context); assertThat(context.getExtensions()) - .hasSize(37) + .hasSize(39) .doesNotContain(Jasper.class); } @@ -61,7 +61,7 @@ void sonarqube_9_9_commercial_extensions() { Plugin.Context context = new Plugin.Context(sqEnterprise); javaPlugin.define(context); assertThat(context.getExtensions()) - .hasSize(38) + .hasSize(40) .contains(Jasper.class); } diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java index 76b3573c242..4f8beb37e2a 100644 --- a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java +++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java @@ -66,6 +66,7 @@ import org.sonar.java.jsp.Jasper; import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JavaVersionImpl; +import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.reporting.AnalyzerMessage; import org.sonar.java.telemetry.DefaultTelemetry; import org.sonar.java.telemetry.Telemetry; @@ -113,7 +114,7 @@ class JavaSensorTest { @Test void test_toString() throws IOException { SonarComponents sonarComponents = createSonarComponentsMock(createContext(InputFile.Type.MAIN)); - assertThat(new JavaSensor(sonarComponents, null, null, null, null, null, telemetry)).hasToString("JavaSensor"); + assertThat(new JavaSensor(sonarComponents, null, null, null, null, null, telemetry, null)).hasToString("JavaSensor"); } @Test @@ -181,7 +182,7 @@ private void testIssueCreation(InputFile.Type onType, int expectedIssues) throws SonarComponents sonarComponents = createSonarComponentsMock(context); DefaultJavaResourceLocator javaResourceLocator = createDefaultJavaResourceLocator(settings.asConfig(), fs); - JavaSensor jss = new JavaSensor(sonarComponents, fs, javaResourceLocator, settings.asConfig(), noSonarFilter, null, telemetry); + JavaSensor jss = new JavaSensor(sonarComponents, fs, javaResourceLocator, settings.asConfig(), noSonarFilter, null, telemetry, null); jss.execute(context); int expectedNoSonarLine = lineNumberOfTheMethodWithNoSonar(fs); @@ -282,7 +283,7 @@ private void assertJasperIsInvoked(MapSettings settings) throws IOException { Jasper jasper = mock(Jasper.class); when(jasper.generateFiles(any(), any())).thenReturn(asList(generatedFile)); JavaSensor jss = new JavaSensor(sonarComponents, context.fileSystem(), mock(JavaResourceLocator.class), - new MapSettings().asConfig(), mock(NoSonarFilter.class), null, jasper, telemetry); + new MapSettings().asConfig(), mock(NoSonarFilter.class), null, jasper, telemetry, null); jss.execute(context); ArgumentCaptor scannerContext = ArgumentCaptor.forClass(JavaFileScannerContext.class); @@ -310,7 +311,7 @@ void should_not_invoke_jasper_jsp_compilation_in_autoscan_for_security_reasons() Jasper jasper = mock(Jasper.class); JavaSensor jss = new JavaSensor(sonarComponents, context.fileSystem(), mock(JavaResourceLocator.class), - context.config(), mock(NoSonarFilter.class), null, jasper, telemetry); + context.config(), mock(NoSonarFilter.class), null, jasper, telemetry, null); jss.execute(context); verify(jasper, never()).generateFiles(any(), any()); @@ -501,7 +502,7 @@ void custom_file_scanner_is_not_filtered_in_autoscan() throws IOException { SonarComponents components = new SonarComponents(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, specificCheckFactory, context.activeRules(), checkRegistrars, null, null); - JavaSensor jss = new JavaSensor(components, fs, resourceLocator, context.config(), mock(NoSonarFilter.class), null, telemetry); + JavaSensor jss = new JavaSensor(components, fs, resourceLocator, context.config(), mock(NoSonarFilter.class), null, telemetry, null); jss.execute(context); assertThat(hook.scanFileCount).as("Custom file scanner should be called even in autoscan mode").isPositive(); @@ -516,7 +517,7 @@ void custom_file_scanner_is_not_filtered_in_autoscan() throws IOException { void test_describe_sensor() throws IOException { DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); SonarComponents sonarComponents = createSonarComponentsMock(createContext(InputFile.Type.MAIN)); - var sensor = new JavaSensor(sonarComponents, null, null, null, null, null, telemetry); + var sensor = new JavaSensor(sonarComponents, null, null, null, null, null, telemetry, null); sensor.describe(descriptor); assertThat(descriptor.name()).isEqualTo("JavaSensor"); assertThat(descriptor.languages()).containsExactly("java", "jsp"); @@ -562,7 +563,7 @@ private SensorContextTester analyzeTwoFilesWithIssues(MapSettings settings) thro SonarComponents components = new SonarComponents(fileLinesContextFactory, fs, javaClasspath, javaTestClasspath, specificCheckFactory, context.activeRules(), checkRegistrars, null, null); - JavaSensor jss = new JavaSensor(components, fs, resourceLocator, context.config(), mock(NoSonarFilter.class), null, telemetry); + JavaSensor jss = new JavaSensor(components, fs, resourceLocator, context.config(), mock(NoSonarFilter.class), null, telemetry, null); jss.execute(context); return context; } @@ -576,7 +577,7 @@ private void executeJavaSensorForPerformanceMeasure(MapSettings settings, Path w fs.setWorkDir(workDir); SonarComponents components = createSonarComponentsMock(context); DefaultJavaResourceLocator resourceLocator = createDefaultJavaResourceLocator(context.config(), fs); - JavaSensor jss = new JavaSensor(components, fs, resourceLocator, configuration, mock(NoSonarFilter.class), null, telemetry); + JavaSensor jss = new JavaSensor(components, fs, resourceLocator, configuration, mock(NoSonarFilter.class), null, telemetry, null); jss.execute(context); } From f8db4d73a8c407cd1166dc77be72ccea1b47457d Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 10:52:44 +0200 Subject: [PATCH 2/7] Review changes --- .../springcontext/SpringContextModel.java | 30 ++---------- .../SpringContextModelGatherer.java | 4 +- .../SpringContextModelGatherers.java | 6 +-- .../SampleSpringContextModelGatherer.java | 47 ------------------- 4 files changed, 8 insertions(+), 79 deletions(-) delete mode 100644 java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java index d2810ad899a..c25706c762c 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModel.java @@ -35,53 +35,31 @@ @SonarLintSide public class SpringContextModel { /** Registry of all bean definitions discovered during scanning. */ - private BeanDefinitionRegistry beanDefinitionRegistry; + private final BeanDefinitionRegistry beanDefinitionRegistry = new BeanDefinitionRegistry(); /** Packages registered for Spring component scanning, grouped by module. */ - private ProjectPackageScan projectPackageScan; + private final ProjectPackageScan projectPackageScan = new ProjectPackageScan(); /** Index for resolving bean names by their fully-qualified type. */ - private TypeToBeanNamesIndex typeToBeanNamesIndex; + private final TypeToBeanNamesIndex typeToBeanNamesIndex = new TypeToBeanNamesIndex(); /** Index of properties associated with Spring Data / Hibernate {@code @Entity} classes. */ - private EntityClassToPropertiesIndex entityClassToPropertiesIndex; - - public SpringContextModel() { - this.beanDefinitionRegistry = new BeanDefinitionRegistry(); - this.projectPackageScan = new ProjectPackageScan(); - this.typeToBeanNamesIndex = new TypeToBeanNamesIndex(); - this.entityClassToPropertiesIndex = new EntityClassToPropertiesIndex(); - } + private final EntityClassToPropertiesIndex entityClassToPropertiesIndex = new EntityClassToPropertiesIndex(); public BeanDefinitionRegistry getBeanDefinitionRegistry() { return beanDefinitionRegistry; } - public void setBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) { - this.beanDefinitionRegistry = beanDefinitionRegistry; - } - public ProjectPackageScan getProjectPackageScan() { return projectPackageScan; } - public void setProjectPackageScan(ProjectPackageScan projectPackageScan) { - this.projectPackageScan = projectPackageScan; - } - public TypeToBeanNamesIndex getTypeToBeanNamesIndex() { return typeToBeanNamesIndex; } - public void setTypeToBeanNamesIndex(TypeToBeanNamesIndex typeToBeanNamesIndex) { - this.typeToBeanNamesIndex = typeToBeanNamesIndex; - } - public EntityClassToPropertiesIndex getEntityClassToPropertiesIndex() { return entityClassToPropertiesIndex; } - public void setEntityClassToPropertiesIndex(EntityClassToPropertiesIndex entityClassToPropertiesIndex) { - this.entityClassToPropertiesIndex = entityClassToPropertiesIndex; - } } diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java index 265f89806cb..71204364628 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherer.java @@ -31,12 +31,12 @@ public abstract class SpringContextModelGatherer extends SubscriptionVisitor imp @Override public final void endOfAnalysis(ModuleScannerContext context) { var defaultModuleContext = (DefaultModuleScannerContext) context; - gatherSpringContextData(defaultModuleContext.getSpringContextModel()); + gatherSpringContextData(context, defaultModuleContext.getSpringContextModel()); } /** * 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); + public abstract void gatherSpringContextData(ModuleScannerContext context, SpringContextModel springContextModel); } diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java index bcfe0298974..8d012038d34 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java +++ b/java-frontend/src/main/java/org/sonar/java/model/springcontext/SpringContextModelGatherers.java @@ -16,10 +16,8 @@ */ package org.sonar.java.model.springcontext; -import org.sonar.java.model.springcontext.gatherers.SampleSpringContextModelGatherer; -import org.sonar.plugins.java.api.JavaCheck; - import java.util.List; +import org.sonar.plugins.java.api.JavaCheck; public class SpringContextModelGatherers { @@ -29,7 +27,7 @@ private SpringContextModelGatherers() { public static List getAllGatherers() { return List.of( - new SampleSpringContextModelGatherer() + // example: new SampleSpringContextModelGatherer() ); } diff --git a/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java b/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java deleted file mode 100644 index 5cc70a64857..00000000000 --- a/java-frontend/src/main/java/org/sonar/java/model/springcontext/gatherers/SampleSpringContextModelGatherer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube Java - * Copyright (C) SonarSource Sàrl - * mailto:info AT sonarsource DOT com - * - * You can redistribute and/or modify this program under the terms of - * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the Sonar Source-Available License for more details. - * - * You should have received a copy of the Sonar Source-Available License - * along with this program; if not, see https://sonarsource.com/license/ssal/ - */ -package org.sonar.java.model.springcontext.gatherers; - -import org.sonar.java.model.springcontext.SpringContextModel; -import org.sonar.java.model.springcontext.SpringContextModelGatherer; -import org.sonar.plugins.java.api.tree.Tree; - -import java.util.ArrayList; -import java.util.List; - -public class SampleSpringContextModelGatherer extends SpringContextModelGatherer { - - private final List collectedData = new ArrayList<>(); - - @Override - public List nodesToVisit() { - return List.of(Tree.Kind.COMPILATION_UNIT); - } - - @Override - public void visitNode(Tree tree) { - collectedData.add(context.getInputFile().filename()); - } - - @Override - public void gatherSpringContextData(SpringContextModel springContextModel) { - for (String data : collectedData) { - springContextModel.getProjectPackageScan().addPackage(data, data); - } - } - -} From 09056d3ef5b7a5d86fb7673cf82dd6a607efbe1b Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 12:05:09 +0200 Subject: [PATCH 3/7] Added some tests --- .../SpringContextModelGathererTest.java | 72 +++++++++++++++++++ .../springcontext/SpringContextModelTest.java | 35 +++++++++ 2 files changed, 107 insertions(+) create mode 100644 java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java create mode 100644 java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelTest.java diff --git a/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java new file mode 100644 index 00000000000..3d259e38d0f --- /dev/null +++ b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.java.model.springcontext; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.internal.SensorContextTester; +import org.sonar.java.SonarComponents; +import org.sonar.java.TestUtils; +import org.sonar.java.model.JParserTestUtils; +import org.sonar.java.model.VisitorsBridge; +import org.sonar.plugins.java.api.JavaCheck; +import org.sonar.plugins.java.api.ModuleScannerContext; +import org.sonar.plugins.java.api.tree.Tree; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpringContextModelGathererTest { + + @Test + void testGatherSpringContextData() { + var model = getSpringModelAfterVisitingFile("src/test/files/model/SimpleClass.java", new SampleGatherer()); + assertThat(model.getTypeToBeanNamesIndex().getNamesForType("com.example.MyService")).containsExactly("myServiceBean"); + } + + private SpringContextModel getSpringModelAfterVisitingFile(String filePath, JavaCheck check) { + File file = new File(filePath); + InputFile inputFile = TestUtils.inputFile(file); + var compilationUnit = JParserTestUtils.parse(file); + SensorContextTester sensorContextTester = SensorContextTester.create(new File("")); + var sonarComponents = new SonarComponents(null, null, null, null, null, null); + sonarComponents.setSensorContext(sensorContextTester); + sonarComponents.setSpringContextModel(new SpringContextModel()); + + VisitorsBridge visitorsBridge = new VisitorsBridge(List.of(check), new ArrayList<>(), sonarComponents); + visitorsBridge.setCurrentFile(inputFile); + visitorsBridge.visitFile(compilationUnit, false); + visitorsBridge.endOfAnalysis(); + return sonarComponents.getSpringContextModel(); + } + + class SampleGatherer extends SpringContextModelGatherer { + + @Override + public void gatherSpringContextData(ModuleScannerContext context, SpringContextModel springContextModel) { + springContextModel.getTypeToBeanNamesIndex().addBeanForType("com.example.MyService", "myServiceBean"); + } + + @Override + public List nodesToVisit() { + return List.of(); + } + } + +} diff --git a/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelTest.java b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelTest.java new file mode 100644 index 00000000000..b207ce9f29e --- /dev/null +++ b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelTest.java @@ -0,0 +1,35 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.java.model.springcontext; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class SpringContextModelTest { + + @Test + void testInitialization() { + SpringContextModel model = new SpringContextModel(); + + assertNotNull(model.getBeanDefinitionRegistry(), "BeanDefinitionRegistry should be initialized"); + assertNotNull(model.getProjectPackageScan(), "ProjectPackageScan should be initialized"); + assertNotNull(model.getTypeToBeanNamesIndex(), "TypeToBeanNamesIndex should be initialized"); + assertNotNull(model.getEntityClassToPropertiesIndex(), "EntityClassToPropertiesIndex should be initialized"); + } + +} From 1be2243e7162cc04f73fd4e2685c5dd6fdcf67ab Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 14:26:11 +0200 Subject: [PATCH 4/7] Review changes --- .../springcontext/SpringContextModelGathererTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java index 3d259e38d0f..bc2c879fd15 100644 --- a/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java +++ b/java-frontend/src/test/java/org/sonar/java/model/springcontext/SpringContextModelGathererTest.java @@ -34,26 +34,27 @@ class SpringContextModelGathererTest { + private final SpringContextModel model = new SpringContextModel(); + @Test void testGatherSpringContextData() { - var model = getSpringModelAfterVisitingFile("src/test/files/model/SimpleClass.java", new SampleGatherer()); + getSpringModelAfterVisitingFile("src/test/files/model/SimpleClass.java", new SampleGatherer()); assertThat(model.getTypeToBeanNamesIndex().getNamesForType("com.example.MyService")).containsExactly("myServiceBean"); } - private SpringContextModel getSpringModelAfterVisitingFile(String filePath, JavaCheck check) { + private void getSpringModelAfterVisitingFile(String filePath, JavaCheck check) { File file = new File(filePath); InputFile inputFile = TestUtils.inputFile(file); var compilationUnit = JParserTestUtils.parse(file); SensorContextTester sensorContextTester = SensorContextTester.create(new File("")); var sonarComponents = new SonarComponents(null, null, null, null, null, null); sonarComponents.setSensorContext(sensorContextTester); - sonarComponents.setSpringContextModel(new SpringContextModel()); + sonarComponents.setSpringContextModel(model); VisitorsBridge visitorsBridge = new VisitorsBridge(List.of(check), new ArrayList<>(), sonarComponents); visitorsBridge.setCurrentFile(inputFile); visitorsBridge.visitFile(compilationUnit, false); visitorsBridge.endOfAnalysis(); - return sonarComponents.getSpringContextModel(); } class SampleGatherer extends SpringContextModelGatherer { From df93fb845104e3979f0c5306ab894a6b70f48e18 Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 16:30:41 +0200 Subject: [PATCH 5/7] Fix QG --- .../java/org/sonar/plugins/java/SpringContextModelSensor.java | 2 +- .../src/test/java/org/sonar/plugins/java/JavaSensorTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java index fdea34540fc..0a925a651da 100644 --- a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java +++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java @@ -39,6 +39,6 @@ public void describe(SensorDescriptor descriptor) { @Override public void execute(SensorContext context) { - System.out.println(springContextModel); + // Nothing to do for now } } diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java index 4f8beb37e2a..2ba50f5eadf 100644 --- a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java +++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java @@ -66,7 +66,6 @@ import org.sonar.java.jsp.Jasper; import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JavaVersionImpl; -import org.sonar.java.model.springcontext.SpringContextModel; import org.sonar.java.reporting.AnalyzerMessage; import org.sonar.java.telemetry.DefaultTelemetry; import org.sonar.java.telemetry.Telemetry; From 239fb7daa50505470e457062343952956f80eb48 Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 16:35:02 +0200 Subject: [PATCH 6/7] Improve coverage --- .../java/SpringContextModelSensorTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java new file mode 100644 index 00000000000..3f57cb6a5ff --- /dev/null +++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java @@ -0,0 +1,20 @@ +package org.sonar.plugins.java; + +import org.junit.jupiter.api.Test; +import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; +import org.sonar.java.model.springcontext.SpringContextModel; + +import static org.assertj.core.api.Assertions.assertThat; + +class SpringContextModelSensorTest { + + @Test + void test_toString() { + DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); + SpringContextModelSensor sensor = new SpringContextModelSensor(new SpringContextModel()); + sensor.describe(descriptor); + assertThat(descriptor.name()).isEqualTo("Java SpringContextModelSensor."); + assertThat(descriptor.languages()).containsExactly("java", "jsp"); + } + +} From 6f2b7c8edfec9f8564c61c9488ad892ac9dbea8d Mon Sep 17 00:00:00 2001 From: Leonardo Pilastri Date: Fri, 5 Jun 2026 16:49:05 +0200 Subject: [PATCH 7/7] Fix issue after rebase --- its/scanner-integration-tests/pom.xml | 2 +- .../java/SpringContextModelSensorTest.java | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/its/scanner-integration-tests/pom.xml b/its/scanner-integration-tests/pom.xml index a102f61cac4..aa013a94dbe 100644 --- a/its/scanner-integration-tests/pom.xml +++ b/its/scanner-integration-tests/pom.xml @@ -5,7 +5,7 @@ org.sonarsource.java java-its - 8.31.0-SNAPSHOT + 8.32.0-SNAPSHOT it-java-scanner-integration-tests diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java index 3f57cb6a5ff..d0796f6e08c 100644 --- a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java +++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/SpringContextModelSensorTest.java @@ -1,3 +1,19 @@ +/* + * SonarQube Java + * Copyright (C) SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * You can redistribute and/or modify this program under the terms of + * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ package org.sonar.plugins.java; import org.junit.jupiter.api.Test; @@ -13,7 +29,7 @@ void test_toString() { DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); SpringContextModelSensor sensor = new SpringContextModelSensor(new SpringContextModel()); sensor.describe(descriptor); - assertThat(descriptor.name()).isEqualTo("Java SpringContextModelSensor."); + assertThat(descriptor.name()).isEqualTo("Java SpringContextModelSensor"); assertThat(descriptor.languages()).containsExactly("java", "jsp"); }