Skip to content

SONARJAVA-6205 Add an agentic focused quality profile for Java#5531

Open
dorian-burihabwa-sonarsource wants to merge 5 commits intomasterfrom
SONARJAVA-6205
Open

SONARJAVA-6205 Add an agentic focused quality profile for Java#5531
dorian-burihabwa-sonarsource wants to merge 5 commits intomasterfrom
SONARJAVA-6205

Conversation

@dorian-burihabwa-sonarsource
Copy link
Copy Markdown
Contributor

No description provided.

@hashicorp-vault-sonar-prod
Copy link
Copy Markdown
Contributor

hashicorp-vault-sonar-prod bot commented Mar 20, 2026

SONARJAVA-6205

@dorian-burihabwa-sonarsource dorian-burihabwa-sonarsource force-pushed the SONARJAVA-6205 branch 2 times, most recently from 37eb8d7 to 0dab089 Compare March 20, 2026 15:29
@dorian-burihabwa-sonarsource dorian-burihabwa-sonarsource marked this pull request as ready for review March 20, 2026 15:56
@sonar-review-alpha
Copy link
Copy Markdown

sonar-review-alpha bot commented Mar 20, 2026

Summary

This PR introduces a new quality profile "Sonar agentic AI" tailored for AI and agentic use cases in Java, while refactoring common profile logic to eliminate duplication.

Key changes:

  • New profile: JavaAgenticWayProfile provides a curated set of 467 rules optimized for agentic scenarios, excluding rules that conflict with AI-focused development patterns
  • Refactoring: Extracted profile registration logic into a new abstract base class BuiltInJavaQualityProfile, which both this profile and the existing "Sonar way" profile now inherit from
  • Plugin registration: The new profile is registered in JavaPlugin and will be available alongside "Sonar way"
  • Dependencies: Added commons-csv (1.14.1) for CSV-based profile generation tooling

What reviewers should know

Start here:

  1. Review BuiltInJavaQualityProfile.java - This is the new base class that consolidates all the common profile logic. The template method pattern is used: define() calls the abstract methods getProfileName(), getPathToJsonProfile(), and isDefault().
  2. Review JavaAgenticWayProfile.java - This is simple: just 30 lines that extend the base class and specify which JSON file to load.

Key differences from "Sonar way":

  • The agentic profile excludes 67 specific rules (see test: S101, S110, S114, S115, etc.) that are deactivated for AI/agentic patterns
  • It is NOT set as the default profile (isDefault() = false)

About the refactoring:

  • JavaSonarWayProfile was substantially simplified by moving ~100 lines of profile logic to the base class. All the external plugin integration (security rules, dataflow bug detection) is now centralized.
  • The base class uses reflection to conditionally load rules from sonar-security and dataflow bug detection plugins if available, with a FIXME noting this should eventually be replaced with a better registration mechanism (SONARJAVA-6207).

Testing:

  • JavaAgenticWayProfileTest verifies the profile has exactly 467 rules, is not default, and explicitly tests that the 67 excluded rules are NOT present
  • The test file includes a disabled utility method for generating profiles from CSV (likely for future tooling)

Dependencies:

  • commons-csv was added but the profile generation test is disabled; this appears to be for future use or exploratory code

  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

sonar-review-alpha[bot]

This comment was marked as resolved.

@rombirli rombirli self-requested a review March 23, 2026 06:52
Copy link
Copy Markdown
Contributor

@rombirli rombirli left a comment

Choose a reason for hiding this comment

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

LGTM! I just have two questions about external rules inclusion mechanism and the purpose of profileRegistrars

Comment on lines +39 to +41
for (ProfileRegistrar profileRegistrar : profileRegistrars) {
profileRegistrar.register(ruleKeys::addAll);
}
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.

In test JavaAgenticWayProfileTest, profileRegistrars is always null and this part is never covered, is there a reason ?

