Skip to content

Commit 0c8da75

Browse files
JS-1352 Allow customization of all analyzable file extensions via sonar properties (#6673)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 64e5b49 commit 0c8da75

File tree

42 files changed

+881
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+881
-619
lines changed

its/ruling/src/test/expected/jquery/css-S4664.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

its/ruling/src/test/expected/jquery/css-S4666.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

its/ruling/src/test/expected/jquery/css-S4667.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

its/ruling/src/test/expected/prototype/css-S125.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

its/ruling/src/test/expected/prototype/css-S4658.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

its/ruling/src/test/expected/prototype/css-S4664.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

its/ruling/src/test/expected/prototype/css-S7924.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/css/src/analysis/analysis.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,19 @@
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
1717
import type { AnalysisInput, AnalysisOutput } from '../../../shared/src/types/analysis.js';
18-
import type { RuleConfig } from '../linter/config.js';
1918
import type { CssIssue } from '../linter/issues/issue.js';
19+
import type { FileType } from '../../../shared/src/helpers/files.js';
2020

2121
/**
22-
* A CSS analysis input
22+
* A CSS analysis input.
2323
*
24-
* A CSS analysis input only needs an input file and a set
25-
* of rule configurations to analyze a stylesheet.
24+
* CSS analysis uses the global linter configuration initialized by
25+
* `LinterWrapper.initialize()` in project analysis.
2626
*
27-
* When `rules` are provided (bridge per-request path), a fresh config is created.
28-
* When `rules` are absent (analyzeProject path), the linter must be pre-initialized.
29-
*
30-
* @param rules the rules from the active quality profile (optional when linter is pre-initialized)
27+
* For TEST files, rules are overridden to an empty set internally.
3128
*/
3229
export interface CssAnalysisInput extends AnalysisInput {
33-
rules?: RuleConfig[];
34-
fileType?: string;
30+
fileType?: FileType;
3531
}
3632

3733
/**
@@ -60,20 +56,12 @@ export interface CssSyntaxHighlight {
6056
/**
6157
* Metrics computed from a CSS source file.
6258
*
63-
* CSS files have limited metric semantics compared to JS/TS, so
64-
* functions, statements, classes, complexity, and cognitiveComplexity
65-
* are always 0. The primary metrics are ncloc and commentLines.
59+
* CSS metrics only include line-based metrics and NOSONAR locations.
6660
*/
6761
export interface CssMetrics {
68-
ncloc: number[];
69-
commentLines: number[];
62+
ncloc?: number[];
63+
commentLines?: number[];
7064
nosonarLines: number[];
71-
executableLines: number[];
72-
functions: number;
73-
statements: number;
74-
classes: number;
75-
complexity: number;
76-
cognitiveComplexity: number;
7765
}
7866

7967
/**

packages/css/src/analysis/analyzer.ts

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,17 @@
1414
* You should have received a copy of the Sonar Source-Available License
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
17-
import type { LinterOptions } from 'stylelint';
1817
import type { CssAnalysisInput, CssAnalysisOutput } from './analysis.js';
1918
import { linter } from '../linter/wrapper.js';
20-
import { createStylelintConfig } from '../linter/config.js';
2119
import { computeMetrics } from './metrics.js';
2220
import { computeHighlighting } from './highlighting.js';
2321
import { APIError } from '../../../shared/src/errors/error.js';
2422
import {
2523
toProjectFailureResult,
2624
type ProjectFailureResult,
2725
} from '../../../shared/src/errors/project-analysis.js';
28-
import { error, warn } from '../../../shared/src/helpers/logging.js';
26+
import { warn } from '../../../shared/src/helpers/logging.js';
2927
import type { CssIssue } from '../linter/issues/issue.js';
30-
import {
31-
shouldIgnoreFile,
32-
type ShouldIgnoreFileParams,
33-
} from '../../../shared/src/helpers/filter/filter.js';
34-
import { isAlsoCssFile } from '../../../shared/src/helpers/configuration.js';
3528

3629
/**
3730
* Analyzes a CSS analysis input
@@ -42,73 +35,80 @@ import { isAlsoCssFile } from '../../../shared/src/helpers/configuration.js';
4235
*
4336
* The input must be fully sanitized (all fields required) before calling this function.
4437
*
45-
* When `input.rules` is provided (bridge per-request path), a fresh Stylelint
46-
* config is created from them. When absent (analyzeProject path), the linter's
47-
* pre-initialized config is used instead (see `LinterWrapper.initialize()`).
38+
* Stylelint config comes from the pre-initialized linter
39+
* (`LinterWrapper.initialize()`). For TEST files, rules are overridden to an
40+
* empty config to suppress issues while preserving parsing/highlighting behavior.
41+
* The CSS linter must be initialized before calling this function.
42+
*
43+
* Behavior:
44+
*
45+
* CSS in HTML/Vue MAIN: linted for issues, no CSS metrics.
46+
* CSS in HTML/Vue TEST: not linted (noMetrics + TEST early return), so no CSS issues.
47+
* Pure CSS MAIN: issues + metrics/highlighting.
48+
* Pure CSS TEST: no issues/metrics, highlighting only
4849
*
4950
* @param input the sanitized CSS analysis input to analyze
50-
* @param shouldIgnoreParams parameters needed to determine whether a file should be ignored
51+
* @param includeMetrics whether to include metrics calculation
5152
* @returns a promise of the CSS analysis output
5253
*/
5354
export async function analyzeCSS(
5455
input: CssAnalysisInput,
55-
shouldIgnoreParams: ShouldIgnoreFileParams,
56+
includeMetrics = true,
5657
): Promise<CssAnalysisOutput> {
57-
const { filePath, fileContent, rules, fileType } = input;
58-
if (await shouldIgnoreFile({ filePath, fileContent }, shouldIgnoreParams)) {
59-
return { issues: [] };
60-
}
58+
const { filePath, fileContent, fileType } = input;
6159

6260
const isTestFile = fileType === 'TEST';
63-
const sanitizedCode = fileContent.replaceAll(/[\u2000-\u200F]/g, ' ');
64-
65-
// If rules are provided explicitly (bridge path), create a fresh config.
66-
// Otherwise, use the linter's pre-initialized config (analyzeProject path).
67-
const config = rules ? createStylelintConfig(rules) : undefined;
6861

69-
const options: LinterOptions = {
70-
code: sanitizedCode,
71-
codeFilename: filePath,
72-
...(config && { config }),
73-
};
62+
// Mixed-file CSS analysis (HTML/Vue) runs with noMetrics=true. For TEST files,
63+
// preserve legacy behavior by skipping CSS linting entirely.
64+
if (isTestFile && !includeMetrics) {
65+
return { issues: [] };
66+
}
67+
const sanitizedCode = fileContent.replaceAll(/[\u2000-\u200F]/g, ' ');
7468

75-
// TEST files only get highlighting (matching old CssMetricSensor behavior).
76-
// Old CssRuleSensor never analyzed TEST files for issues, but we still
77-
// need to run Stylelint to get the PostCSS root for highlighting.
78-
const { issues, root } = await linter.lint(filePath, options).catch(err => {
79-
error(`Linter failed to parse file ${filePath}: ${err}`);
80-
throw APIError.linterError(`Linter failed to parse file ${filePath}: ${err}`);
81-
});
82-
throwIfCssParsingError(issues);
69+
// TEST files keep highlighting (parity with old CssMetricSensor), but issues remain suppressed.
70+
const lintResult = await linter.lint(filePath, sanitizedCode, fileType);
71+
const { root, issues: lintingIssues } = lintResult;
72+
throwIfCssParsingError(lintingIssues);
73+
const issues = isTestFile ? [] : lintingIssues;
8374

84-
// Skip metrics and highlighting in SonarLint mode and for non-pure-CSS files
75+
// Skip metrics and highlighting for non-pure-CSS files
8576
// (HTML/Vue files are handled by their own analyzers for metrics)
86-
if (input.sonarlint || isAlsoCssFile(filePath) || !root) {
87-
return { issues: isTestFile ? [] : issues };
77+
if (!includeMetrics || !root) {
78+
return { issues };
8879
}
8980

9081
try {
91-
const highlights = computeHighlighting(root, sanitizedCode);
92-
if (isTestFile) {
93-
return { issues: [], highlights };
82+
if (input.sonarlint) {
83+
const metrics = computeMetrics(root);
84+
// In SonarLint context, keep only NOSONAR lines (parity with JS/TS and old sensors).
85+
return {
86+
issues,
87+
metrics: { nosonarLines: metrics.nosonarLines },
88+
};
89+
} else {
90+
const highlights = computeHighlighting(root, sanitizedCode);
91+
if (isTestFile) {
92+
return { issues, highlights };
93+
}
94+
return {
95+
issues,
96+
highlights,
97+
metrics: computeMetrics(root),
98+
};
9499
}
95-
return {
96-
issues,
97-
highlights,
98-
metrics: computeMetrics(root),
99-
};
100100
} catch (err) {
101101
warn(`Failed to compute metrics/highlighting for ${filePath}: ${err}`);
102-
return { issues: isTestFile ? [] : issues };
102+
return { issues };
103103
}
104104
}
105105

106106
export async function analyzeCSSProject(
107107
input: CssAnalysisInput,
108-
shouldIgnoreParams: ShouldIgnoreFileParams,
108+
includeMetrics = true,
109109
): Promise<CssAnalysisOutput | ProjectFailureResult> {
110110
try {
111-
return await analyzeCSS(input, shouldIgnoreParams);
111+
return await analyzeCSS(input, includeMetrics);
112112
} catch (err) {
113113
return toProjectFailureResult(err, 'css');
114114
}

packages/css/src/analysis/metrics.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,5 @@ export function computeMetrics(root: Root | Document): CssMetrics {
8383
ncloc: Array.from(codeLines).sort((a, b) => a - b),
8484
commentLines: Array.from(commentCandidates).sort((a, b) => a - b),
8585
nosonarLines: nosonarLines.sort((a, b) => a - b),
86-
executableLines: [],
87-
functions: 0,
88-
statements: 0,
89-
classes: 0,
90-
complexity: 0,
91-
cognitiveComplexity: 0,
9286
};
9387
}

0 commit comments

Comments
 (0)