Skip to content

Commit a05ccf3

Browse files
Affankhushnod1994akhushnood
andauthored
Support suppressed lint message (#163)
* Bump ESLint version * Add logic to add ESLint SuppresedLintMessage * revert eslint version * Map SuppressedMessages to messages with severity = 0 * Make SuppressedMessages in ESLintLog optional. * Add Unit Test for parsing severity and fix import in ESLintParser.ts --------- Co-authored-by: akhushnood <affan.khushnood@agoda.com>
1 parent 3789a9a commit a05ccf3

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

sample/eslint/eslint-output.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
"filePath": "C:\\src\\github.com\\codeleague\\codecoach\\src\\app.constants.ts",
44
"messages": [],
5+
"suppressedMessages": [],
56
"errorCount": 0,
67
"warningCount": 0,
78
"fixableErrorCount": 0,
@@ -31,11 +32,25 @@
3132
"endColumn": 30
3233
}
3334
],
35+
"suppressedMessages": [
36+
{
37+
"ruleId": "@typescript-eslint/no-unused-vars",
38+
"severity": 1,
39+
"message": "'supContent' is defined but never used.",
40+
"line": 30,
41+
"column": 10,
42+
"nodeType": "Identifier",
43+
"messageId": "unusedVar",
44+
"endLine": 30,
45+
"endColumn": 30,
46+
"suppressions": [{ "kind": "directive", "justification": "" }]
47+
}
48+
],
3449
"errorCount": 1,
3550
"warningCount": 1,
3651
"fixableErrorCount": 0,
3752
"fixableWarningCount": 0,
3853
"source": "#!/usr/bin/env node\r\n\r\nimport { Config, ProjectType } from './Config';\r\nimport { File } from './File';\r\nimport { Log } from './Logger';\r\nimport { CSharpParser, LintItem, Parser, TSLintParser } from './Parser';\r\nimport { GitHub, GitHubPRService, VCS } from './Provider';\r\n\r\nclass App {\r\n private readonly parser: Parser;\r\n private readonly vcs: VCS\r\n\r\n constructor() {\r\n this.parser = App.setProjectType(Config.app.projectType);\r\n const githubPRService = new GitHubPRService(\r\n Config.provider.token,\r\n Config.provider.repoUrl,\r\n Config.provider.prId,\r\n );\r\n this.vcs = new GitHub(githubPRService);\r\n }\r\n\r\n async start() {\r\n const logs = await this.parseBuildData(Config.app.buildLogFiles);\r\n Log.info('Build data parsing completed');\r\n\r\n await this.vcs.report(logs);\r\n Log.info('Report to VCS completed');\r\n\r\n await App.writeLogToFile(logs);\r\n Log.info('Write output completed');\r\n }\r\n\r\n private static setProjectType(type: ProjectType): Parser {\r\n switch (type) {\r\n case ProjectType.csharp:\r\n return new CSharpParser(Config.app.cwd);\r\n case ProjectType.tslint:\r\n return new TSLintParser(Config.app.cwd);\r\n }\r\n }\r\n\r\n private async parseBuildData(files: string[]): Promise<LintItem[]> {\r\n const parserTasks = files.map(async (file) => {\r\n const content = await File.readFileHelper(file);\r\n this.parser.withContent(content);\r\n });\r\n\r\n await Promise.all(parserTasks);\r\n\r\n return this.parser.getLogs();\r\n }\r\n\r\n private static async writeLogToFile(items: LintItem[]): Promise<void> {\r\n await File.writeFileHelper(Config.app.logFilePath, JSON.stringify(logs, null, 2));\r\n }\r\n}\r\n\r\nnew App(",
3954
"usedDeprecatedRules": []
4055
}
41-
]
56+
]

src/Parser/@types/ESLintLog.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { ESLintIssue } from './ESLintIssue';
2+
import { SuppressedESLintIssue } from './SuppressedESLintIssue';
23

