This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
SonarQube HTML Plugin - A static code analyzer for HTML, JSP, and related template languages (CSHTML, Vue, PHP, etc.). The plugin provides rules for code quality, accessibility (WCAG/ARIA compliance), and security.
# Build and run all unit tests
mvn clean install
# Run a single test class
mvn test -Dtest=LabelHasAssociatedControlCheckTest -pl sonar-html-plugin
# Run a specific test method
mvn test -Dtest=LabelHasAssociatedControlCheckTest#razor -pl sonar-html-plugin
# Integration tests (requires submodule init first)
git submodule init && git submodule update
mvn verify -Pits
# Plugin integration tests only
cd its/plugin && mvn verify
# Ruling tests only (compares analysis results against expected issues)
cd its/ruling && mvn verifyFiles are parsed by PageLexer which uses a chain of tokenizers to produce a list of Node objects:
CommentTokenizer- HTML (<!-- -->) and JSP (<%-- --%>) commentsDirectiveTokenizer- XML (<? ?>) and JSP (<%@ %>) directivesExpressionTokenizer- JSP expressions (<% %>)NormalElementTokenizer- HTML/XML tagsTextTokenizer- Everything else (including Razor@...syntax, which is NOT parsed as expressions)
Node types: TagNode, TextNode, CommentNode, DirectiveNode, ExpressionNode
Rules extend AbstractPageCheck and implement visitor methods:
startElement(TagNode)/endElement(TagNode)- Tag open/closecharacters(TextNode)- Text contentcomment(CommentNode),directive(DirectiveNode),expression(ExpressionNode)startDocument(List<Node>)/endDocument()- Document boundaries
Rules are annotated with @Rule(key = "S1234") and discovered via reflection in CheckClasses.
Each rule has two resource files in src/main/resources/org/sonar/l10n/web/rules/Web/:
{RuleKey}.json- Rule metadata (title, severity, tags, type){RuleKey}.html- Rule description (why, how to fix, examples)
Tests use TestHelper.scan() with CheckMessagesVerifierRule:
@Test
void testName() {
HtmlSourceCode sourceCode = TestHelper.scan(
new File("src/test/resources/checks/MyCheck/test.html"),
new MyCheck());
checkMessagesVerifier.verify(sourceCode.getIssues())
.next().atLine(5).withMessage("Expected message")
.noMore();
}Test files go in src/test/resources/checks/{CheckName}/.
- Razor syntax (
@Html.TextBoxFor,@if, etc.) is parsed as plainTextNode, not asExpressionNode. Rules needing Razor support must detect patterns in text content. - JSP expressions (
<% %>) ARE parsed asExpressionNode. - Vue files use
VueLexerwhich extracts the<template>section.
HTML: .html, .htm, .xhtml, .cshtml, .vbhtml, .aspx, .ascx, .rhtml, .erb, .shtm, .shtml, .cmp, .twig
JSP: .jsp, .jspf, .jspx
Rule metadata and descriptions are managed in the RSPEC repository. To sync updates:
- Download the rule-api JAR from sonar-rule-api
- From the repository root, run:
java -jar ../rule-api-2.18.0.5734.jar updateWhen creating PRs, add quality-web-squad as a reviewer (requires org prefix):
gh pr edit <PR_NUMBER> --add-reviewer SonarSource/quality-web-squad