diff --git a/package-lock.json b/package-lock.json index b218a6d..e6d6b62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@types/node": "^14.6.0", "@typescript-eslint/eslint-plugin": "^3.10.1", "@typescript-eslint/parser": "^3.10.1", - "brighterscript": "^1.0.0-alpha.34", + "brighterscript": "^1.0.0-alpha.35", "chai": "^4.3.6", "coveralls-next": "^4.2.0", "eslint": "^7.7.0", @@ -359,9 +359,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -941,18 +941,6 @@ "node": ">=8" } }, - "node_modules/@rokucommunity/logger/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -1485,9 +1473,9 @@ } }, "node_modules/brighterscript": { - "version": "1.0.0-alpha.34", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-1.0.0-alpha.34.tgz", - "integrity": "sha512-txXLfB7/n9X7dl6s/QqJbbAcgHpeubxTFyTnOxzfc60BMMlKPNrB0j85/770MgJpTRzheRh2c93qdyVoyrTr0A==", + "version": "1.0.0-alpha.35", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-1.0.0-alpha.35.tgz", + "integrity": "sha512-pvMOPoCjMn+26FPAX48vCMbO7pr9HCIR7Vu68Q82rMWyi+K5Mpr8J6Or+puwUH6p9EGbGlzyCc7N6rnCBGfxTg==", "dev": true, "dependencies": { "@rokucommunity/bslib": "^0.1.1", @@ -1514,7 +1502,7 @@ "parse-ms": "^2.1.0", "readline": "^1.3.0", "require-relative": "^0.8.7", - "roku-deploy": "^3.12.0", + "roku-deploy": "^3.12.1", "serialize-error": "^7.0.1", "source-map": "^0.7.4", "thenby": "^1.3.4", @@ -4444,9 +4432,9 @@ } }, "node_modules/postman-request": { - "version": "2.88.1-postman.35", - "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.35.tgz", - "integrity": "sha512-fNkGBIA5+8I9zEA4HTphdaLHUtCRZsmWlp6Ow2fsm/8rVYVJVi/8S/sCmeit0YDnS6TL0EOwkk3WTfEqnsa2DA==", + "version": "2.88.1-postman.36", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.36.tgz", + "integrity": "sha512-frYz62rp/C9Ip+l0KrOuPuFfv9UhkczCUK6sITc+0AZ1z/8Lcr7brs8AQ38VjxBFmaEyL/ITjy6u0uHyFLV5RQ==", "dev": true, "dependencies": { "@postman/form-data": "~3.1.1", @@ -6059,9 +6047,9 @@ "dev": true }, "@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dev": true, "requires": { "regenerator-runtime": "^0.14.0" @@ -6522,12 +6510,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, @@ -6919,9 +6901,9 @@ } }, "brighterscript": { - "version": "1.0.0-alpha.34", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-1.0.0-alpha.34.tgz", - "integrity": "sha512-txXLfB7/n9X7dl6s/QqJbbAcgHpeubxTFyTnOxzfc60BMMlKPNrB0j85/770MgJpTRzheRh2c93qdyVoyrTr0A==", + "version": "1.0.0-alpha.35", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-1.0.0-alpha.35.tgz", + "integrity": "sha512-pvMOPoCjMn+26FPAX48vCMbO7pr9HCIR7Vu68Q82rMWyi+K5Mpr8J6Or+puwUH6p9EGbGlzyCc7N6rnCBGfxTg==", "dev": true, "requires": { "@rokucommunity/bslib": "^0.1.1", @@ -6948,7 +6930,7 @@ "parse-ms": "^2.1.0", "readline": "^1.3.0", "require-relative": "^0.8.7", - "roku-deploy": "^3.12.0", + "roku-deploy": "^3.12.1", "serialize-error": "^7.0.1", "source-map": "^0.7.4", "thenby": "^1.3.4", @@ -9153,9 +9135,9 @@ } }, "postman-request": { - "version": "2.88.1-postman.35", - "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.35.tgz", - "integrity": "sha512-fNkGBIA5+8I9zEA4HTphdaLHUtCRZsmWlp6Ow2fsm/8rVYVJVi/8S/sCmeit0YDnS6TL0EOwkk3WTfEqnsa2DA==", + "version": "2.88.1-postman.36", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.36.tgz", + "integrity": "sha512-frYz62rp/C9Ip+l0KrOuPuFfv9UhkczCUK6sITc+0AZ1z/8Lcr7brs8AQ38VjxBFmaEyL/ITjy6u0uHyFLV5RQ==", "dev": true, "requires": { "@postman/form-data": "~3.1.1", diff --git a/package.json b/package.json index 3b7a892..305b69a 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@types/node": "^14.6.0", "@typescript-eslint/eslint-plugin": "^3.10.1", "@typescript-eslint/parser": "^3.10.1", - "brighterscript": "^1.0.0-alpha.34", + "brighterscript": "^1.0.0-alpha.35", "chai": "^4.3.6", "coveralls-next": "^4.2.0", "eslint": "^7.7.0", diff --git a/src/createColorValidator.ts b/src/createColorValidator.ts index 542c200..26bb076 100644 --- a/src/createColorValidator.ts +++ b/src/createColorValidator.ts @@ -1,10 +1,10 @@ -import { BsDiagnostic, Range } from 'brighterscript'; +import { BsDiagnostic, Location } from 'brighterscript'; import { messages } from './plugins/codeStyle/diagnosticMessages'; import { BsLintRules, RuleColorFormat, RuleColorCase, RuleColorAlpha, RuleColorAlphaDefaults, RuleColorCertCompliant } from './index'; export function createColorValidator(severity: Readonly) { const { colorFormat, colorCase, colorAlpha, colorAlphaDefaults, colorCertCompliant } = severity; - return (text, range, diagnostics) => { + return (text: string, location: Location, diagnostics: BsDiagnostic[]) => { const len = text.length; if (len < 7 || len > 12) { // we're only interested in string length is between 7 (#EBEBEB) to 12 ("0xEBEBEBFF") chars long @@ -17,7 +17,7 @@ export function createColorValidator(severity: Readonly) { const quotedNumericHexMatches = (text.startsWith('0x') || text.startsWith('"0x')) ? text.match(quotedNumericHexRegex) : undefined; if ((colorFormat === 'never') && (quotedNumericHexMatches || hashHexMatches)) { - diagnostics.push(messages.expectedColorFormat(range)); + diagnostics.push(messages.expectedColorFormat(location)); return; } const hashHexAlphaRegex = /#[0-9A-Fa-f]{8}/g; @@ -25,60 +25,60 @@ export function createColorValidator(severity: Readonly) { if (colorFormat === 'hash-hex') { if (quotedNumericHexMatches) { - diagnostics.push(messages.expectedColorFormat(range)); + diagnostics.push(messages.expectedColorFormat(location)); } - validateColorCase(hashHexMatches, range, diagnostics, colorCase, colorFormat); - validateColorAlpha(text.match(hashHexAlphaRegex), hashHexMatches, quotedNumericHexMatches, range, diagnostics, colorAlpha, colorAlphaDefaults); - validateColorCertCompliance(hashHexMatches, range, diagnostics, colorFormat, colorCertCompliant); + validateColorCase(hashHexMatches, location, diagnostics, colorCase, colorFormat); + validateColorAlpha(text.match(hashHexAlphaRegex), hashHexMatches, quotedNumericHexMatches, location, diagnostics, colorAlpha, colorAlphaDefaults); + validateColorCertCompliance(hashHexMatches, location, diagnostics, colorFormat, colorCertCompliant); } else if (colorFormat === 'quoted-numeric-hex') { if (hashHexMatches) { - diagnostics.push(messages.expectedColorFormat(range)); + diagnostics.push(messages.expectedColorFormat(location)); } - validateColorCase(quotedNumericHexMatches, range, diagnostics, colorCase, colorFormat); - validateColorAlpha(text.match(quotedNumericHexAlphaRegex), hashHexMatches, quotedNumericHexMatches, range, diagnostics, colorAlpha, colorAlphaDefaults); - validateColorCertCompliance(quotedNumericHexMatches, range, diagnostics, colorFormat, colorCertCompliant); + validateColorCase(quotedNumericHexMatches, location, diagnostics, colorCase, colorFormat); + validateColorAlpha(text.match(quotedNumericHexAlphaRegex), hashHexMatches, quotedNumericHexMatches, location, diagnostics, colorAlpha, colorAlphaDefaults); + validateColorCertCompliance(quotedNumericHexMatches, location, diagnostics, colorFormat, colorCertCompliant); } }; } -function validateColorAlpha(alphaMatches: RegExpMatchArray, hashMatches: RegExpMatchArray, quotedNumericHexMatches: RegExpMatchArray, range: Range, diagnostics: (Omit)[], alpha: RuleColorAlpha, alphaDefaults: RuleColorAlphaDefaults) { +function validateColorAlpha(alphaMatches: RegExpMatchArray, hashMatches: RegExpMatchArray, quotedNumericHexMatches: RegExpMatchArray, location: Location, diagnostics: (BsDiagnostic)[], alpha: RuleColorAlpha, alphaDefaults: RuleColorAlphaDefaults) { const validateColorAlpha = (alpha === 'never' || alpha === 'always' || alpha === 'allowed'); if (validateColorAlpha) { if (alpha === 'never' && alphaMatches) { - diagnostics.push(messages.expectedColorAlpha(range)); + diagnostics.push(messages.expectedColorAlpha(location)); } if ((alpha === 'always' && alphaMatches === null) && (hashMatches || quotedNumericHexMatches)) { - diagnostics.push(messages.expectedColorAlpha(range)); + diagnostics.push(messages.expectedColorAlpha(location)); } if ((alphaDefaults === 'never' || alphaDefaults === 'only-hidden') && alphaMatches) { for (let i = 0; i < alphaMatches.length; i++) { const colorHashAlpha = alphaMatches[i]; const alphaValue = colorHashAlpha.slice(-2).toLowerCase(); if (alphaValue === 'ff' || (alphaDefaults === 'never' && alphaValue === '00')) { - diagnostics.push(messages.expectedColorAlphaDefaults(range)); + diagnostics.push(messages.expectedColorAlphaDefaults(location)); } } } } } -function validateColorCase(matches: RegExpMatchArray, range: Range, diagnostics: (Omit)[], colorCase: RuleColorCase, colorFormat: RuleColorFormat) { +function validateColorCase(matches: RegExpMatchArray, location: Location, diagnostics: (BsDiagnostic)[], colorCase: RuleColorCase, colorFormat: RuleColorFormat) { const validateColorCase = colorCase === 'upper' || colorCase === 'lower'; if (validateColorCase && matches) { let colorValue = matches[0]; const charsToStrip = (colorFormat === 'hash-hex') ? 1 : 2; colorValue = colorValue.substring(charsToStrip); if (colorCase === 'lower' && colorValue !== colorValue.toLowerCase()) { - diagnostics.push(messages.expectedColorCase(range)); + diagnostics.push(messages.expectedColorCase(location)); } if (colorCase === 'upper' && colorValue !== colorValue.toUpperCase()) { - diagnostics.push(messages.expectedColorCase(range)); + diagnostics.push(messages.expectedColorCase(location)); } } } -function validateColorCertCompliance(matches: RegExpMatchArray, range: Range, diagnostics: (Omit)[], colorFormat: RuleColorFormat, certCompliant: RuleColorCertCompliant) { +function validateColorCertCompliance(matches: RegExpMatchArray, location: Location, diagnostics: (BsDiagnostic)[], colorFormat: RuleColorFormat, certCompliant: RuleColorCertCompliant) { const validateCertCompliant = certCompliant === 'always'; if (validateCertCompliant && matches) { const BROADCAST_SAFE_BLACK = '161616'; @@ -90,7 +90,7 @@ function validateColorCertCompliance(matches: RegExpMatchArray, range: Range, di colorValue = colorValue.substring(charsToStrip); const colorLuma = getColorLuma(colorValue); if (colorLuma > MAX_WHITE_LUMA || colorLuma < MAX_BLACK_LUMA) { - diagnostics.push(messages.colorCertCompliance(range)); + diagnostics.push(messages.colorCertCompliance(location)); } } } diff --git a/src/plugins/checkUsage/index.ts b/src/plugins/checkUsage/index.ts index 13ca639..d3b7929 100644 --- a/src/plugins/checkUsage/index.ts +++ b/src/plugins/checkUsage/index.ts @@ -1,4 +1,4 @@ -import { AfterFileValidateEvent, AfterProgramValidateEvent, AfterScopeValidateEvent, CompilerPlugin, createVisitor, DiagnosticSeverity, isBrsFile, isXmlFile, Range, TokenKind, WalkMode, XmlFile, FunctionExpression, BscFile, isFunctionExpression, Cache } from 'brighterscript'; +import { AfterFileValidateEvent, AfterProgramValidateEvent, AfterScopeValidateEvent, CompilerPlugin, createVisitor, DiagnosticSeverity, isBrsFile, isXmlFile, Range, TokenKind, WalkMode, XmlFile, FunctionExpression, BscFile, isFunctionExpression, Cache, util } from 'brighterscript'; import { SGNode } from 'brighterscript/dist/parser/SGTypes'; import { PluginContext } from '../../util'; import { BsLintDiagnosticContext } from '../../Linter'; @@ -209,16 +209,14 @@ export default class CheckUsage implements CompilerPlugin { severity: DiagnosticSeverity.Warning, code: UnusedCode.UnusedScript, message: `Script '${v.file.pkgPath}' does not seem to be used`, - range: Range.create(0, 0, 1, 0), - file: v.file + location: util.createLocationFromFileRange(v.file, util.createRange(0, 0, 1, 0)) }, BsLintDiagnosticContext); } else if (isXmlFile(v.file) && v.file.componentName?.location.range) { v.file.program.diagnostics.register({ severity: DiagnosticSeverity.Warning, code: UnusedCode.UnusedComponent, message: `Component '${v.file.pkgPath}' does not seem to be used`, - range: v.file.componentName.location.range, - file: v.file + location: v.file.componentName.location }, BsLintDiagnosticContext); } } diff --git a/src/plugins/codeStyle/diagnosticMessages.ts b/src/plugins/codeStyle/diagnosticMessages.ts index a74c862..b046e12 100644 --- a/src/plugins/codeStyle/diagnosticMessages.ts +++ b/src/plugins/codeStyle/diagnosticMessages.ts @@ -1,4 +1,4 @@ -import { DiagnosticSeverity, FunctionExpression, IfStatement, Range, WhileStatement } from 'brighterscript'; +import { DiagnosticSeverity, FunctionExpression, IfStatement, Location, WhileStatement } from 'brighterscript'; export enum CodeStyleError { InlineIfFound = 'LINT3001', @@ -38,7 +38,7 @@ export const messages = { code: CodeStyleError.BlockIfThenMissing, source: 'bslint', message: `${CS} add 'then' keyword`, - range: stat.tokens.if.location.range, + location: stat.tokens.if.location, data: stat }), removeBlockIfThenKeyword: (stat: IfStatement) => ({ @@ -46,22 +46,22 @@ export const messages = { code: CodeStyleError.BlockIfThenFound, source: 'bslint', message: `${CS} remove 'then' keyword`, - range: stat.tokens.then.location.range, + location: stat.tokens.then.location, data: stat }), - inlineIfNotAllowed: (range: Range) => ({ + inlineIfNotAllowed: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.InlineIfFound, source: 'bslint', message: `${CS} no inline if statement allowed`, - range + location }), addInlineIfThenKeyword: (stat: IfStatement) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.InlineIfThenMissing, source: 'bslint', message: `${CS} add 'then' keyword`, - range: stat.tokens.if.location.range, + location: stat.tokens.if.location, data: stat }), removeInlineIfThenKeyword: (stat: IfStatement) => ({ @@ -69,7 +69,7 @@ export const messages = { code: CodeStyleError.InlineIfThenFound, source: 'bslint', message: `${CS} remove 'then' keyword`, - range: stat.tokens.then.location.range, + location: stat.tokens.then.location, data: stat }), addParenthesisAroundCondition: (stat: IfStatement | WhileStatement) => ({ @@ -77,7 +77,7 @@ export const messages = { code: CodeStyleError.ConditionGroupMissing, source: 'bslint', message: `${CS} add parenthesis around condition`, - range: stat.condition.location.range, + location: stat.condition.location, data: stat }), removeParenthesisAroundCondition: (stat: IfStatement | WhileStatement) => ({ @@ -85,7 +85,7 @@ export const messages = { code: CodeStyleError.ConditionGroupFound, source: 'bslint', message: `${CS} remove parenthesis around condition`, - range: stat.condition.location.range, + location: stat.condition.location, data: stat }), expectedSubKeyword: (fun: FunctionExpression, reason: string) => ({ @@ -93,7 +93,7 @@ export const messages = { code: CodeStyleError.SubKeywordExpected, source: 'bslint', message: `${CS} expected 'sub' keyword ${reason}`, - range: fun.tokens.functionType.location.range, + location: fun.tokens.functionType.location, data: fun }), expectedFunctionKeyword: (fun: FunctionExpression, reason: string) => ({ @@ -101,121 +101,121 @@ export const messages = { code: CodeStyleError.FunctionKeywordExpected, source: 'bslint', message: `${CS} expected 'function' keyword ${reason}`, - range: fun.tokens.functionType.location.range, + location: fun.tokens.functionType.location, data: fun }), - expectedReturnTypeAnnotation: (range: Range) => ({ + expectedReturnTypeAnnotation: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ReturnTypeAnnotation, source: 'bslint', message: `${ST} function should declare the return type`, - range + location }), - expectedTypeAnnotation: (range: Range) => ({ + expectedTypeAnnotation: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.TypeAnnotation, source: 'bslint', message: `${ST} type annotation required`, - range + location }), - noPrint: (range: Range, severity: DiagnosticSeverity) => ({ + noPrint: (location: Location, severity: DiagnosticSeverity) => ({ severity: severity, code: CodeStyleError.NoPrint, source: 'bslint', message: `${CS} Avoid using direct Print statements`, - range + location }), - noTodo: (range: Range, severity: DiagnosticSeverity) => ({ + noTodo: (location: Location, severity: DiagnosticSeverity) => ({ severity: severity, code: CodeStyleError.NoTodo, source: 'bslint', message: `${CS} Avoid using TODO comments`, - range + location }), - noStop: (range: Range, severity: DiagnosticSeverity) => ({ + noStop: (location: Location, severity: DiagnosticSeverity) => ({ severity: severity, code: CodeStyleError.NoStop, source: 'bslint', message: `${CS} STOP statements are not allowed in published applications`, - range + location }), - removeAAComma: (range: Range) => ({ + removeAAComma: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.AACommaFound, source: 'bslint', message: `Remove optional comma`, - range + location }), - addAAComma: (range: Range) => ({ + addAAComma: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.AACommaMissing, source: 'bslint', message: `Add comma after the expression`, - range + location }), - addEolLast: (range: Range, preferredEol: string) => ({ + addEolLast: (location: Location, preferredEol: string) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.EolLastMissing, source: 'bslint', message: `${CS} File should end with a newline`, - range, + location, data: { preferredEol } }), - removeEolLast: (range: Range) => ({ + removeEolLast: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.EolLastFound, source: 'bslint', message: `${CS} File should not end with a newline`, - range + location }), - expectedColorFormat: (range: Range) => ({ + expectedColorFormat: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ColorFormat, source: 'bslint', message: `${CS} File should follow color format`, - range + location }), - expectedColorCase: (range: Range) => ({ + expectedColorCase: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ColorCase, source: 'bslint', message: `${CS} File should follow color case`, - range + location }), - expectedColorAlpha: (range: Range) => ({ + expectedColorAlpha: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ColorAlpha, source: 'bslint', message: `${CS} File should follow color alpha rule`, - range + location }), - expectedColorAlphaDefaults: (range: Range) => ({ + expectedColorAlphaDefaults: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ColorAlphaDefaults, source: 'bslint', message: `${CS} File should follow color alpha defaults rule`, - range + location }), - colorCertCompliance: (range: Range) => ({ + colorCertCompliance: (location: Location) => ({ severity: DiagnosticSeverity.Error, code: CodeStyleError.ColorCertCompliant, source: 'bslint', message: `${CS} File should follow Roku broadcast safe color cert requirement`, - range + location }), - noAssocarrayFieldType: (range: Range, severity: DiagnosticSeverity) => ({ + noAssocarrayFieldType: (location: Location, severity: DiagnosticSeverity) => ({ message: `Avoid using field type 'assocarray'`, code: CodeStyleError.NoAssocarrayFieldType, severity: severity, source: 'bslint', - range + location }), - noArrayFieldType: (range: Range, severity: DiagnosticSeverity) => ({ + noArrayFieldType: (location: Location, severity: DiagnosticSeverity) => ({ message: `Avoid using field type 'array'`, code: CodeStyleError.NoArrayFieldType, severity: severity, source: 'bslint', - range + location }), nameShadowing: (thisThingKind: string, thatThingKind: string, thatThingName: string, severity: DiagnosticSeverity) => ({ message: `${ST} ${thisThingKind} has same name as ${thatThingKind ? thatThingKind + ' ' : ''}'${thatThingName}'`, diff --git a/src/plugins/codeStyle/index.spec.ts b/src/plugins/codeStyle/index.spec.ts index 88ee181..c619df8 100644 --- a/src/plugins/codeStyle/index.spec.ts +++ b/src/plugins/codeStyle/index.spec.ts @@ -354,7 +354,7 @@ describe('codeStyle', () => { ]; expect(actual).deep.equal(expected); // should only highlight the function name - expect(diagnostics[0].range).to.eql( + expect(diagnostics[0].location.range).to.eql( util.createRange(4, 0, 4, 8) ); }); @@ -683,14 +683,14 @@ describe('codeStyle', () => { 'color-format': 'quoted-numeric-hex', 'color-case': 'upper' }); - program.setFile( + const file = program.setFile( 'source/main.bs', `sub init()\n${code}\nend sub` ); program.validate(); expectDiagnostics( program, - diagnosticCharLocations.map(x => messages.expectedColorCase(util.createRange(1, x[0], 1, x[1]))) + diagnosticCharLocations.map(x => messages.expectedColorCase(util.createLocationFromFileRange(file, util.createRange(1, x[0], 1, x[1])))) ); } /* eslint-enable no-template-curly-in-string */ diff --git a/src/plugins/codeStyle/index.ts b/src/plugins/codeStyle/index.ts index f71a4b9..2e01e46 100644 --- a/src/plugins/codeStyle/index.ts +++ b/src/plugins/codeStyle/index.ts @@ -47,11 +47,11 @@ export default class CodeStyle implements CompilerPlugin { onGetCodeActions(event: OnGetCodeActionsEvent) { const addFixes = addFixesToEvent(event); - extractFixes(addFixes, event.diagnostics); + extractFixes(event.file, addFixes, event.diagnostics); } validateXMLFile(file: XmlFile) { - const diagnostics: Omit[] = []; + const diagnostics: BsDiagnostic[] = []; const { noArrayComponentFieldType, noAssocarrayComponentFieldType } = this.lintContext.severity; const validateArrayComponentFieldType = noArrayComponentFieldType !== DiagnosticSeverity.Hint; @@ -65,14 +65,14 @@ export default class CodeStyle implements CompilerPlugin { if (typeValue === 'array' && validateArrayComponentFieldType) { diagnostics.push( messages.noArrayFieldType( - typeAttribute?.tokens?.value?.location?.range, + typeAttribute?.tokens?.value?.location, noArrayComponentFieldType ) ); } else if (typeValue === 'assocarray' && validateAssocarrayComponentFieldType) { diagnostics.push( messages.noAssocarrayFieldType( - typeAttribute?.tokens?.value?.location?.range, + typeAttribute?.tokens?.value?.location, noAssocarrayComponentFieldType ) ); @@ -84,7 +84,7 @@ export default class CodeStyle implements CompilerPlugin { } validateBrsFile(file: BrsFile) { - const diagnostics: (Omit)[] = []; + const diagnostics: (BsDiagnostic)[] = []; const { severity } = this.lintContext; const { inlineIfStyle, blockIfStyle, conditionStyle, noPrint, noTodo, noStop, aaCommaStyle, eolLast, colorFormat } = severity; const validatePrint = noPrint !== DiagnosticSeverity.Hint; @@ -120,7 +120,7 @@ export default class CodeStyle implements CompilerPlugin { const penultimateToken = tokens[tokens.length - 2]; if (disallowEolLast) { if (penultimateToken?.kind === TokenKind.Newline) { - diagnostics.push(messages.removeEolLast(penultimateToken.location.range)); + diagnostics.push(messages.removeEolLast(penultimateToken.location)); } } else if (penultimateToken?.kind !== TokenKind.Newline) { // Set the preferredEol as the last newline. @@ -136,7 +136,7 @@ export default class CodeStyle implements CompilerPlugin { diagnostics.push( messages.addEolLast( - penultimateToken.location.range, + penultimateToken.location, preferredEol ) ); @@ -159,7 +159,7 @@ export default class CodeStyle implements CompilerPlugin { } } else if (s.isInline && validateInlineIf) { if (disallowInlineIf) { - diagnostics.push(messages.inlineIfNotAllowed(s.location.range)); + diagnostics.push(messages.inlineIfNotAllowed(s.location)); } else if (hasThenToken !== requireInlineIfThen) { diagnostics.push(requireInlineIfThen ? messages.addInlineIfThenKeyword(s) @@ -189,18 +189,18 @@ export default class CodeStyle implements CompilerPlugin { }, PrintStatement: s => { if (validatePrint) { - diagnostics.push(messages.noPrint(s.tokens.print.location.range, noPrint)); + diagnostics.push(messages.noPrint(s.tokens.print.location, noPrint)); } }, LiteralExpression: e => { if (validateColorStyle && e.tokens.value.kind === TokenKind.StringLiteral) { - validateColorStyle(e.tokens.value.text, e.tokens.value.location.range, diagnostics); + validateColorStyle(e.tokens.value.text, e.tokens.value.location, diagnostics); } }, TemplateStringExpression: e => { // only validate template strings that look like regular strings (i.e. `0xAABBCC`) if (validateColorStyle && e.quasis.length === 1 && e.quasis[0].expressions.length === 1) { - validateColorStyle(e.quasis[0].expressions[0].tokens.value.text, e.quasis[0].expressions[0].tokens.value.location.range, diagnostics); + validateColorStyle(e.quasis[0].expressions[0].tokens.value.text, e.quasis[0].expressions[0].tokens.value.location, diagnostics); } }, AALiteralExpression: e => { @@ -210,7 +210,7 @@ export default class CodeStyle implements CompilerPlugin { }, StopStatement: s => { if (validateNoStop) { - diagnostics.push(messages.noStop(s.tokens.stop.location.range, noStop)); + diagnostics.push(messages.noStop(s.tokens.stop.location, noStop)); } }, AstNode: (node: Statement | Expression) => { @@ -218,7 +218,7 @@ export default class CodeStyle implements CompilerPlugin { if (validateTodo && comments.length > 0) { for (const e of comments) { if (this.lintContext.todoPattern.test(e.text)) { - diagnostics.push(messages.noTodo(e.location.range, noTodo)); + diagnostics.push(messages.noTodo(e.location, noTodo)); } } } @@ -229,7 +229,7 @@ export default class CodeStyle implements CompilerPlugin { } validateBrsFileInScope(file: BrsFile) { - const diagnostics: (Omit)[] = []; + const diagnostics: (BsDiagnostic)[] = []; const { severity } = this.lintContext; const { nameShadowing } = severity; @@ -261,7 +261,7 @@ export default class CodeStyle implements CompilerPlugin { return; } - const diagnostics: (Omit)[] = []; + const diagnostics: (BsDiagnostic)[] = []; if (isXmlFile(file)) { diagnostics.push(...this.validateXMLFile(file)); } else if (isBrsFile(file)) { @@ -278,7 +278,7 @@ export default class CodeStyle implements CompilerPlugin { // apply fix if (fix) { - bsDiagnostics = extractFixes(this.lintContext.addFixes, bsDiagnostics); + bsDiagnostics = extractFixes(event.file, this.lintContext.addFixes, bsDiagnostics); } // append diagnostics @@ -291,7 +291,7 @@ export default class CodeStyle implements CompilerPlugin { return; } - const diagnostics: (Omit)[] = []; + const diagnostics: (BsDiagnostic)[] = []; if (isBrsFile(file)) { diagnostics.push(...this.validateBrsFileInScope(file)); } @@ -306,7 +306,7 @@ export default class CodeStyle implements CompilerPlugin { // apply fix if (fix) { - bsDiagnostics = extractFixes(this.lintContext.addFixes, bsDiagnostics); + bsDiagnostics = extractFixes(file, this.lintContext.addFixes, bsDiagnostics); } // append diagnostics @@ -314,7 +314,7 @@ export default class CodeStyle implements CompilerPlugin { } } - validateAAStyle(aa: AALiteralExpression, aaCommaStyle: RuleAAComma, diagnostics: (Omit)[]) { + validateAAStyle(aa: AALiteralExpression, aaCommaStyle: RuleAAComma, diagnostics: (BsDiagnostic)[]) { const indexes = collectWrappingAAMembersIndexes(aa); const last = indexes.length - 1; const isSingleLine = (aa: AALiteralExpression): boolean => { @@ -326,15 +326,15 @@ export default class CodeStyle implements CompilerPlugin { const hasComma = !!member.tokens.comma; if (aaCommaStyle === 'never' || (i === last && ((aaCommaStyle === 'no-dangling') || isSingleLine(aa)))) { if (hasComma) { - diagnostics.push(messages.removeAAComma(member.tokens.comma.location.range)); + diagnostics.push(messages.removeAAComma(member.tokens.comma.location)); } } else if (!hasComma) { - diagnostics.push(messages.addAAComma(member.value.location.range)); + diagnostics.push(messages.addAAComma(member.value.location)); } }); } - validateFunctionStyle(fun: FunctionExpression, diagnostics: (Omit)[]) { + validateFunctionStyle(fun: FunctionExpression, diagnostics: (BsDiagnostic)[]) { const { severity } = this.lintContext; const { namedFunctionStyle, anonFunctionStyle, typeAnnotations } = severity; const style = fun.functionStatement ? namedFunctionStyle : anonFunctionStyle; @@ -347,7 +347,7 @@ export default class CodeStyle implements CompilerPlugin { if (hasReturnedValue && !fun.returnTypeExpression) { diagnostics.push(messages.expectedReturnTypeAnnotation( // add the error to the function keyword (or just highlight the whole function if that's somehow missing) - fun.tokens.functionType?.location?.range ?? fun.location.range + fun.tokens.functionType?.location ?? fun.location )); } } @@ -355,7 +355,7 @@ export default class CodeStyle implements CompilerPlugin { const missingAnnotation = fun.parameters.find(arg => !arg.typeExpression); if (missingAnnotation) { // only report 1st missing arg annotation to avoid error overload - diagnostics.push(messages.expectedTypeAnnotation(missingAnnotation.location.range)); + diagnostics.push(messages.expectedTypeAnnotation(missingAnnotation.location)); } } } @@ -404,7 +404,7 @@ export default class CodeStyle implements CompilerPlugin { return hasReturnedValue; } - validateNameShadowing(file: BrsFile, node: AstNode, nameIdentifier: Token, severity: DiagnosticSeverity, diagnostics: (Omit)[]) { + validateNameShadowing(file: BrsFile, node: AstNode, nameIdentifier: Token, severity: DiagnosticSeverity, diagnostics: (BsDiagnostic)[]) { const name = nameIdentifier?.text; if (!name || !node) { return; @@ -443,7 +443,7 @@ export default class CodeStyle implements CompilerPlugin { diagnostics.push({ ...messages.nameShadowing(thisNodeKindName, thatNodeKindName, name, severity), - range: nameLocation.range, + location: nameLocation, relatedInformation: relatedInformation }); } diff --git a/src/plugins/codeStyle/styleFixes.ts b/src/plugins/codeStyle/styleFixes.ts index e77abbe..3b29bff 100644 --- a/src/plugins/codeStyle/styleFixes.ts +++ b/src/plugins/codeStyle/styleFixes.ts @@ -4,13 +4,14 @@ import { CodeStyleError } from './diagnosticMessages'; import { platform } from 'process'; export function extractFixes( + file: BscFile, addFixes: (file: BscFile, changes: ChangeEntry) => void, diagnostics: BsDiagnostic[] ): BsDiagnostic[] { return diagnostics.filter(diagnostic => { const fix = getFixes(diagnostic); if (fix) { - addFixes(diagnostic.file, fix); + addFixes(file, fix); return false; } return true; @@ -47,21 +48,21 @@ export function getFixes(diagnostic: BsDiagnostic): ChangeEntry { } function addAAComma(diagnostic: BsDiagnostic) { - const { range } = diagnostic; + const { location } = diagnostic; return { diagnostic, changes: [ - insertText(range.end, ',') + insertText(location.range.end, ',') ] }; } function removeAAComma(diagnostic: BsDiagnostic) { - const { range } = diagnostic; + const { location } = diagnostic; return { diagnostic, changes: [ - replaceText(range, '') + replaceText(location.range, '') ] }; } @@ -154,7 +155,7 @@ function addEolLast(diagnostic: BsDiagnostic): ChangeEntry { diagnostic, changes: [ insertText( - diagnostic.range.end, + diagnostic.location.range.end, // In single line files, the `preferredEol` cannot be determined // e.g: `sub foo() end sub\EOF` diagnostic.data.preferredEol ?? (platform.toString() === 'win32' ? '\r\n' : '\n') @@ -167,7 +168,7 @@ function removeEolLast(diagnostic: BsDiagnostic): ChangeEntry { return { diagnostic, changes: [ - replaceText(diagnostic.range, '') + replaceText(diagnostic.location.range, '') ] }; } diff --git a/src/plugins/trackCodeFlow/index.spec.ts b/src/plugins/trackCodeFlow/index.spec.ts index 2c394d6..8fd0398 100644 --- a/src/plugins/trackCodeFlow/index.spec.ts +++ b/src/plugins/trackCodeFlow/index.spec.ts @@ -51,7 +51,9 @@ describe('trackCodeFlow', () => { expectDiagnostics(program, [{ code: VarLintError.UnsafeInitialization, message: `Not all the code paths assign 'text2'`, - range: util.createRange(9, 22, 9, 27) + location: { + range: util.createRange(9, 22, 9, 27) + } }]); }); diff --git a/src/plugins/trackCodeFlow/index.ts b/src/plugins/trackCodeFlow/index.ts index f6d8afa..08f9daf 100644 --- a/src/plugins/trackCodeFlow/index.ts +++ b/src/plugins/trackCodeFlow/index.ts @@ -62,7 +62,7 @@ export default class TrackCodeFlow implements CompilerPlugin { onGetCodeActions(event: OnGetCodeActionsEvent) { const addFixes = addFixesToEvent(event); - extractFixes(addFixes, event.diagnostics); + extractFixes(event.file, addFixes, event.diagnostics); } afterScopeValidate(event: AfterScopeValidateEvent) { @@ -186,7 +186,7 @@ export default class TrackCodeFlow implements CompilerPlugin { } if (this.lintContext.fix) { - diagnostics = extractFixes(this.lintContext.addFixes, diagnostics); + diagnostics = extractFixes(event.file, this.lintContext.addFixes, diagnostics); } event.program.diagnostics.register(diagnostics, BsLintDiagnosticContext); } diff --git a/src/plugins/trackCodeFlow/returnTracking.ts b/src/plugins/trackCodeFlow/returnTracking.ts index 0ebee3a..bef850c 100644 --- a/src/plugins/trackCodeFlow/returnTracking.ts +++ b/src/plugins/trackCodeFlow/returnTracking.ts @@ -39,8 +39,7 @@ export function createReturnLinter( severity: severity.unreachableCode, code: ReturnLintError.UnreachableCode, message: 'Unreachable code', - range: curr.stat.location.range, - file: file, + location: curr.stat.location, tags: [DiagnosticTag.Unnecessary] }); } else if (isReturnStatement(curr.stat)) { @@ -96,7 +95,7 @@ export function createReturnLinter( const funRangeStart = (fun.tokens.functionType ?? fun.tokens.leftParen).location.range.start; const funRangeEnd = (fun.returnTypeExpression ?? fun.tokens.rightParen).location.range.end; const funRange = util.createRangeFromPositions(funRangeStart, funRangeEnd); - + const funLocation = util.createLocationFromRange(fun.location.uri, funRange); // Explicit `as void` or `sub` without return type should never return a value const returnType = fun.returnTypeExpression?.getType({ flags: SymbolTypeFlag.typetime }); @@ -110,8 +109,7 @@ export function createReturnLinter( severity: consistentReturn, code: ReturnLintError.ReturnValueUnexpected, message: `${kind} as void should not return a value`, - range: r.stat?.location.range || funRange, - file: file + location: r.stat?.location ?? funLocation }); }); } @@ -132,8 +130,7 @@ export function createReturnLinter( severity: consistentReturn, code: ReturnLintError.UnsafeReturnValue, message: 'Not all code paths return a value', - range: funRange, - file: file + location: funLocation }); } @@ -146,8 +143,7 @@ export function createReturnLinter( severity: consistentReturn, code: ReturnLintError.ReturnValueMissing, message: `${kind} should consistently return a value`, - range: r.stat.location.range || funRange, - file: file + location: r.stat.location || funLocation }); }); } diff --git a/src/plugins/trackCodeFlow/trackFixes.ts b/src/plugins/trackCodeFlow/trackFixes.ts index 83848c9..6e11a1b 100644 --- a/src/plugins/trackCodeFlow/trackFixes.ts +++ b/src/plugins/trackCodeFlow/trackFixes.ts @@ -1,15 +1,16 @@ -import { BscFile, BsDiagnostic, Range } from 'brighterscript'; +import { BscFile, BsDiagnostic, Location } from 'brighterscript'; import { ChangeEntry, replaceText } from '../../textEdit'; import { VarLintError } from './varTracking'; export function extractFixes( + file: BscFile, addFixes: (file: BscFile, changes: ChangeEntry) => void, diagnostics: BsDiagnostic[] ): BsDiagnostic[] { return diagnostics.filter(diagnostic => { const fix = getFixes(diagnostic); if (fix) { - addFixes(diagnostic.file, fix); + addFixes(file, fix); return false; } return true; @@ -26,11 +27,11 @@ export function getFixes(diagnostic: BsDiagnostic): ChangeEntry { } function fixCasing(diagnostic: BsDiagnostic) { - const data: { name: string; range: Range } = diagnostic.data; + const data: { name: string; location: Location } = diagnostic.data; return { diagnostic, changes: [ - replaceText(data.range, data.name) + replaceText(data.location.range, data.name) ] }; } diff --git a/src/plugins/trackCodeFlow/varTracking.ts b/src/plugins/trackCodeFlow/varTracking.ts index a78e399..bed2201 100644 --- a/src/plugins/trackCodeFlow/varTracking.ts +++ b/src/plugins/trackCodeFlow/varTracking.ts @@ -21,7 +21,7 @@ interface ValidationInfo { kind: ValidationKind; name: string; local?: VarInfo; - range: Range; + location: Location; namespace?: NamespaceStatement; } @@ -63,11 +63,10 @@ export function createVarLinter( severity: severity.caseSensitivity, code: VarLintError.CaseMismatch, message: `Variable '${name.text}' was previously set with a different casing as '${curr.name}'`, - range: name.location.range, - file: file, + location: name.location, data: { name: curr.name, - range: name.location.range + location: name.location } }); } @@ -104,7 +103,7 @@ export function createVarLinter( kind: ValidationKind.Assignment, name: name.text, local: local, - range: name.location.range + location: name.location }); return local; @@ -291,7 +290,7 @@ export function createVarLinter( deferred.push({ kind: ValidationKind.UninitializedVar, name: name, - range: expr.location.range, + location: expr.location, namespace: expr.findAncestor(isNamespaceStatement) }); return; @@ -306,16 +305,14 @@ export function createVarLinter( severity: severity.unsafeIterators, code: VarLintError.UnsafeIteratorVar, message: `Using iterator variable '${name}' outside loop`, - range: expr.location.range, - file: file + location: expr.location }); } else if (!isNarrowing(local, expr, parent, curr)) { diagnostics.push({ severity: severity.unsafePathLoop, code: VarLintError.UnsafeInitialization, message: `Not all the code paths assign '${name}'`, - range: expr.location.range, - file: file + location: expr.location }); } } @@ -359,8 +356,7 @@ export function createVarLinter( severity: severity.unusedVariable, code: VarLintError.UnusedVariable, message: `Variable '${local.name}' is set but value is never used`, - range: local.location.range, - file: file + location: local.location }); } }); @@ -422,7 +418,7 @@ function deferredVarLinter( deferred: ValidationInfo[], diagnostics: BsDiagnostic[] ) { - deferred.forEach(({ kind, name, local, range, namespace }) => { + deferred.forEach(({ kind, name, local, location, namespace }) => { const key = name?.toLowerCase(); let hasCallable = key ? callables.has(key) || toplevel.has(key) : false; if (key && !hasCallable && namespace) { @@ -437,8 +433,7 @@ function deferredVarLinter( severity: DiagnosticSeverity.Error, code: VarLintError.UninitializedVar, message: `Using uninitialised variable '${name}' when this file is included in scope '${scope.name}'`, - range: range, - file: file + location: location }); } // TODO else test case diff --git a/src/testHelpers.spec.ts b/src/testHelpers.spec.ts index 1b07dd2..fefa434 100644 --- a/src/testHelpers.spec.ts +++ b/src/testHelpers.spec.ts @@ -1,12 +1,12 @@ -import { BsDiagnostic, BscFile, DiagnosticSeverity, DiagnosticTag, Range } from 'brighterscript'; -import { CodeDescription, DiagnosticRelatedInformation, Diagnostic } from 'vscode-languageserver-types'; +import { BsDiagnostic, DiagnosticSeverity, DiagnosticTag, Location } from 'brighterscript'; +import { CodeDescription, DiagnosticRelatedInformation } from 'vscode-languageserver-types'; import { expect } from 'chai'; import { firstBy } from 'thenby'; -type DiagnosticCollection = { getDiagnostics: () => Array } | { diagnostics: Diagnostic[] } | Diagnostic[]; +type DiagnosticCollection = { getDiagnostics: () => Array } | { diagnostics: BsDiagnostic[] } | BsDiagnostic[]; function getDiagnostics(arg: DiagnosticCollection): BsDiagnostic[] { if (Array.isArray(arg)) { - return arg as BsDiagnostic[]; + return arg; } else if ((arg as any).getDiagnostics) { return (arg as any).getDiagnostics(); } else if ((arg as any).diagnostics) { @@ -20,10 +20,10 @@ function sortDiagnostics(diagnostics: BsDiagnostic[]) { return diagnostics.sort( firstBy('code') .thenBy('message') - .thenBy((a, b) => (a.range?.start?.line ?? 0) - (b.range?.start?.line ?? 0)) - .thenBy((a, b) => (a.range?.start?.character ?? 0) - (b.range?.start?.character ?? 0)) - .thenBy((a, b) => (a.range?.end?.line ?? 0) - (b.range?.end?.line ?? 0)) - .thenBy((a, b) => (a.range?.end?.character ?? 0) - (b.range?.end?.character ?? 0)) + .thenBy((a, b) => (a.location.range?.start?.line ?? 0) - (b.location.range?.start?.line ?? 0)) + .thenBy((a, b) => (a.location.range?.start?.character ?? 0) - (b.location.range?.start?.character ?? 0)) + .thenBy((a, b) => (a.location.range?.end?.line ?? 0) - (b.location.range?.end?.line ?? 0)) + .thenBy((a, b) => (a.location.range?.end?.character ?? 0) - (b.location.range?.end?.character ?? 0)) ); } @@ -41,7 +41,7 @@ function cloneObject(original: TOriginal, template: TTempl } interface PartialDiagnostic { - range?: Range; + location?: Partial; severity?: DiagnosticSeverity; code?: number | string; codeDescription?: Partial; @@ -50,7 +50,6 @@ interface PartialDiagnostic { tags?: Partial[]; relatedInformation?: Partial[]; data?: unknown; - file?: Partial; } /** @@ -60,7 +59,7 @@ function cloneDiagnostic(actualDiagnosticInput: BsDiagnostic, expectedDiagnostic const actualDiagnostic = cloneObject( actualDiagnosticInput, expectedDiagnostic, - ['message', 'code', 'range', 'severity', 'relatedInformation'] + ['message', 'code', 'location', 'severity', 'relatedInformation'] ); // deep clone relatedInformation if available if (actualDiagnostic.relatedInformation) { @@ -73,11 +72,11 @@ function cloneDiagnostic(actualDiagnosticInput: BsDiagnostic, expectedDiagnostic } } // deep clone file info if available - if (actualDiagnostic.file) { - actualDiagnostic.file = cloneObject( - actualDiagnostic.file, - expectedDiagnostic?.file, - ['srcPath', 'pkgPath'] + if (actualDiagnostic.location) { + actualDiagnostic.location = cloneObject( + actualDiagnostic.location, + expectedDiagnostic?.location, + ['uri', 'range'] ) as any; } return actualDiagnostic; @@ -122,8 +121,8 @@ function pad(n: number) { export function fmtDiagnostics(diagnostics: BsDiagnostic[]) { return diagnostics .filter((d) => d.severity && d.severity < 4) - .sort((a, b) => a.range.start.line - b.range.start.line) - .map((d) => `${pad(d.range.start.line + 1)}:${d.code}:${d.message}`) + .sort((a, b) => a.location.range.start.line - b.location.range.start.line) + .map((d) => `${pad(d.location.range.start.line + 1)}:${d.code}:${d.message}`) .sort(); }