Skip to content

Commit

Permalink
Support suppressed lint message (#163)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
Affankhushnod1994 and akhushnood committed Mar 19, 2024
1 parent 3789a9a commit a05ccf3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 3 deletions.
17 changes: 16 additions & 1 deletion sample/eslint/eslint-output.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
"filePath": "C:\\src\\github.com\\codeleague\\codecoach\\src\\app.constants.ts",
"messages": [],
"suppressedMessages": [],
"errorCount": 0,
"warningCount": 0,
"fixableErrorCount": 0,
Expand Down Expand Up @@ -31,11 +32,25 @@
"endColumn": 30
}
],
"suppressedMessages": [
{
"ruleId": "@typescript-eslint/no-unused-vars",
"severity": 1,
"message": "'supContent' is defined but never used.",
"line": 30,
"column": 10,
"nodeType": "Identifier",
"messageId": "unusedVar",
"endLine": 30,
"endColumn": 30,
"suppressions": [{ "kind": "directive", "justification": "" }]
}
],
"errorCount": 1,
"warningCount": 1,
"fixableErrorCount": 0,
"fixableWarningCount": 0,
"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(",
"usedDeprecatedRules": []
}
]
]
2 changes: 2 additions & 0 deletions src/Parser/@types/ESLintLog.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { ESLintIssue } from './ESLintIssue';
import { SuppressedESLintIssue } from './SuppressedESLintIssue';

export type ESLintLog = {
filePath: string;
messages: ESLintIssue[];
suppressedMessages?: SuppressedESLintIssue[];
errorCount: number;
warningCount: number;
fixableErrorCount: number;
Expand Down
6 changes: 6 additions & 0 deletions src/Parser/@types/SuppressedESLintIssue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ESLintIssue } from './ESLintIssue';
import { SuppressionInfo } from './SuprressionInfo';

export type SuppressedESLintIssue = ESLintIssue & {
suppressions: SuppressionInfo[];
};
4 changes: 4 additions & 0 deletions src/Parser/@types/SuprressionInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type SuppressionInfo = {
kind: string;
justification: string;
};
40 changes: 38 additions & 2 deletions src/Parser/ESLintParser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('ESLintParser', () => {
column: 8,
},
],
suppressedMessages: [],
errorCount: 1,
warningCount: 0,
fixableErrorCount: 0,
Expand All @@ -38,6 +39,19 @@ describe('ESLintParser', () => {
endColumn: 30,
},
],
suppressedMessages: [
{
ruleId: '@typescript-eslint/no-unused-vars',
severity: 1,
message: "'content' is defined but never used.",
line: 24,
column: 15,
nodeType: 'Identifier',
messageId: 'unusedVar',
endLine: 24,
endColumn: 30,
},
],
errorCount: 1,
warningCount: 1,
fixableErrorCount: 0,
Expand All @@ -51,7 +65,7 @@ describe('ESLintParser', () => {

it('Should parse correctly', () => {
const result = new ESLintParser(cwd).parse(mockedContentString);
expect(result).toHaveLength(2);
expect(result).toHaveLength(3);

expect(result[0]).toEqual({
ruleId: '',
Expand All @@ -76,6 +90,18 @@ describe('ESLintParser', () => {
valid: true,
type: 'eslint',
});

expect(result[2]).toEqual({
ruleId: '@typescript-eslint/no-unused-vars',
source: `src/app.ts`,
severity: LintSeverity.ignore,
line: 24,
lineOffset: 15,
msg: `'content' is defined but never used.`,
log: JSON.stringify({ ...mockedContent[1].messages[0], severity: 0 }),
valid: true,
type: 'eslint',
});
});

it('Should do nothing if put empty string', () => {
Expand All @@ -87,10 +113,20 @@ describe('ESLintParser', () => {
const result = new ESLintParser(cwd).parse(mockedContentString);
const valid = result.filter((el) => el.valid);
const invalid = result.filter((el) => !el.valid);
expect(valid).toHaveLength(1);
expect(valid).toHaveLength(2);
expect(invalid).toHaveLength(1);
});

it('Should parse with severity correctly', () => {
const result = new ESLintParser(cwd).parse(mockedContentString);
const resultWithError = result.filter((el) => el.severity === LintSeverity.error);
const resultWithWarning = result.filter((el) => el.severity === LintSeverity.warning);
const ignoredResult = result.filter((el) => el.severity === LintSeverity.ignore);
expect(resultWithError).toHaveLength(1);
expect(resultWithWarning).toHaveLength(1);
expect(ignoredResult).toHaveLength(1);
});

it('Should throw error if the line not match the rule', () => {
expect(() => new ESLintParser(cwd).parse(':')).toThrow();
});
Expand Down
12 changes: 12 additions & 0 deletions src/Parser/ESLintParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ export class ESLintParser extends Parser {
const logs = JSON.parse(content) as ESLintLog[];
return logs
.filter((log) => log.messages.length !== 0)
.concat(
logs
.filter((log) => log.suppressedMessages?.length !== 0)
.map((log) => {
const messages =
log.suppressedMessages?.map((msg) => ({
...msg,
severity: 0,
})) ?? [];
return { ...log, messages: messages };
}),
)
.flatMap((log) => {
const source = getRelativePath(this.cwd, log.filePath);
return log.messages.map((msg) => ESLintParser.toLintItem(msg, source));
Expand Down

0 comments on commit a05ccf3

Please sign in to comment.