Skip to content

Commit da0f473

Browse files
authored
JS-548 Make parser and parserOptions visible in rules (#5094)
1 parent f80b013 commit da0f473

45 files changed

Lines changed: 294 additions & 318 deletions

Some content is hidden

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

its/ruling/src/test/expected/jsts/ant-design/typescript-S1537.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,6 @@
11631163
269
11641164
],
11651165
"ant-design:components/locale-provider/LocaleReceiver.tsx": [
1166-
15,
11671166
19,
11681167
33,
11691168
54,
@@ -3198,7 +3197,6 @@
31983197
],
31993198
"ant-design:components/transfer/list.tsx": [
32003199
15,
3201-
81,
32023200
87,
32033201
99,
32043202
121,

its/ruling/src/test/expected/jsts/eigen/typescript-S1537.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13496,7 +13496,6 @@
1349613496
],
1349713497
"eigen:src/palette/elements/Select/Select.tsx": [
1349813498
12,
13499-
46,
1350013499
64,
1350113500
149,
1350213501
219,
@@ -13511,10 +13510,6 @@
1351113510
204,
1351213511
302
1351313512
],
13514-
"eigen:src/palette/elements/Select/index.tsx": [
13515-
18,
13516-
22
13517-
],
1351813513
"eigen:src/palette/elements/Separator/Separator.tsx": [
1351913514
21
1352013515
],
@@ -13749,7 +13744,6 @@
1374913744
232
1375013745
],
1375113746
"eigen:src/storybook/helpers.tsx": [
13752-
5,
1375313747
9,
1375413748
26,
1375513749
28,

packages/html/tests/builder/build.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import { embeddedInput } from '../../../jsts/tests/tools/helpers/input.js';
1919
import { describe, it } from 'node:test';
2020
import { expect } from 'expect';
2121
import { parseHTML } from '../../src/parser/parse.js';
22-
import { buildSourceCodes } from '../../../jsts/src/embedded/builder/build.js';
22+
import { build } from '../../../jsts/src/embedded/builder/build.js';
2323

2424
describe('buildSourceCodes()', () => {
2525
const fixturesPath = join(import.meta.dirname, 'fixtures');
2626
it('should build source codes from an HTML file', async () => {
2727
const filePath = join(fixturesPath, 'multiple.html');
28-
const sourceCodes = buildSourceCodes(await embeddedInput({ filePath }), parseHTML);
28+
const sourceCodes = build(await embeddedInput({ filePath }), parseHTML);
2929
expect(sourceCodes).toHaveLength(2);
3030
expect(sourceCodes[0].sourceCode.ast.loc.start).toEqual({ line: 4, column: 8 });
3131
expect(sourceCodes[1].sourceCode.ast.loc.start).toEqual({ line: 8, column: 8 });

packages/jsts/src/analysis/analyzer.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { JsTsAnalysisInput, JsTsAnalysisOutput } from './analysis.js';
2020
import type { TSESTree } from '@typescript-eslint/utils';
2121
import { JsTsLanguage } from '../../../shared/src/helpers/language.js';
2222
import { getLinter } from '../linter/linters.js';
23-
import { buildSourceCode } from '../builders/build.js';
23+
import { build } from '../builders/build.js';
2424
import { LinterWrapper } from '../linter/wrapper.js';
2525
import { APIError } from '../../../shared/src/errors/error.js';
2626
import { serializeInProtobuf } from '../parsers/ast.js';
@@ -31,6 +31,7 @@ import { getSyntaxHighlighting } from '../linter/visitors/syntax-highlighting.js
3131
import { getCpdTokens } from '../linter/visitors/cpd.js';
3232
import { clearDependenciesCache, getAllDependencies } from '../rules/index.js';
3333
import { Telemetry } from '../../../bridge/src/request.js';
34+
import { ParseResult } from '../parsers/parse.js';
3435

3536
/**
3637
* Analyzes a JavaScript / TypeScript analysis input
@@ -51,7 +52,7 @@ import { Telemetry } from '../../../bridge/src/request.js';
5152
export function analyzeJSTS(input: JsTsAnalysisInput, language: JsTsLanguage): JsTsAnalysisOutput {
5253
debug(`Analyzing file "${input.filePath}" with linterId "${input.linterId}"`);
5354
const linter = getLinter(input.linterId);
54-
return analyzeFile(linter, input, buildSourceCode(input, language));
55+
return analyzeFile(linter, input, build(input, language));
5556
}
5657

5758
/**
@@ -63,26 +64,26 @@ export function analyzeJSTS(input: JsTsAnalysisInput, language: JsTsLanguage): J
6364
*
6465
* @param linter the linter to use for the analysis
6566
* @param input the JavaScript / TypeScript analysis input to analyze
66-
* @param sourceCode the corresponding parsed ESLint SourceCode instance
67+
* @param parseResult the corresponding parsing result containing the SourceCode instance
6768
* @returns the JavaScript / TypeScript analysis output
6869
*/
6970
function analyzeFile(
7071
linter: LinterWrapper,
7172
input: JsTsAnalysisInput,
72-
sourceCode: SourceCode,
73+
parseResult: ParseResult,
7374
): JsTsAnalysisOutput {
7475
try {
7576
const { filePath, fileType, language, shouldClearDependenciesCache } = input;
7677
shouldClearDependenciesCache && clearDependenciesCache();
7778
const { issues, highlightedSymbols, cognitiveComplexity, ucfgPaths } = linter.lint(
78-
sourceCode,
79+
parseResult,
7980
filePath,
8081
fileType,
8182
language,
8283
);
8384
const extendedMetrics = computeExtendedMetrics(
8485
input,
85-
sourceCode,
86+
parseResult.sourceCode,
8687
highlightedSymbols,
8788
cognitiveComplexity,
8889
);
@@ -94,7 +95,7 @@ function analyzeFile(
9495
};
9596

9697
if (!input.skipAst) {
97-
const ast = serializeAst(sourceCode, filePath);
98+
const ast = serializeAst(parseResult.sourceCode, filePath);
9899
if (ast) {
99100
result.ast = ast;
100101
}

packages/jsts/src/builders/build.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import { debug } from '../../../shared/src/helpers/logging.js';
1818
import { JsTsAnalysisInput } from '../analysis/analysis.js';
1919
import { buildParserOptions } from '../parsers/options.js';
20-
import { parseForESLint } from '../parsers/parse.js';
21-
import { parsers } from '../parsers/eslint.js';
20+
import { parse } from '../parsers/parse.js';
21+
import { Parser, parsersMap } from '../parsers/eslint.js';
2222
import { getProgramById } from '../program/program.js';
2323
import { Linter } from 'eslint';
2424
import { JsTsLanguage } from '../../../shared/src/helpers/language.js';
@@ -34,59 +34,59 @@ import { getContext } from '../../../shared/src/helpers/context.js';
3434
* @param language the language of the input
3535
* @returns the parsed source code
3636
*/
37-
export function buildSourceCode(input: JsTsAnalysisInput, language: JsTsLanguage) {
37+
export function build(input: JsTsAnalysisInput, language: JsTsLanguage) {
3838
const vueFile = isVueFile(input.filePath);
3939

40+
let parser: Parser = vueFile ? parsersMap.vuejs : parsersMap.typescript;
4041
if (shouldUseTypescriptParser(language)) {
4142
const options: Linter.ParserOptions = {
4243
// enable logs for @typescript-eslint
4344
// debugLevel: true,
4445
filePath: input.filePath,
45-
parser: vueFile ? parsers.typescript : undefined,
46+
parser: vueFile ? parsersMap.typescript : undefined,
4647
};
47-
const parser = vueFile ? parsers.vuejs : parsers.typescript;
4848
if (!vueFile) {
4949
options.programs = input.programId && [getProgramById(input.programId)];
5050
options.project = input.tsConfigs;
5151
}
5252
try {
53-
debug(`Parsing ${input.filePath} with ${parser.parser}`);
54-
return parseForESLint(input.fileContent, parser.parse, buildParserOptions(options, false));
53+
debug(`Parsing ${input.filePath} with ${parser.meta.name}`);
54+
return parse(input.fileContent, parser, buildParserOptions(options, false));
5555
} catch (error) {
56-
debug(`Failed to parse ${input.filePath} with TypeScript parser: ${error.message}`);
56+
debug(`Failed to parse ${input.filePath} with ${parser.meta.name}: ${error.message}`);
5757
if (language === 'ts') {
5858
throw error;
5959
}
6060
}
6161
}
6262

6363
let moduleError;
64+
parser = vueFile ? parsersMap.vuejs : parsersMap.javascript;
6465
try {
65-
const parser = vueFile ? parsers.vuejs : parsers.javascript;
66-
debug(`Parsing ${input.filePath} with ${parser.parser}`);
67-
return parseForESLint(
66+
debug(`Parsing ${input.filePath} with ${parser.meta?.name}`);
67+
return parse(
6868
input.fileContent,
69-
parser.parse,
70-
buildParserOptions({ parser: vueFile ? parsers.javascript : undefined }, true),
69+
parser,
70+
buildParserOptions({ parser: vueFile ? parsersMap.javascript : undefined }, true),
7171
);
7272
} catch (error) {
73-
debug(`Failed to parse ${input.filePath} with Javascript parser: ${error.message}`);
73+
debug(`Failed to parse ${input.filePath} with ${parser.meta?.name}: ${error.message}`);
7474
if (vueFile) {
7575
throw error;
7676
}
7777
moduleError = error;
7878
}
7979

8080
try {
81-
debug(`Parsing ${input.filePath} with Javascript parser in 'script' mode`);
82-
return parseForESLint(
81+
debug(`Parsing ${input.filePath} with ${parsersMap.javascript.meta?.name} in 'script' mode`);
82+
return parse(
8383
input.fileContent,
84-
parsers.javascript.parse,
84+
parsersMap.javascript,
8585
buildParserOptions({ sourceType: 'script' }, true),
8686
);
8787
} catch (error) {
8888
debug(
89-
`Failed to parse ${input.filePath} with Javascript parser in 'script' mode: ${error.message}`,
89+
`Failed to parse ${input.filePath} with ${parsersMap.javascript.meta?.name} in 'script' mode: ${error.message}`,
9090
);
9191
/**
9292
* We prefer displaying parsing error as module if parsing as script also failed,

packages/jsts/src/embedded/analysis/analyzer.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { getLinter } from '../../linter/linters.js';
2121
import type { LinterWrapper } from '../../linter/wrapper.js';
2222
import { EmbeddedAnalysisInput, EmbeddedAnalysisOutput } from './analysis.js';
2323
import { findNcloc } from '../../linter/visitors/metrics/ncloc.js';
24-
import { buildSourceCodes, ExtendedSourceCode, LanguageParser } from '../builder/build.js';
24+
import { build, ExtendedParseResult, LanguageParser } from '../builder/build.js';
2525
import { debug } from '../../../../shared/src/helpers/logging.js';
2626

2727
/**
@@ -51,25 +51,25 @@ export function analyzeEmbedded(
5151
): EmbeddedAnalysisOutput {
5252
debug(`Analyzing file "${input.filePath}" with linterId "${input.linterId}"`);
5353
const linter = getLinter(input.linterId);
54-
const extendedSourceCodes = buildSourceCodes(input, languageParser);
55-
return analyzeFile(linter, extendedSourceCodes);
54+
const extendedParseResults = build(input, languageParser);
55+
return analyzeFile(linter, extendedParseResults);
5656
}
5757

5858
/**
5959
* Extracted logic from analyzeEmbedded() so we can compute metrics
6060
*
6161
* @param linter
62-
* @param extendedSourceCodes
62+
* @param extendedParseResults
6363
* @returns
6464
*/
65-
function analyzeFile(linter: LinterWrapper, extendedSourceCodes: ExtendedSourceCode[]) {
65+
function analyzeFile(linter: LinterWrapper, extendedParseResults: ExtendedParseResult[]) {
6666
const aggregatedIssues: Issue[] = [];
6767
const aggregatedUcfgPaths: string[] = [];
6868
let ncloc: number[] = [];
69-
for (const extendedSourceCode of extendedSourceCodes) {
70-
const { issues, ucfgPaths, ncloc: singleNcLoc } = analyzeSnippet(linter, extendedSourceCode);
69+
for (const extendedParseResult of extendedParseResults) {
70+
const { issues, ucfgPaths, ncloc: singleNcLoc } = analyzeSnippet(linter, extendedParseResult);
7171
ncloc = ncloc.concat(singleNcLoc);
72-
const filteredIssues = removeNonJsIssues(extendedSourceCode.sourceCode, issues);
72+
const filteredIssues = removeNonJsIssues(extendedParseResult.sourceCode, issues);
7373
aggregatedIssues.push(...filteredIssues);
7474
aggregatedUcfgPaths.push(...ucfgPaths);
7575
}
@@ -79,13 +79,13 @@ function analyzeFile(linter: LinterWrapper, extendedSourceCodes: ExtendedSourceC
7979
metrics: { ncloc },
8080
};
8181

82-
function analyzeSnippet(linter: LinterWrapper, extendedSourceCode: ExtendedSourceCode) {
82+
function analyzeSnippet(linter: LinterWrapper, extendedParseResult: ExtendedParseResult) {
8383
const { issues, ucfgPaths } = linter.lint(
84-
extendedSourceCode.sourceCode,
85-
extendedSourceCode.syntheticFilePath,
84+
extendedParseResult,
85+
extendedParseResult.syntheticFilePath,
8686
'MAIN',
8787
);
88-
const ncloc = findNcloc(extendedSourceCode.sourceCode);
88+
const ncloc = findNcloc(extendedParseResult.sourceCode);
8989
return { issues, ucfgPaths, ncloc };
9090
}
9191

packages/jsts/src/embedded/builder/build.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,15 @@
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 { SourceCode } from 'eslint';
1817
import { patchParsingError, patchSourceCode } from './patch.js';
1918
import path from 'path';
2019
import { EmbeddedJS } from '../analysis/embedded-js.js';
2120
import { EmbeddedAnalysisInput } from '../analysis/analysis.js';
2221
import { JsTsAnalysisInput } from '../../analysis/analysis.js';
23-
import { buildSourceCode } from '../../builders/build.js';
22+
import { build as buildJsTs } from '../../builders/build.js';
23+
import { ParseResult } from '../../parsers/parse.js';
2424

25-
export type ExtendedSourceCode = {
26-
sourceCode: SourceCode;
25+
export type ExtendedParseResult = ParseResult & {
2726
syntheticFilePath: string;
2827
};
2928
export type LanguageParser = (text: string) => EmbeddedJS[];
@@ -37,12 +36,12 @@ export type LanguageParser = (text: string) => EmbeddedJS[];
3736
* If there is at least one parsing error in any snippet, we return only the first error and
3837
* we don't even consider any parsing errors in the remaining snippets for simplicity.
3938
*/
40-
export function buildSourceCodes(
39+
export function build(
4140
input: EmbeddedAnalysisInput,
4241
languageParser: LanguageParser,
43-
): ExtendedSourceCode[] {
42+
): ExtendedParseResult[] {
4443
const embeddedJSs: EmbeddedJS[] = languageParser(input.fileContent);
45-
const extendedSourceCodes: ExtendedSourceCode[] = [];
44+
const extendedParseResults: ExtendedParseResult[] = [];
4645
for (const embeddedJS of embeddedJSs) {
4746
const { code } = embeddedJS;
4847

@@ -62,22 +61,24 @@ export function buildSourceCodes(
6261
fileType: 'MAIN',
6362
} as JsTsAnalysisInput;
6463
try {
65-
const extendedSourceCode = {
66-
sourceCode: patchSourceCode(buildSourceCode(jsTsAnalysisInput, 'js'), embeddedJS),
64+
const parseResult = buildJsTs(jsTsAnalysisInput, 'js');
65+
extendedParseResults.push({
66+
sourceCode: patchSourceCode(parseResult.sourceCode, embeddedJS),
67+
parser: parseResult.parser,
68+
parserOptions: parseResult.parserOptions,
6769
syntheticFilePath,
68-
};
69-
extendedSourceCodes.push(extendedSourceCode);
70+
});
7071
} catch (error) {
7172
throw patchParsingError(error, embeddedJS);
7273
}
7374
}
74-
return extendedSourceCodes;
75+
return extendedParseResults;
7576
}
7677

7778
/**
7879
* Returns the filename composed as following:
7980
*
80-
* {filepath-without-extention}-{resourceName}{filepath-extension}
81+
* {filepath-without-extension}-{resourceName}{filepath-extension}
8182
*/
8283
export function composeSyntheticFilePath(filePath: string, resourceName: string): string {
8384
const { dir, name, ext } = path.parse(filePath);

0 commit comments

Comments
 (0)