34
export type ESLintLog = {
45
filePath: string;
56
messages: ESLintIssue[];
7+
suppressedMessages?: SuppressedESLintIssue[];
68
errorCount: number;
79
warningCount: number;
810
fixableErrorCount: number;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { ESLintIssue } from './ESLintIssue';
2+
import { SuppressionInfo } from './SuprressionInfo';
3+
4+
export type SuppressedESLintIssue = ESLintIssue & {
5+
suppressions: SuppressionInfo[];
6+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type SuppressionInfo = {
2+
kind: string;
3+
justification: string;
4+
};

src/Parser/ESLintParser.spec.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('ESLintParser', () => {
1616
column: 8,
1717
},
1818
],
19+
suppressedMessages: [],
1920
errorCount: 1,
2021
warningCount: 0,
2122
fixableErrorCount: 0,
@@ -38,6 +39,19 @@ describe('ESLintParser', () => {
3839
endColumn: 30,
3940
},
4041
],
42+
suppressedMessages: [
43+
{
44+
ruleId: '@typescript-eslint/no-unused-vars',
45+
severity: 1,
46+
message: "'content' is defined but never used.",
47+
line: 24,
48+
column: 15,
49+
nodeType: 'Identifier',
50+
messageId: 'unusedVar',
51+
endLine: 24,
52+
endColumn: 30,
53+
},
54+
],
4155
errorCount: 1,
4256
warningCount: 1,
4357
fixableErrorCount: 0,
@@ -51,7 +65,7 @@ describe('ESLintParser', () => {
5165

5266
it('Should parse correctly', () => {
5367
const result = new ESLintParser(cwd).parse(mockedContentString);
54-
expect(result).toHaveLength(2);
68+
expect(result).toHaveLength(3);
5569

5670
expect(result[0]).toEqual({
5771
ruleId: '',
@@ -76,6 +90,18 @@ describe('ESLintParser', () => {
7690
valid: true,
7791
type: 'eslint',
7892
});
93+
94+
expect(result[2]).toEqual({
95+
ruleId: '@typescript-eslint/no-unused-vars',
96+
source: `src/app.ts`,
97+
severity: LintSeverity.ignore,
98+
line: 24,
99+
lineOffset: 15,
100+
msg: `'content' is defined but never used.`,
101+
log: JSON.stringify({ ...mockedContent[1].messages[0], severity: 0 }),
102+
valid: true,
103+
type: 'eslint',
104+
});
79105
});
80106

81107
it('Should do nothing if put empty string', () => {
@@ -87,10 +113,20 @@ describe('ESLintParser', () => {
87113
const result = new ESLintParser(cwd).parse(mockedContentString);
88114
const valid = result.filter((el) => el.valid);
89115
const invalid = result.filter((el) => !el.valid);
90-
expect(valid).toHaveLength(1);
116+
expect(valid).toHaveLength(2);
91117
expect(invalid).toHaveLength(1);
92118
});
93119

120+
it('Should parse with severity correctly', () => {
121+
const result = new ESLintParser(cwd).parse(mockedContentString);
122+
const resultWithError = result.filter((el) => el.severity === LintSeverity.error);
123+
const resultWithWarning = result.filter((el) => el.severity === LintSeverity.warning);
124+
const ignoredResult = result.filter((el) => el.severity === LintSeverity.ignore);
125+
expect(resultWithError).toHaveLength(1);
126+
expect(resultWithWarning).toHaveLength(1);
127+
expect(ignoredResult).toHaveLength(1);
128+
});
129+
94130
it('Should throw error if the line not match the rule', () => {
95131
expect(() => new ESLintParser(cwd).parse(':')).toThrow();
96132
});

src/Parser/ESLintParser.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ export class ESLintParser extends Parser {
1313
const logs = JSON.parse(content) as ESLintLog[];
1414
return logs
1515
.filter((log) => log.messages.length !== 0)
16+
.concat(
17+
logs
18+
.filter((log) => log.suppressedMessages?.length !== 0)
19+
.map((log) => {
20+
const messages =
21+
log.suppressedMessages?.map((msg) => ({
22+
...msg,
23+
severity: 0,
24+
})) ?? [];
25+
return { ...log, messages: messages };
26+
}),
27+
)
1628
.flatMap((log) => {
1729
const source = getRelativePath(this.cwd, log.filePath);
1830
return log.messages.map((msg) => ESLintParser.toLintItem(msg, source));

0 commit comments

Comments
 (0)