diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaAgentQualityProfile.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaAgentQualityProfile.java new file mode 100644 index 00000000000..a9f7105ca03 --- /dev/null +++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaAgentQualityProfile.java @@ -0,0 +1,56 @@ +/* + * SonarQube Java + * Copyright (C) 2012-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. + * + * 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 java.util.Set; +import java.util.stream.Collectors; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; +import org.sonar.java.GeneratedCheckList; +import org.sonar.java.annotations.VisibleForTesting; +import org.sonarsource.analyzer.commons.BuiltInQualityProfileJsonLoader; +import org.sonarsource.api.sonarlint.SonarLintSide; + +/** + * Agent Quality Profile - Built-in profile focused on security, reliability, and code complexity + * + * This profile activates rules that help maintain code quality for AI agents by focusing on: + * - Security vulnerabilities and security hotspots + * - Reliability issues (bugs) + * - Code complexity metrics (cognitive complexity, cyclomatic complexity, etc.) + */ +@SonarLintSide +public class JavaAgentQualityProfile implements BuiltInQualityProfilesDefinition { + + static final String AGENT_PROFILE_PATH = "/org/sonar/l10n/java/rules/java/Agent_quality_profile.json"; + static final String PROFILE_NAME = "Agent Quality Profile"; + + @Override + public void define(Context context) { + NewBuiltInQualityProfile agentProfile = context.createBuiltInQualityProfile(PROFILE_NAME, Java.KEY); + Set ruleKeys = agentProfileRuleKeys(); + ruleKeys.forEach(ruleKey -> agentProfile.activateRule(ruleKey.repository(), ruleKey.rule())); + agentProfile.done(); + } + + @VisibleForTesting + static Set agentProfileRuleKeys() { + return BuiltInQualityProfileJsonLoader.loadActiveKeysFromJsonProfile(AGENT_PROFILE_PATH).stream() + .map(rule -> RuleKey.of(GeneratedCheckList.REPOSITORY_KEY, rule)) + .collect(Collectors.toSet()); + } +} 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 c1f64a5613c..bee891bb642 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 @@ -62,6 +62,7 @@ public void define(Context context) { list.addAll(SurefireExtensions.getExtensions()); list.add(DroppedPropertiesSensor.class); list.add(JavaSonarWayProfile.class); + list.add(JavaAgentQualityProfile.class); list.add(ClasspathForMain.class); ExternalReportExtensions.define(context); diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/Agent_quality_profile.json b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/Agent_quality_profile.json new file mode 100644 index 00000000000..f46b785bcbf --- /dev/null +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/Agent_quality_profile.json @@ -0,0 +1,242 @@ +{ + "name": "Agent Quality Profile", + "ruleKeys": [ + "S104", + "S1067", + "S107", + "S108", + "S109", + "S1111", + "S1114", + "S1141", + "S1142", + "S1143", + "S1151", + "S1172", + "S1175", + "S1188", + "S1200", + "S1201", + "S1217", + "S1221", + "S1244", + "S1317", + "S134", + "S138", + "S1448", + "S1479", + "S1541", + "S1656", + "S1700", + "S1751", + "S1764", + "S1774", + "S1820", + "S1821", + "S1849", + "S1860", + "S1862", + "S1872", + "S1996", + "S2053", + "S2060", + "S2061", + "S2068", + "S2077", + "S2109", + "S2110", + "S2111", + "S2114", + "S2115", + "S2116", + "S2118", + "S2119", + "S2121", + "S2122", + "S2123", + "S2127", + "S2134", + "S2141", + "S2142", + "S2151", + "S2154", + "S2159", + "S2168", + "S2175", + "S2177", + "S2201", + "S2204", + "S2225", + "S2226", + "S2229", + "S2230", + "S2234", + "S2236", + "S2245", + "S2251", + "S2252", + "S2254", + "S2257", + "S2273", + "S2275", + "S2276", + "S2326", + "S2390", + "S2441", + "S2445", + "S2446", + "S2612", + "S2639", + "S2647", + "S2658", + "S2677", + "S2695", + "S2757", + "S2761", + "S2789", + "S2885", + "S2886", + "S2972", + "S3030", + "S3034", + "S3039", + "S3046", + "S3064", + "S3067", + "S3078", + "S3306", + "S3329", + "S3346", + "S3358", + "S3436", + "S3551", + "S3553", + "S3750", + "S3753", + "S3776", + "S3923", + "S3981", + "S3984", + "S3986", + "S4143", + "S4274", + "S4275", + "S4347", + "S4348", + "S4351", + "S4423", + "S4426", + "S4433", + "S4434", + "S4454", + "S4502", + "S4512", + "S4517", + "S4544", + "S4601", + "S4602", + "S4684", + "S4790", + "S4792", + "S4830", + "S4973", + "S5042", + "S5164", + "S5247", + "S5320", + "S5322", + "S5324", + "S5332", + "S5344", + "S5443", + "S5445", + "S5527", + "S5542", + "S5547", + "S5612", + "S5659", + "S5679", + "S5693", + "S5779", + "S5783", + "S5790", + "S5804", + "S5808", + "S5810", + "S5831", + "S5833", + "S5845", + "S5850", + "S5852", + "S5855", + "S5856", + "S5863", + "S5866", + "S5868", + "S5876", + "S5917", + "S5960", + "S5961", + "S5967", + "S5973", + "S5979", + "S5994", + "S5996", + "S5998", + "S6001", + "S6002", + "S6070", + "S6073", + "S6103", + "S6104", + "S6209", + "S6216", + "S6218", + "S6263", + "S6288", + "S6291", + "S6293", + "S6300", + "S6301", + "S6362", + "S6363", + "S6418", + "S6432", + "S6437", + "S6804", + "S6806", + "S6810", + "S6813", + "S6814", + "S6816", + "S6817", + "S6818", + "S6829", + "S6831", + "S6832", + "S6838", + "S6856", + "S6857", + "S6862", + "S6863", + "S6881", + "S6901", + "S6906", + "S6909", + "S6913", + "S6915", + "S7177", + "S7178", + "S7179", + "S7180", + "S7183", + "S7184", + "S7185", + "S7186", + "S7190", + "S7409", + "S8346", + "S8447", + "S8465" + ] +} \ No newline at end of file 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 eb700626422..06031c47465 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 @@ -51,7 +51,7 @@ void sonarqube_9_9_extensions() { Plugin.Context context = new Plugin.Context(sqCommunity); javaPlugin.define(context); assertThat(context.getExtensions()) - .hasSize(36) + .hasSize(37) .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(37) + .hasSize(38) .contains(Jasper.class); }