Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'severityOverride' option #725

Merged
merged 4 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,23 @@ These are the options available in the `bsconfig.json` file.
- A `string` value should be a relative-to-root-dir or absolute file path or glob pattern of the files that should be excluded. Any file matching this pattern will have all diagnostics supressed.
- A `number` value should be a diagnostic code. This will supress all diagnostics with that code for the whole project.
- An object can also be provided to filter specific diagnostic codes for a file pattern. For example,

```jsonc
"diagnosticFilters": [{
"src": "vendor/**/*",
"codes": [1000, 1011] //ignore these specific codes from vendor libraries
}]
```

- **severityOverride**: `Record<string | number, 'hint' | 'info' | 'warn' | 'error'>` - A map of error codes and severity levels, to override some diagnostics' severity; when a diagnostic generator doesn't offer enough control on an error's severity, this is a tool to work around blocking errors, or raise the level of other errors.

```jsonc
"severityOverride": {
1011: "error", //raise a warning to an error
"BSLINT1001": "warn" //oops we have lots of those to fix... later
}
```

- **diagnosticLevel**: `'hint' | 'info' | 'warn' | 'error'` - Specify what diagnostic levels are printed to the console. This has no effect on what diagnostics are reported in the LanguageServer. Defaults to 'warn'

- **autoImportComponentScript**: `bool` - BrighterScript only: will automatically import a script at transpile-time for a component with the same name if it exists.
Expand Down
10 changes: 10 additions & 0 deletions bsconfig.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@
]
}
},
"severityOverride": {
"description": "A map of error codes with their severity level override (error|warn|info)",
"type": "object",
"patternProperties": {
".{1,}": {
"type": ["number", "string"],
"enum": ["error", "warn", "info", "hint"]
}
}
},
"emitFullPaths": {
"description": "Emit full paths to files when printing diagnostics to the console.",
"type": "boolean",
Expand Down
5 changes: 5 additions & 0 deletions src/BsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ export interface BsConfig {
*/
ignoreErrorCodes?: (number | string)[];

/**
* A map of error codes with their severity level override (error|warn|info)
*/
severityOverride?: Record<number | string, 'error' | 'warn' | 'info' | 'hint'>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this diagnosticSeverityOverrides instead? Keeps it more in line with diagnosticFilters


/**
* Emit full paths to files when printing diagnostics to the console. Defaults to false
*/
Expand Down
53 changes: 53 additions & 0 deletions src/DiagnosticSeverityAdjuster.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { DiagnosticSeverity } from 'vscode-languageserver-protocol';
import { expect } from './chai-config.spec';

import { DiagnosticSeverityAdjuster } from './DiagnosticSeverityAdjuster';
import type { BsDiagnostic } from './interfaces';

describe('DiagnosticSeverityAdjuster', () => {
const adjuster = new DiagnosticSeverityAdjuster();

it('supports empty map', () => {
const actual = adjuster.createSeverityMap({});
expect(Array.from(actual.keys()).length === 0);
});

it('maps strings to enums', () => {
const actual = adjuster.createSeverityMap({
'a': 'error',
'b': 'warn',
'c': 'info',
1001: 'hint',
// @ts-expect-error using invalid key
'e': 'foo',
// @ts-expect-error using invalid key
'f': 42
});
expect(actual.get('a')).to.equal(DiagnosticSeverity.Error);
expect(actual.get('b')).to.equal(DiagnosticSeverity.Warning);
expect(actual.get('c')).to.equal(DiagnosticSeverity.Information);
expect(actual.get('1001')).to.equal(DiagnosticSeverity.Hint);
expect(actual.get('e')).to.equal(undefined);
expect(actual.get('f')).to.equal(undefined);
});

it('adjusts severity', () => {
const diagnostics = [
{
code: 'BSLINT1001',
severity: DiagnosticSeverity.Error
} as BsDiagnostic, {
code: 1001,
severity: DiagnosticSeverity.Error
} as BsDiagnostic
];
adjuster.adjust({
severityOverride: {
'BSLINT1001': 'warn',
1001: 'info'
}
}, diagnostics);
expect(diagnostics[0].severity).to.equal(DiagnosticSeverity.Warning);
expect(diagnostics[1].severity).to.equal(DiagnosticSeverity.Information);
});
});
38 changes: 38 additions & 0 deletions src/DiagnosticSeverityAdjuster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { DiagnosticSeverity } from 'vscode-languageserver-protocol';
import type { BsConfig } from './BsConfig';
import type { BsDiagnostic } from './interfaces';

export class DiagnosticSeverityAdjuster {
public adjust(options: BsConfig, diagnostics: BsDiagnostic[]): void {
const map = this.createSeverityMap(options.severityOverride);

diagnostics.forEach(diagnostic => {
const code = String(diagnostic.code);
if (map.has(code)) {
diagnostic.severity = map.get(code);
}
});
}

public createSeverityMap(severityOverride: BsConfig['severityOverride']): Map<string, DiagnosticSeverity> {
const map = new Map<string, DiagnosticSeverity>();
Object.keys(severityOverride).forEach(key => {
const value = severityOverride[key];
switch (value) {
case 'error':
map.set(key, DiagnosticSeverity.Error);
break;
case 'warn':
map.set(key, DiagnosticSeverity.Warning);
break;
case 'info':
map.set(key, DiagnosticSeverity.Information);
break;
case 'hint':
map.set(key, DiagnosticSeverity.Hint);
break;
}
});
return map;
}
}
7 changes: 7 additions & 0 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { rokuDeploy } from 'roku-deploy';
import type { Statement } from './parser/AstNode';
import { CallExpressionInfo } from './bscPlugin/CallExpressionInfo';
import { SignatureHelpUtil } from './bscPlugin/SignatureHelpUtil';
import { DiagnosticSeverityAdjuster } from './DiagnosticSeverityAdjuster';

const startOfSourcePkgPath = `source${path.sep}`;
const bslibNonAliasedRokuModulesPkgPath = s`source/roku_modules/rokucommunity_bslib/bslib.brs`;
Expand Down Expand Up @@ -102,6 +103,8 @@ export class Program {

private diagnosticFilterer = new DiagnosticFilterer();

private diagnosticAdjuster = new DiagnosticSeverityAdjuster();

/**
* A scope that contains all built-in global functions.
* All scopes should directly or indirectly inherit from this scope
Expand Down Expand Up @@ -288,6 +291,10 @@ export class Program {
return finalDiagnostics;
});

this.logger.time(LogLevel.debug, ['adjust diagnostics severity'], () => {
this.diagnosticAdjuster.adjust(this.options, diagnostics);
});

this.logger.info(`diagnostic counts: total=${chalk.yellow(diagnostics.length.toString())}, after filter=${chalk.yellow(filteredDiagnostics.length.toString())}`);
return filteredDiagnostics;
});
Expand Down
1 change: 1 addition & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export class Util {
config.retainStagingFolder = config.retainStagingDir;
config.copyToStaging = config.copyToStaging === false ? false : true;
config.ignoreErrorCodes = config.ignoreErrorCodes ?? [];
config.severityOverride = config.severityOverride ?? {};
config.diagnosticFilters = config.diagnosticFilters ?? [];
config.plugins = config.plugins ?? [];
config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
Expand Down