public void define(Context context) {
NewBuiltInQualityProfile agenticWay = context.createBuiltInQualityProfile("AI Quality Profile", Java.KEY);
Set<RuleKey> ruleKeys = QualityProfileUtils.registerRulesFromJson(
"/org/sonar/l10n/java/rules/java/Agentic_way_profile.json",
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.

This string constant could be extracted in a constant SONAR_AGENTIC_WAY_PATH like SONAR_WAY_PATH in JavaSonarWayProfile

Comment on lines +49 to +51
ruleKeys.forEach(ruleKey -> agenticWay.activateRule(ruleKey.repository(), ruleKey.rule()));
agenticWay.done();
}
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.

These lines and the creation of agenticWay (or sonarWay) are repeated in JavaSonarWayProfile, maybe it could be refactored in QualityProfileUtils

static void createQualityProfile(String title, Set<RuleKey> ruleKeys) {
  NewBuiltInQualityProfile way = context.createBuiltInQualityProfile(title, Java.KEY);
  ruleKeys.forEach(ruleKey -> way.activateRule(ruleKey.repository(), ruleKey.rule()));
    way.done();
  }
}

Comment on lines 76 to 78
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.

Is there a reason this mechanism to include external rules is not present in JavaAgenticWayProfile? (Why the implementations diverge? Is there a justification?)

Copy link
Copy Markdown
Contributor

@rombirli rombirli left a comment

Choose a reason for hiding this comment

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

Agentic_way_profile.json seems to be wrong

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.

Is this file auto-generated from the CSV with a script? Could we add the script to the repo? It seems to be wrong!
S100 shouldn't be included according to the spreadsheet.

Image

Copy link
Copy Markdown
Contributor

@rombirli rombirli left a comment

Choose a reason for hiding this comment

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

LGTM i get the exact same json quality profile file, I still have 2 refactoring proposals :

  • use tsv format instead of csv to get rid of csv library (so we can simply split with '\t' instead of ';')
  • use a single class that take qp name and json path instead of duplicated logic (we could also get rid of qualityprofileutils.java and put everything in this class)

Copy link
Copy Markdown

@sonar-review-alpha sonar-review-alpha bot left a comment

Choose a reason for hiding this comment

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

Conclusion: Clean refactoring overall — the base class extraction is well-done and the agentic profile is properly wired up. Two issues in the generator utility method worth fixing before someone uses it to regenerate the profile.

🗣️ Give feedback

return fileName.substring(0, fileName.lastIndexOf('.'));
})
.collect(Collectors.toSet());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Path.endsWith(String) does not work like String.endsWith(String). On a Path, it checks whether the path ends with a complete path segment named exactly "_profile.json", not whether the filename string ends with that suffix. This predicate is always false, so profile JSON files (Sonar_way_profile.json, Agentic_way_profile.json, etc.) are never excluded from keysOfImplementedRules.

The bug is harmless today because profile filenames won't appear as rule IDs in the CSV, but the filter silently does nothing. Fix:

.filter(path -> !path.getFileName().toString().endsWith("_profile.json"))
  • Mark as noise

Path.of("Path", "to", "your", "input.csv"),
RULE_DESCRIPTION_DIRECTORY.resolve("Agentic_way_profile.json"),
"AI Quality Profile"
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

generate_ai_quality_profile() is missing @Test. In JUnit 5, @Disabled without @Test is a no-op — the framework never discovers the method, so the annotation provides no documentation value and could mislead a future developer into thinking this was intentionally skipped rather than just a utility method. Either add @Test so @Disabled works as intended, or remove @Disabled and leave it as a plain utility method with a descriptive Javadoc comment.

  • Mark as noise

sonar-review-alpha[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@sonar-review-alpha sonar-review-alpha bot left a comment

Choose a reason for hiding this comment

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

LGTM! ✅

🗣️ Give feedback

@sonarqube-next
Copy link
Copy Markdown

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