From 1bff509338521c677d8dc1f0ed6e20de978ee882 Mon Sep 17 00:00:00 2001 From: Andrew Qu Date: Sat, 21 Mar 2020 14:01:40 -0700 Subject: [PATCH 1/7] Removed $ bash code block prefix --- website/docs/community/contributing.md | 10 +++++----- website/docs/introduction/getting-started.md | 14 +++++++------- website/docs/introduction/installation.md | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/website/docs/community/contributing.md b/website/docs/community/contributing.md index fdd883e0047..e7c5d753ca4 100644 --- a/website/docs/community/contributing.md +++ b/website/docs/community/contributing.md @@ -13,9 +13,9 @@ Our [Discord server](https://discord.gg/9WxHa5d) is open for help and more adhoc Getting started with developing Rome is as easy as three commands. You will need Node v12 or above. ``` -$ git clone https://github.com/facebookexperimental/rome -$ cd rome -$ scripts/dev-rome --help +git clone https://github.com/facebookexperimental/rome +cd rome +scripts/dev-rome --help ``` No dependency installation step is required as we check in our `node_modules` folder that contains only a copy of TypeScript and some definitions. @@ -27,7 +27,7 @@ Refer to [Getting Started](../introduction/getting-started.md) for more usage do You can run the test suite with the following command: ``` -$ scripts/dev-rome test +scripts/dev-rome test ``` This will run all tests inside of any `__rtests__` directories. @@ -37,5 +37,5 @@ This will run all tests inside of any `__rtests__` directories. Run TypeScript with code emitting disabled to perform a full typecheck outside the editor. ``` -$ node_modules/.bin/tsc --noEmit +node_modules/.bin/tsc --noEmit ``` diff --git a/website/docs/introduction/getting-started.md b/website/docs/introduction/getting-started.md index 9b124363e4b..5b229085c0b 100644 --- a/website/docs/introduction/getting-started.md +++ b/website/docs/introduction/getting-started.md @@ -13,13 +13,13 @@ as much or as little as you like. First, navigate into your project folder: ```bash -$ cd my_existing_project +cd my_existing_project ``` Now, create a Rome configuration for your project. When prompted, use the recommended settings: ```bash -$ rome init +rome init ``` ## What did we do? @@ -47,7 +47,7 @@ The `rome run` command will run whatever file is passed to it. Use this command with your project's main file, for example: ```bash -$ rome run index.js +rome run index.js ``` Rome is still under active development and may not be able to properly @@ -62,7 +62,7 @@ This command will lint a file with a set of default lints and display the produc When ran with no arguments, all JavaScript files in a project are linted. For example: ```bash -$ rome lint file.js +rome lint file.js ``` ### `compile` @@ -70,7 +70,7 @@ $ rome lint file.js This command will compile a file with a set of default transforms. There is currently no options for this command to specify a subset of transforms. ``` -$ rome compile file.js +rome compile file.js ``` ### `parse` @@ -78,5 +78,5 @@ $ rome compile file.js This command will parse a file and output a pretty formatted AST. ``` -$ rome parse file.js -``` \ No newline at end of file +rome parse file.js +``` diff --git a/website/docs/introduction/installation.md b/website/docs/introduction/installation.md index 58165e55dde..47833ddfec2 100644 --- a/website/docs/introduction/installation.md +++ b/website/docs/introduction/installation.md @@ -15,19 +15,19 @@ Rome is not available via `npm` and must be installed from GitHub. In a folder of your choice, clone the `rome` repository: ```bash -$ git clone https://github.com/facebookexperimental/rome +git clone https://github.com/facebookexperimental/rome ``` Then, navigate into it and build `rome`: ```bash -$ cd rome; ./scripts/build-release dist +cd rome; ./scripts/build-release dist ``` Now, install `rome` globally: ``` -$ npm install -g ./dist/ +npm install -g ./dist/ ``` Congratulations! Rome is installed. From 0b7fc5f3ba3af003b141b6484689caa700dca777 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 21 Mar 2020 22:06:49 -0700 Subject: [PATCH 2/7] Simplify diagnostics --- .../cli-diagnostics/DiagnosticsPrinter.ts | 118 +- .../cli-diagnostics/ansiHighlightCode.ts | 9 +- .../cli-diagnostics/buildMessageCodeFrame.ts | 8 +- packages/@romejs/cli-diagnostics/index.ts | 8 +- .../@romejs/cli-diagnostics/printAdvice.ts | 74 +- .../@romejs/cli-flags/serializeCLIFlags.ts | 4 +- packages/@romejs/codec-js-manifest/index.ts | 4 +- packages/@romejs/codec-js-manifest/name.ts | 4 +- packages/@romejs/codec-js-regexp/index.ts | 20 +- packages/@romejs/codec-json/index.ts | 2 - packages/@romejs/codec-json/messages.ts | 29 - packages/@romejs/codec-json/parse.ts | 61 +- packages/@romejs/codec-json/parser.test.ts | 37 +- packages/@romejs/codec-semver/parse.ts | 30 +- packages/@romejs/codec-spdx-license/parse.ts | 29 +- packages/@romejs/consume/Consumer.ts | 55 +- packages/@romejs/consume/types.ts | 10 +- .../core/common/bridges/TestWorkerBridge.ts | 4 +- .../core/common/bridges/WorkerBridge.ts | 9 +- packages/@romejs/core/common/fileHandlers.ts | 4 +- .../core/common/types/analyzeDependencies.ts | 4 +- packages/@romejs/core/common/types/bundler.ts | 4 +- .../@romejs/core/common/utils/executeMain.ts | 24 +- packages/@romejs/core/master/Master.ts | 13 +- packages/@romejs/core/master/MasterRequest.ts | 80 +- .../core/master/bundler/BundleRequest.ts | 17 +- .../@romejs/core/master/commands/format.ts | 24 +- packages/@romejs/core/master/commands/lint.ts | 6 +- packages/@romejs/core/master/commands/test.ts | 4 +- .../master/dependencies/DependencyNode.ts | 123 +- .../master/dependencies/DependencyOrderer.ts | 57 +- packages/@romejs/core/master/fs/Resolver.ts | 8 +- .../@romejs/core/master/fs/resolverSuggest.ts | 17 +- packages/@romejs/core/master/linter/Linter.ts | 24 +- .../core/master/project/ProjectManager.ts | 61 +- .../@romejs/core/master/testing/TestRunner.ts | 34 +- packages/@romejs/core/master/testing/types.ts | 4 +- .../core/test-worker/SnapshotManager.ts | 43 +- .../core/test-worker/SnapshotParser.ts | 7 +- packages/@romejs/core/test-worker/TestAPI.ts | 17 +- .../core/test-worker/TestWorkerRunner.ts | 48 +- packages/@romejs/core/worker/Worker.ts | 4 +- packages/@romejs/core/worker/WorkerAPI.ts | 46 +- .../diagnostics/DiagnosticsProcessor.ts | 81 +- packages/@romejs/diagnostics/categories.ts | 1 + packages/@romejs/diagnostics/constants.ts | 4 +- packages/@romejs/diagnostics/derive.ts | 84 +- packages/@romejs/diagnostics/descriptions.ts | 1326 +++++++++++++++++ packages/@romejs/diagnostics/errors.ts | 28 +- packages/@romejs/diagnostics/helpers.ts | 34 +- packages/@romejs/diagnostics/index.ts | 4 +- packages/@romejs/diagnostics/normalize.ts | 274 ---- packages/@romejs/diagnostics/types.ts | 219 +-- packages/@romejs/diagnostics/wrap.ts | 4 +- packages/@romejs/js-analysis/api/check.ts | 66 +- .../@romejs/js-analysis/tests/basic.test.ts | 4 +- .../@romejs/js-analysis/types/ExhaustiveT.ts | 11 +- .../@romejs/js-analysis/types/errors/E.ts | 11 +- .../js-analysis/types/errors/MissingUnionE.ts | 8 +- .../js-analysis/types/errors/NotCallableE.ts | 4 +- .../types/errors/UndeclaredVarE.ts | 9 +- .../types/errors/UnknownImportE.ts | 42 +- .../js-analysis/types/errors/UnknownPropE.ts | 8 +- packages/@romejs/js-ast/core/Program.ts | 4 +- .../api/analyzeDependencies/index.ts | 4 +- packages/@romejs/js-compiler/api/compile.ts | 4 +- packages/@romejs/js-compiler/api/lint.ts | 4 +- packages/@romejs/js-compiler/lib/Context.ts | 40 +- packages/@romejs/js-compiler/lib/Path.ts | 4 +- .../@romejs/js-compiler/methods/transform.ts | 6 +- packages/@romejs/js-compiler/suppressions.ts | 33 +- .../js-compiler/transforms/compile/jsx.ts | 4 +- .../transforms/compile/transpile/classes.ts | 4 +- .../lint/defaultExportSameBasename.ts | 29 +- .../transforms/lint/emptyBlocks.ts | 4 +- .../transforms/lint/getterReturn.ts | 4 +- .../transforms/lint/noAsyncPromiseExecutor.ts | 4 +- .../transforms/lint/noCompareNegZero.ts | 9 +- .../transforms/lint/noCondAssign.ts | 4 +- ...noDanglingBackslashInRegularExpressions.ts | 4 +- .../js-compiler/transforms/lint/noDebugger.ts | 5 +- .../transforms/lint/noDeleteVars.ts | 4 +- .../transforms/lint/noDupeArgs.test.ts | 2 +- .../js-compiler/transforms/lint/noDupeArgs.ts | 4 +- .../transforms/lint/noDuplicateCase.test.ts | 2 +- .../transforms/lint/noDuplicateCase.ts | 4 +- ...DuplicateGroupNamesInRegularExpressions.ts | 33 +- .../transforms/lint/noDuplicateKeys.ts | 5 +- .../transforms/lint/noEmptyCharacterClass.ts | 5 +- .../transforms/lint/noExplicitAny.ts | 4 +- .../lint/noExtraBooleanCast.test.ts | 8 +- .../transforms/lint/noExtraBooleanCast.ts | 4 +- .../transforms/lint/noFunctionAssign.test.ts | 6 +- .../transforms/lint/noFunctionAssign.ts | 4 +- .../transforms/lint/noImportAssign.test.ts | 4 +- .../transforms/lint/noImportAssign.ts | 7 +- .../transforms/lint/noLabelVar.test.ts | 8 +- .../js-compiler/transforms/lint/noLabelVar.ts | 4 +- ...ltipleSpacesInRegularExpressionLiterals.ts | 14 +- .../lint/noShadowRestrictedNames.test.ts | 2 +- .../lint/noShadowRestrictedNames.ts | 12 +- .../lint/noTemplateCurlyInString.ts | 5 +- .../transforms/lint/noUnsafeFinally.test.ts | 8 +- .../transforms/lint/noUnsafeFinally.ts | 4 +- .../js-compiler/transforms/lint/noVar.ts | 4 +- .../lint/preferFunctionDeclarations.ts | 5 +- .../transforms/lint/preferTemplate.ts | 4 +- .../transforms/lint/sparseArray.ts | 5 +- .../transforms/lint/undeclaredVariables.ts | 5 +- .../transforms/lint/unsafeNegation.ts | 5 +- .../transforms/lint/unusedVariables.ts | 4 +- packages/@romejs/js-parser-utils/index.ts | 2 - packages/@romejs/js-parser-utils/messages.ts | 13 - packages/@romejs/js-parser-utils/regex.ts | 8 +- packages/@romejs/js-parser/index.test.ts | 6 +- packages/@romejs/js-parser/index.ts | 4 +- packages/@romejs/js-parser/parser.ts | 134 +- packages/@romejs/js-parser/parser/classes.ts | 40 +- .../@romejs/js-parser/parser/expression.ts | 138 +- packages/@romejs/js-parser/parser/flow.ts | 58 +- packages/@romejs/js-parser/parser/jsx.ts | 147 +- packages/@romejs/js-parser/parser/lval.ts | 99 +- packages/@romejs/js-parser/parser/modules.ts | 37 +- .../@romejs/js-parser/parser/statement.ts | 77 +- .../@romejs/js-parser/parser/type-systems.ts | 39 +- .../@romejs/js-parser/parser/typescript.ts | 23 +- packages/@romejs/js-parser/tokenizer/index.ts | 95 +- packages/@romejs/js-parser/tokenizer/state.ts | 9 +- packages/@romejs/messages/en.ts | 1 - packages/@romejs/parser-core/index.ts | 64 +- packages/@romejs/path-match/parse.ts | 5 +- packages/@romejs/project/save.ts | 7 +- packages/@romejs/string-escape/index.ts | 4 - packages/@romejs/string-escape/messages.ts | 12 - .../@romejs/string-escape/unescapeString.ts | 27 +- packages/@romejs/string-markup/parse.ts | 23 +- packages/@romejs/typescript-helpers/index.ts | 4 + packages/@romejs/v8/errors.ts | 8 +- packages/rome/error.ts | 4 +- 139 files changed, 2703 insertions(+), 2150 deletions(-) delete mode 100644 packages/@romejs/codec-json/messages.ts create mode 100644 packages/@romejs/diagnostics/descriptions.ts delete mode 100644 packages/@romejs/diagnostics/normalize.ts delete mode 100644 packages/@romejs/js-parser-utils/messages.ts delete mode 100644 packages/@romejs/messages/en.ts delete mode 100644 packages/@romejs/string-escape/messages.ts diff --git a/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts b/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts index 697b45db451..1f483c14749 100644 --- a/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts +++ b/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts @@ -6,15 +6,12 @@ */ import { - Diagnostic, Diagnostics, - PartialDiagnostics, - PartialDiagnostic, - DiagnosticAdvice, + Diagnostic, DiagnosticOrigin, DiagnosticLanguage, DiagnosticSourceType, - PartialDiagnosticAdvice, + DiagnosticAdvice, } from '@romejs/diagnostics'; import {Reporter} from '@romejs/cli-reporter'; import { @@ -25,7 +22,6 @@ import { } from './types'; import {DiagnosticsProcessor} from '@romejs/diagnostics'; import { - normalizeDiagnosticAdviceItem, deriveRootAdviceFromDiagnostic, getDiagnosticHeader, } from '@romejs/diagnostics'; @@ -55,8 +51,8 @@ type Banner = { }; type PositionLike = { - line: undefined | Number1; - column: undefined | Number0; + line?: undefined | Number1; + column?: undefined | Number0; }; export function readDiagnosticsFileLocal( @@ -110,8 +106,8 @@ type ReferenceFileDependency = { type: 'reference'; path: UnknownFilePath; mtime: undefined | number; - sourceType: DiagnosticSourceType; - language: DiagnosticLanguage; + sourceType: undefined | DiagnosticSourceType; + language: undefined | DiagnosticLanguage; }; type FileDependency = ChangeFileDependency | ReferenceFileDependency; @@ -164,6 +160,20 @@ export default class DiagnosticsPrinter extends Error { filteredCount: number; truncatedCount: number; + createFilePath(filename: undefined | string): UnknownFilePath { + if (filename === undefined) { + filename = 'unknown'; + } + + const {normalizeFilename} = this.reporter.markupOptions; + + if (normalizeFilename === undefined) { + return createUnknownFilePath(filename); + } else { + return createUnknownFilePath(normalizeFilename(filename)); + } + } + throwIfAny() { if (this.hasDiagnostics()) { throw this; @@ -188,16 +198,14 @@ export default class DiagnosticsPrinter extends Error { } getDiagnostics(): Diagnostics { - return this.processor.getCompleteSortedDiagnostics( - this.reporter.markupOptions, - ); + return this.processor.getSortedDiagnostics(); } isFocused(diag: Diagnostic): boolean { const focusFlag = this.flags.focus; const focusEnabled = focusFlag !== undefined && focusFlag !== ''; - const {filename, start, end} = diag; + const {filename, start, end} = diag.location; // If focus is enabled, exclude locationless errors if (focusEnabled && (filename === undefined || start === undefined)) { @@ -237,7 +245,8 @@ export default class DiagnosticsPrinter extends Error { } // Match against the supplied grep pattern - let ignored = diag.message.toLowerCase().includes(grep) === false; + let ignored = + diag.description.message.value.toLowerCase().includes(grep) === false; if (inverseGrep) { ignored = !ignored; } @@ -264,43 +273,47 @@ export default class DiagnosticsPrinter extends Error { const deps: Array = []; for (const { - advice, - filename, dependencies, - language, - sourceType, - mtime, + description: {advice}, + location: {language, sourceType, mtime, filename}, } of diagnostics) { if (filename !== undefined) { deps.push({ type: 'reference', - path: createUnknownFilePath(filename), + path: this.createFilePath(filename), mtime, language, sourceType, }); } - for (const {filename, mtime} of dependencies) { - deps.push({ - type: 'change', - path: createUnknownFilePath(filename), - mtime, - }); - } - - for (const item of advice) { - if (item.type === 'frame' && item.filename !== undefined && - item.sourceText === undefined) { + if (dependencies !== undefined) { + for (const {filename, mtime} of dependencies) { deps.push({ - type: 'reference', - path: createUnknownFilePath(item.filename), - language: item.language, - sourceType: item.sourceType, - mtime: item.mtime, + type: 'change', + path: this.createFilePath(filename), + mtime, }); } } + + if (advice !== undefined) { + for (const item of advice) { + if (item.type === 'frame') { + const {location: pointer} = item; + if (pointer.filename !== undefined && pointer.sourceText === + undefined) { + deps.push({ + type: 'reference', + path: this.createFilePath(pointer.filename), + language: pointer.language, + sourceType: pointer.sourceType, + mtime: pointer.mtime, + }); + } + } + } + } } const depsMap: UnknownFilePathMap = new UnknownFilePathMap(); @@ -351,11 +364,11 @@ export default class DiagnosticsPrinter extends Error { } } - addDiagnostic(partialDiagnostic: PartialDiagnostic, origin?: DiagnosticOrigin) { + addDiagnostic(partialDiagnostic: Diagnostic, origin?: DiagnosticOrigin) { this.addDiagnostics([partialDiagnostic], origin); } - addDiagnostics(partials: PartialDiagnostics, origin?: DiagnosticOrigin) { + addDiagnostics(partials: Diagnostics, origin?: DiagnosticOrigin) { if (partials.length === 0) { return; } @@ -379,7 +392,8 @@ export default class DiagnosticsPrinter extends Error { displayDiagnostic(diag: Diagnostic) { const {reporter} = this; - const {start, end, filename} = diag; + const {start, end, filename} = diag.location; + const {advice} = diag.description; // Determine if we should skip showing the frame at the top of the diagnostic output @@ -387,10 +401,13 @@ export default class DiagnosticsPrinter extends Error { // useful for stuff like reporting call stacks let skipFrame = false; - if (start !== undefined && end !== undefined) { - adviceLoop: for (const item of diag.advice) { - if (item.type === 'frame' && item.filename === filename && - equalPosition(item.start, start) && equalPosition(item.end, end)) { + if (start !== undefined && end !== undefined && advice !== undefined) { + adviceLoop: for (const item of advice) { + if (item.type === 'frame' && item.location.filename === filename && + equalPosition(item.location.start, start) && equalPosition( + item.location.end, + end, + )) { skipFrame = true; break; } @@ -419,7 +436,7 @@ export default class DiagnosticsPrinter extends Error { } } - const outdatedAdvice: PartialDiagnosticAdvice = []; + const outdatedAdvice: DiagnosticAdvice = []; const isOutdated = outdatedFiles.size > 0; if (isOutdated) { const outdatedFilesArr = Array.from(outdatedFiles, (path) => path.join()); @@ -456,17 +473,16 @@ export default class DiagnosticsPrinter extends Error { reporter.indent(() => { // Concat all the advice together - const derivedAdvice: DiagnosticAdvice = [ + const advice: DiagnosticAdvice = [ ...derived.advice, ...outdatedAdvice, - ].map((item) => - normalizeDiagnosticAdviceItem(diag, item, this.reporter.markupOptions) - ); - const advice: DiagnosticAdvice = derivedAdvice.concat(diag.advice); + ...(diag.description.advice || []), + ]; // Print advice for (const item of advice) { const noSpacer = printAdvice(item, { + printer: this, flags: this.flags, missingFileSources: this.missingFileSources, fileSources: this.fileSources, @@ -482,7 +498,7 @@ export default class DiagnosticsPrinter extends Error { if (this.flags.verboseDiagnostics) { const {origins} = diag; - if (origins.length > 0) { + if (origins !== undefined && origins.length > 0) { reporter.spacer(); reporter.info('Why are you seeing this diagnostic?'); reporter.forceSpacer(); diff --git a/packages/@romejs/cli-diagnostics/ansiHighlightCode.ts b/packages/@romejs/cli-diagnostics/ansiHighlightCode.ts index 99951b72753..20a8d78a365 100644 --- a/packages/@romejs/cli-diagnostics/ansiHighlightCode.ts +++ b/packages/@romejs/cli-diagnostics/ansiHighlightCode.ts @@ -19,8 +19,8 @@ const FILE_SIZE_MAX = 100_000; export type AnsiHighlightOptions = { path: UnknownFilePath; input: string; - sourceType: DiagnosticSourceType; - language: DiagnosticLanguage; + sourceType: undefined | DiagnosticSourceType; + language: undefined | DiagnosticLanguage; }; export default function ansiHighlightCode(opts: AnsiHighlightOptions): string { @@ -30,9 +30,8 @@ export default function ansiHighlightCode(opts: AnsiHighlightOptions): string { if (opts.language === 'js') { // js-parser does not accept an "unknown" sourceType - return ansiHighlightJS(opts.input, opts.sourceType === 'unknown' - ? 'script' : opts.sourceType - ); + return ansiHighlightJS(opts.input, opts.sourceType === undefined || + opts.sourceType === 'unknown' ? 'script' : opts.sourceType); } if (opts.language === 'json') { diff --git a/packages/@romejs/cli-diagnostics/buildMessageCodeFrame.ts b/packages/@romejs/cli-diagnostics/buildMessageCodeFrame.ts index ac1c54c3036..7f79d1b1a88 100644 --- a/packages/@romejs/cli-diagnostics/buildMessageCodeFrame.ts +++ b/packages/@romejs/cli-diagnostics/buildMessageCodeFrame.ts @@ -31,13 +31,17 @@ import { export default function buildMessageCodeFrame( allLines: Array, - start: Position, - end: Position, + start: undefined | Position, + end: undefined | Position, maybeMarkerMessage?: string, ): string { let markerMessage: string = maybeMarkerMessage === undefined ? '' : maybeMarkerMessage; + if (start === undefined || end === undefined) { + return CODE_FRAME_INDENT + markerMessage; + } + const startLineIndex = coerce1to0(start.line); let endLineIndex = coerce1to0(end.line); diff --git a/packages/@romejs/cli-diagnostics/index.ts b/packages/@romejs/cli-diagnostics/index.ts index 3f6e26f64c0..d77252b67ad 100644 --- a/packages/@romejs/cli-diagnostics/index.ts +++ b/packages/@romejs/cli-diagnostics/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {DiagnosticsPrinterOptions} from './types'; import {Reporter, ReporterStream} from '@romejs/cli-reporter'; import DiagnosticsPrinter from './DiagnosticsPrinter'; @@ -24,7 +24,7 @@ export * from './types'; // Simple wrappers around DiagnosticsPrinter export async function printDiagnostics( - diagnostics: PartialDiagnostics, + diagnostics: Diagnostics, opts: DiagnosticsPrinterOptions, ): Promise { const printer = new DiagnosticsPrinter(opts); @@ -34,7 +34,7 @@ export async function printDiagnostics( } export function printDiagnosticsSync( - diagnostics: PartialDiagnostics, + diagnostics: Diagnostics, opts: DiagnosticsPrinterOptions, ): DiagnosticsPrinter { const printer = new DiagnosticsPrinter(opts); @@ -44,7 +44,7 @@ export function printDiagnosticsSync( } export function printDiagnosticsToString( - diagnostics: PartialDiagnostics, + diagnostics: Diagnostics, opts: Omit = {}, format: ReporterStream['format'] = 'none', ): string { diff --git a/packages/@romejs/cli-diagnostics/printAdvice.ts b/packages/@romejs/cli-diagnostics/printAdvice.ts index 9f9e58eba35..88cb3a47cbd 100644 --- a/packages/@romejs/cli-diagnostics/printAdvice.ts +++ b/packages/@romejs/cli-diagnostics/printAdvice.ts @@ -9,13 +9,13 @@ import {Reporter} from '@romejs/cli-reporter'; import { Diagnostic, DiagnosticAdviceItem, - DiagnosticAdviceItemLog, - DiagnosticAdviceItemList, - DiagnosticAdviceItemCode, - DiagnosticAdviceItemFrame, - DiagnosticAdviceItemInspect, - DiagnosticAdviceItemDiff, - DiagnosticAdviceItemStacktrace, + DiagnosticAdviceLog, + DiagnosticAdviceList, + DiagnosticAdviceCode, + DiagnosticAdviceFrame, + DiagnosticAdviceInspect, + DiagnosticAdviceDiff, + DiagnosticAdviceStacktrace, } from '@romejs/diagnostics'; import {Position} from '@romejs/parser-core'; import {toLines} from './utils'; @@ -27,9 +27,11 @@ import {formatAnsi} from '@romejs/string-ansi'; import {DiagnosticsPrinterFlags} from './types'; import {number0Neg1} from '@romejs/ob1'; import {DiagnosticsPrinterFileSources} from './DiagnosticsPrinter'; -import {createUnknownFilePath, AbsoluteFilePathSet} from '@romejs/path'; +import {AbsoluteFilePathSet} from '@romejs/path'; +import DiagnosticsPrinter from './DiagnosticsPrinter'; type AdvicePrintOptions = { + printer: DiagnosticsPrinter; flags: DiagnosticsPrinterFlags; missingFileSources: AbsoluteFilePathSet; fileSources: DiagnosticsPrinterFileSources; @@ -66,7 +68,7 @@ export default function printAdvice( } function printInspect( - item: DiagnosticAdviceItemInspect, + item: DiagnosticAdviceInspect, opts: AdvicePrintOptions, ): boolean { const {reporter} = opts; @@ -76,10 +78,7 @@ function printInspect( return false; } -function printDiff( - item: DiagnosticAdviceItemDiff, - opts: AdvicePrintOptions, -): boolean { +function printDiff(item: DiagnosticAdviceDiff, opts: AdvicePrintOptions): boolean { const frame = buildPatchCodeFrame(item.diff); if (frame === '') { return true; @@ -98,10 +97,7 @@ function printDiff( return false; } -function printList( - item: DiagnosticAdviceItemList, - opts: AdvicePrintOptions, -): boolean { +function printList(item: DiagnosticAdviceList, opts: AdvicePrintOptions): boolean { if (item.list.length === 0) { return true; } else { @@ -114,10 +110,7 @@ function printList( } } -function printCode( - item: DiagnosticAdviceItemCode, - opts: AdvicePrintOptions, -): boolean { +function printCode(item: DiagnosticAdviceCode, opts: AdvicePrintOptions): boolean { const {reporter} = opts; const {code} = item; reporter.indent(() => { @@ -127,12 +120,13 @@ function printCode( } function printFrame( - item: DiagnosticAdviceItemFrame, + item: DiagnosticAdviceFrame, opts: AdvicePrintOptions, ): boolean { const {reporter} = opts; - const {start, end, filename, sourceText, marker} = item; - const path = createUnknownFilePath(filename); + const {marker} = item; + const {start, end, filename, sourceText} = item.location; + const path = opts.printer.createFilePath(filename); let cleanMarker: string = ''; if (marker !== undefined) { @@ -144,8 +138,8 @@ function printFrame( lines = toLines({ path, input: sourceText, - sourceType: item.sourceType, - language: item.language, + sourceType: item.location.sourceType, + language: item.location.language, }); } else if (filename !== undefined) { lines = opts.fileSources.get(path); @@ -169,7 +163,7 @@ function printFrame( } function printStacktrace( - item: DiagnosticAdviceItemStacktrace, + item: DiagnosticAdviceStacktrace, opts: AdvicePrintOptions, ): boolean { // Here we duplicate some of the list logic that is in Reporter @@ -181,7 +175,8 @@ function printStacktrace( let shownCodeFrames = 0; - const isFirstPart = diagnostic.advice[0] === item; + const isFirstPart = diagnostic.description.advice !== undefined && + diagnostic.description.advice[0] === item; if (!isFirstPart) { opts.reporter.info(item.title === undefined ? 'Stack trace' : item.title); opts.reporter.forceSpacer(); @@ -255,14 +250,16 @@ function printStacktrace( const skipped = printFrame({ type: 'frame', - language, - filename, - sourceType: 'module', marker: undefined, - mtime: undefined, - start: pos, - end: pos, - sourceText: code, + location: { + language, + filename, + sourceType: 'module', + mtime: undefined, + start: pos, + end: pos, + sourceText: code, + }, }, opts); if (!skipped) { opts.reporter.forceSpacer(); @@ -277,10 +274,7 @@ function printStacktrace( return false; } -function printLog( - item: DiagnosticAdviceItemLog, - opts: AdvicePrintOptions, -): boolean { +function printLog(item: DiagnosticAdviceLog, opts: AdvicePrintOptions): boolean { const {reporter} = opts; const {message, category} = item; @@ -307,7 +301,7 @@ function printLog( } } - return item.compact; + return item.compact === true; } function cleanMessage(msg: string): string { diff --git a/packages/@romejs/cli-flags/serializeCLIFlags.ts b/packages/@romejs/cli-flags/serializeCLIFlags.ts index 18e8ceacb57..a06c90190e9 100644 --- a/packages/@romejs/cli-flags/serializeCLIFlags.ts +++ b/packages/@romejs/cli-flags/serializeCLIFlags.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {DiagnosticPointer} from '@romejs/diagnostics'; +import {DiagnosticLocation} from '@romejs/diagnostics'; import {toKebabCase} from '@romejs/string-utils'; import {ConsumeSourceLocationRequestTarget} from '@romejs/consume'; import {Number0, coerce0, number1, number0Neg1} from '@romejs/ob1'; @@ -49,7 +49,7 @@ function normalizeFlagValue(val: unknown): unknown { export function serializeCLIFlags( data: SerializeCLIData, cliTarget: SerializeCLITarget, -): DiagnosticPointer { +): DiagnosticLocation { const {args, flags, defaultFlags} = data; let code = `$ `; diff --git a/packages/@romejs/codec-js-manifest/index.ts b/packages/@romejs/codec-js-manifest/index.ts index 8c5045b32ef..4df49c224f6 100644 --- a/packages/@romejs/codec-js-manifest/index.ts +++ b/packages/@romejs/codec-js-manifest/index.ts @@ -23,7 +23,7 @@ import { } from './types'; import {tryParseWithOptionalOffsetPosition} from '@romejs/parser-core'; import {normalizeName} from './name'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import { AbsoluteFilePath, createRelativeFilePath, @@ -568,7 +568,7 @@ export async function normalizeManifest( consumer: Consumer, ): Promise<{ manifest: Manifest; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; }> { const loose = path.getSegments().includes('node_modules'); diff --git a/packages/@romejs/codec-js-manifest/name.ts b/packages/@romejs/codec-js-manifest/name.ts index 0932277bd72..6d5c8639704 100644 --- a/packages/@romejs/codec-js-manifest/name.ts +++ b/packages/@romejs/codec-js-manifest/name.ts @@ -7,13 +7,13 @@ import {number0, Number0, coerce0, inc, add} from '@romejs/ob1'; import {escapeMarkup} from '@romejs/string-markup'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {DiagnosticAdvice} from '@romejs/diagnostics'; type NormalizeNameUnexpected = (opts: { message: string; start?: Number0; end?: Number0; - advice?: PartialDiagnosticAdvice; + advice?: DiagnosticAdvice; at?: 'prefix'; }) => void; diff --git a/packages/@romejs/codec-js-regexp/index.ts b/packages/@romejs/codec-js-regexp/index.ts index fcb1cd783ad..2a898ab26fe 100644 --- a/packages/@romejs/codec-js-regexp/index.ts +++ b/packages/@romejs/codec-js-regexp/index.ts @@ -30,7 +30,7 @@ import { RegExpAlternation, AnyRegExpExpression, } from '@romejs/js-ast'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics, descriptions} from '@romejs/diagnostics'; import {Number0, get0, add} from '@romejs/ob1'; type Operator = @@ -103,7 +103,7 @@ export const createRegExpParser = createParser((ParserCore) => this.unicode = opts.unicode; } - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; unicode: boolean; addDiagnostic(opts: ParserUnexpectedOptions) { @@ -372,7 +372,7 @@ export const createRegExpParser = createParser((ParserCore) => } this.addDiagnostic({ - message: 'Invalid capture group modifier', + ...descriptions.REGEX_PARSER.INVALID_CAPTURE_GROUP_MODIFIER, token, }); } @@ -404,7 +404,7 @@ export const createRegExpParser = createParser((ParserCore) => if (!this.eatOperator(')')) { this.addDiagnostic({ - message: 'Unclosed group', + ...descriptions.REGEX_PARSER.UNCLOSED_GROUP, start, }); } @@ -441,7 +441,7 @@ export const createRegExpParser = createParser((ParserCore) => if (!this.eatOperator(']')) { this.addDiagnostic({ - message: 'Unclosed character set', + ...descriptions.REGEX_PARSER.UNCLOSED_CHAR_SET, start, }); } @@ -567,7 +567,7 @@ export const createRegExpParser = createParser((ParserCore) => getCodePoint(end.value) < getCodePoint(start.value) ) { this.addDiagnostic({ - message: 'Range values reversed. Start char code is greater than end char code', + ...descriptions.REGEX_PARSER.REVERSED_CHAR_SET_RANGE, loc, }); const _end = end; @@ -725,7 +725,7 @@ export const createRegExpParser = createParser((ParserCore) => case ')': this.nextToken(); this.addDiagnostic({ - message: 'Unopened group', + ...descriptions.REGEX_PARSER.UNOPENED_GROUP, token, }); return; @@ -735,7 +735,7 @@ export const createRegExpParser = createParser((ParserCore) => case '+': this.nextToken(); this.addDiagnostic({ - message: 'Invalid target for quantifier', + ...descriptions.REGEX_PARSER.INVALID_QUANTIFIER_TARGET, token, }); return; @@ -759,7 +759,7 @@ export const createRegExpParser = createParser((ParserCore) => } this.addDiagnostic({ - message: 'Unknown regex part', + ...descriptions.REGEX_PARSER.UNKNOWN_REGEX_PART, token, }); } @@ -841,7 +841,7 @@ export const createRegExpParser = createParser((ParserCore) => parse(): { expression: AnyRegExpExpression; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; } { return { expression: this.parseExpression(), diff --git a/packages/@romejs/codec-json/index.ts b/packages/@romejs/codec-json/index.ts index 3d6a4b3266d..044911200af 100644 --- a/packages/@romejs/codec-json/index.ts +++ b/packages/@romejs/codec-json/index.ts @@ -63,5 +63,3 @@ export function stringifyJSON( ): string { return stringifyRootConsumer(opts.consumer, opts.comments); } - -export {default as messages} from './messages'; diff --git a/packages/@romejs/codec-json/messages.ts b/packages/@romejs/codec-json/messages.ts deleted file mode 100644 index 9a07fccbc7c..00000000000 --- a/packages/@romejs/codec-json/messages.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {createMessageFactory} from '@romejs/messages'; - -export default createMessageFactory({ - SINGLE_QUOTE_USAGE: 'You can only use double quoted strings', - TRAILING_COMMA_VALUE: 'Trailing comma is only allowed after a value', - UNCLOSED_STRING: 'Unclosed string', - UNCLOSED_BLOCK_COMMENT: 'Unclosed block comment', - MISTAKEN_ARRAY_IDENTITY: 'Trying to use an array element as an object property. Did you mean to make an object?', - REDUNDANT_COMMA: 'Redundant comma', - - EMPTY_INPUT_IN_JSON: 'Empty input', - PROPERTY_KEY_UNQUOTED_IN_JSON: 'Property keys must be quoted in JSON', - IMPLICIT_OBJECT_IN_JSON: 'Objects must be wrapped in curly braces in JSON', - COMMENTS_IN_JSON: 'Comments aren\'t allowed in JSON', - TRAILING_COMMA_IN_JSON: 'Trailing commas aren\'t allowed in JSON', - REGEX_IN_JSON: 'Regular expressions aren\'t allowed in JSON', - UNKNOWN_WORD_IN_JSON: '$0 isn\'t a valid JSON word', - STRING_NEWLINES_IN_JSON: 'Newlines aren\'t allowed in JSON, you insert a newline by escaping it like this "\\n"', - UNDEFINED_IN_JSON: 'undefined isn\'t allowed in JSON, you could use null instead', - BIGINT_IN_JSON: 'Bigints aren\'t allowed in JSON', - NUMERIC_SEPARATORS_IN_JSON: 'Numeric separators are not allowed in JSON', -}); diff --git a/packages/@romejs/codec-json/parse.ts b/packages/@romejs/codec-json/parse.ts index 43af87689b1..188b39759fc 100644 --- a/packages/@romejs/codec-json/parse.ts +++ b/packages/@romejs/codec-json/parse.ts @@ -5,7 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -import {DiagnosticPointer, DiagnosticCategory} from '@romejs/diagnostics'; +import { + DiagnosticLocation, + DiagnosticCategory, + descriptions, +} from '@romejs/diagnostics'; import { JSONParserResult, JSONParserOptions, @@ -22,7 +26,6 @@ import { ConsumeSourceLocationRequestTarget, } from '@romejs/consume'; import {unescapeString} from '@romejs/string-escape'; -import messages from './messages'; import { isAlpha, isDigit, @@ -184,7 +187,7 @@ export default createParser((ParserCore) => if (this.input[get0(endIndex) - 2] !== '*' || this.input[get0(endIndex) - 1] !== '/') { throw this.unexpected({ - message: messages.UNCLOSED_BLOCK_COMMENT(), + description: descriptions.JSON.UNCLOSED_BLOCK_COMMENT, start: this.getPositionFromIndex(endIndex), }); } @@ -201,7 +204,7 @@ export default createParser((ParserCore) => const end = add(add(index, value.length), 2); if (input[get0(end) - 1] !== '"') { throw this.unexpected({ - message: messages.UNCLOSED_STRING(), + description: descriptions.JSON.UNCLOSED_STRING, start: this.getPositionFromIndex(end), }); } @@ -212,16 +215,16 @@ export default createParser((ParserCore) => if (char === '\n') { throw this.unexpected({ - message: messages.STRING_NEWLINES_IN_JSON(), + description: descriptions.JSON.STRING_NEWLINES_IN_JSON, start: this.getPositionFromIndex(add(index, strIndex)), }); } } // Unescape the string - const unescaped = unescapeString(value, (message, strIndex) => { + const unescaped = unescapeString(value, (metadata, strIndex) => { throw this.unexpected({ - message, + description: metadata, start: this.getPositionFromIndex(add(index, strIndex)), }); }); @@ -230,13 +233,13 @@ export default createParser((ParserCore) => case '\'': throw this.unexpected({ - message: messages.SINGLE_QUOTE_USAGE(), + description: descriptions.JSON.SINGLE_QUOTE_USAGE, start: this.getPositionFromIndex(index), }); case '/': throw this.unexpected({ - message: messages.REGEX_IN_JSON(), + description: descriptions.JSON.REGEX_IN_JSON, start: this.getPositionFromIndex(index), }); @@ -316,7 +319,7 @@ export default createParser((ParserCore) => // Throw a meainingful error for redundant commas if (this.matchToken('Comma')) { throw this.unexpected({ - message: messages.REDUNDANT_COMMA(), + description: descriptions.JSON.REDUNDANT_COMMA, }); } @@ -428,7 +431,7 @@ export default createParser((ParserCore) => // Don't allow separators in JSON if (!this.hasExtensions) { throw this.unexpected({ - message: messages.NUMERIC_SEPARATORS_IN_JSON(), + description: descriptions.JSON.NUMERIC_SEPARATORS_IN_JSON, start: this.getPositionFromIndex(inc(index)), }); } @@ -462,7 +465,9 @@ export default createParser((ParserCore) => // Comments aren't allowed in regular JSON if (!this.hasExtensions) { - throw this.unexpected({message: messages.COMMENTS_IN_JSON()}); + throw this.unexpected({ + description: descriptions.JSON.COMMENTS_IN_JSON, + }); } this.nextToken(); @@ -488,7 +493,7 @@ export default createParser((ParserCore) => if (this.matchToken('Comma')) { throw this.unexpected({ - message: messages.REDUNDANT_COMMA(), + description: descriptions.JSON.REDUNDANT_COMMA, }); } @@ -526,7 +531,7 @@ export default createParser((ParserCore) => // Have a meaningful error message when an object is incorrectly using brackets: ["foo": "bar"] if (this.matchToken('Colon')) { throw this.unexpected({ - message: messages.MISTAKEN_ARRAY_IDENTITY(), + description: descriptions.JSON.MISTAKEN_ARRAY_IDENTITY, }); } } while (this.eatPropertySeparator()); @@ -568,7 +573,9 @@ export default createParser((ParserCore) => // Make sure this isn't a trailing comma const lookahead = this.lookaheadToken(); if (lookahead.type === 'BraceClose' || lookahead.type === 'BracketClose') { - throw this.unexpected({message: messages.TRAILING_COMMA_IN_JSON()}); + throw this.unexpected({ + description: descriptions.JSON.TRAILING_COMMA_IN_JSON, + }); } this.nextToken(); @@ -591,7 +598,9 @@ export default createParser((ParserCore) => return null; case 'undefined': - throw this.unexpected({message: messages.UNDEFINED_IN_JSON()}); + throw this.unexpected({ + description: descriptions.JSON.UNDEFINED_IN_JSON, + }); } if (isStart && this.matchToken('Colon')) { @@ -599,13 +608,13 @@ export default createParser((ParserCore) => return this.parseObject(start, token.value); } else { throw this.unexpected({ - message: messages.IMPLICIT_OBJECT_IN_JSON(), + description: descriptions.JSON.IMPLICIT_OBJECT_IN_JSON, }); } } throw this.unexpected({ - message: messages.UNKNOWN_WORD_IN_JSON(token.value), + description: descriptions.JSON.UNKNOWN_WORD_IN_JSON(token.value), }); } @@ -650,7 +659,7 @@ export default createParser((ParserCore) => const nextToken2 = this.getToken(); if (nextToken2.type === 'Word' && nextToken2.value === 'n') { throw this.unexpected({ - message: messages.BIGINT_IN_JSON(), + description: descriptions.JSON.BIGINT_IN_JSON, }); } @@ -676,7 +685,7 @@ export default createParser((ParserCore) => return token.value; } else { throw this.unexpected({ - message: messages.PROPERTY_KEY_UNQUOTED_IN_JSON(), + description: descriptions.JSON.PROPERTY_KEY_UNQUOTED_IN_JSON, }); } @@ -694,7 +703,7 @@ export default createParser((ParserCore) => return this.parseObject(start, token.value); } else { throw this.unexpected({ - message: messages.IMPLICIT_OBJECT_IN_JSON(), + description: descriptions.JSON.IMPLICIT_OBJECT_IN_JSON, }); } } else { @@ -734,7 +743,9 @@ export default createParser((ParserCore) => // If we're in RJSON mode then an empty input is an implicit object return {}; } else { - throw this.unexpected({message: messages.EMPTY_INPUT_IN_JSON()}); + throw this.unexpected({ + description: descriptions.JSON.EMPTY_INPUT_IN_JSON, + }); } } else { return this.parseExpression(true); @@ -814,10 +825,12 @@ export default createParser((ParserCore) => getDiagnosticPointer: ( keys: ConsumePath, target: ConsumeSourceLocationRequestTarget, - ): undefined | DiagnosticPointer => { + ): DiagnosticLocation => { const info = this.getPathInfo(keys); if (info === undefined) { - return; + return { + filename: this.filename, + }; } let start = info.keyStart; diff --git a/packages/@romejs/codec-json/parser.test.ts b/packages/@romejs/codec-json/parser.test.ts index 8258b5283f1..0f24cc5b111 100644 --- a/packages/@romejs/codec-json/parser.test.ts +++ b/packages/@romejs/codec-json/parser.test.ts @@ -6,7 +6,8 @@ */ import '@romejs/core'; -import {parseJSON, messages} from '@romejs/codec-json'; +import {descriptions} from '@romejs/diagnostics'; +import {parseJSON} from '@romejs/codec-json'; import test from '@romejs/test'; import {ParserOptions} from '@romejs/parser-core'; import {createUnknownFilePath} from '@romejs/path'; @@ -88,7 +89,7 @@ test('comments', (t) => { // ensure closed block comment t.throws(() => { parseExtJSON({input: 'true /* unclosed comment'}); - }, messages.UNCLOSED_BLOCK_COMMENT()); + }, descriptions.JSON.UNCLOSED_BLOCK_COMMENT.message.value); }); test('numbers', (t) => { @@ -111,15 +112,15 @@ test('strings', (t) => { t.throws(() => { parseExtJSON({input: '"foo'}); - }, messages.UNCLOSED_STRING()); + }, descriptions.JSON.UNCLOSED_STRING.message.value); t.throws(() => { parseExtJSON({input: '"foo\n"'}); - }, messages.UNCLOSED_STRING()); + }, descriptions.JSON.UNCLOSED_STRING.message.value); t.throws(() => { parseExtJSON({input: '\'foo\''}); - }, messages.SINGLE_QUOTE_USAGE()); + }, descriptions.JSON.SINGLE_QUOTE_USAGE.message.value); // TODO escMessage.INVALID_HEX_DIGIT_FOR_ESCAPE @@ -140,7 +141,7 @@ test('null', (t) => { test('undefined', (t) => { t.throws(() => { t.is(parseExtJSON({input: 'undefined'}), undefined); - }, messages.UNDEFINED_IN_JSON()); + }, descriptions.JSON.UNDEFINED_IN_JSON.message.value); }); test('arrays', (t) => { @@ -150,19 +151,19 @@ test('arrays', (t) => { t.throws(() => { parseExtJSON({input: '[,]'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); t.throws(() => { parseExtJSON({input: '[1,,]'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); t.throws(() => { parseExtJSON({input: '[1, /*comment*/,]'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); t.throws(() => { parseExtJSON({input: '["foo": "bar"]'}); - }, messages.MISTAKEN_ARRAY_IDENTITY()); + }, descriptions.JSON.MISTAKEN_ARRAY_IDENTITY.message.value); }); test('objects', (t) => { @@ -175,35 +176,35 @@ test('objects', (t) => { t.throws(() => { parseExtJSON({input: '{,}'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); t.throws(() => { parseExtJSON({input: '{"foo": "bar",,}'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); t.throws(() => { parseExtJSON({input: '{"foo": "bar", /*comment*/,}'}); - }, messages.REDUNDANT_COMMA()); + }, descriptions.JSON.REDUNDANT_COMMA.message.value); }); test('regular JSON', (t) => { t.throws(() => { parseJSON({input: '{foo: "bar"}'}); - }, messages.PROPERTY_KEY_UNQUOTED_IN_JSON()); + }, descriptions.JSON.PROPERTY_KEY_UNQUOTED_IN_JSON.message.value); t.throws(() => { parseJSON({input: '// foobar\ntrue'}); - }, messages.COMMENTS_IN_JSON()); + }, descriptions.JSON.COMMENTS_IN_JSON.message.value); t.throws(() => { parseJSON({input: '/* foobar */\ntrue'}); - }, messages.COMMENTS_IN_JSON()); + }, descriptions.JSON.COMMENTS_IN_JSON.message.value); t.throws(() => { parseJSON({input: '{"foo": "bar",}'}); - }, messages.TRAILING_COMMA_IN_JSON()); + }, descriptions.JSON.TRAILING_COMMA_IN_JSON.message.value); t.throws(() => { parseJSON({input: '["foo",]'}); - }, messages.TRAILING_COMMA_IN_JSON()); + }, descriptions.JSON.TRAILING_COMMA_IN_JSON.message.value); }); diff --git a/packages/@romejs/codec-semver/parse.ts b/packages/@romejs/codec-semver/parse.ts index 8216d9ee779..08fd46994a4 100644 --- a/packages/@romejs/codec-semver/parse.ts +++ b/packages/@romejs/codec-semver/parse.ts @@ -19,9 +19,9 @@ import { Tokens, } from './types'; import {TokenValues, ParserOptions} from '@romejs/parser-core'; -import {markup} from '@romejs/string-markup'; import {createParser, isAlpha, isDigit} from '@romejs/parser-core'; import {Number0, add, get0} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; type ParseMode = 'version' | 'range'; @@ -143,7 +143,7 @@ const createSemverParser = createParser((ParserCore) => minor = this.parseVersionNumber(); } else if (this.mode === 'version') { throw this.unexpected({ - message: 'A minor number is required for a version', + description: descriptions.SEMVER.MISSING_MINOR_VERSION, }); } @@ -151,12 +151,14 @@ const createSemverParser = createParser((ParserCore) => patch = this.parseVersionNumber(); } else if (this.mode === 'version') { throw this.unexpected({ - message: 'A patch number is required for a version', + description: descriptions.SEMVER.MISSING_PATCH_VERSION, }); } if (this.matchToken('Dot')) { - throw this.unexpected({message: 'Too many parts for version'}); + throw this.unexpected({ + description: descriptions.SEMVER.EXCESSIVE_VERSION_PARTS, + }); } // The dash is optional in loose mode. eg. 1.2.3pre @@ -214,7 +216,9 @@ const createSemverParser = createParser((ParserCore) => this.nextToken(); parts.push('-'); } else { - throw this.unexpected({message: 'Invalid version qualifier part'}); + throw this.unexpected({ + description: descriptions.SEMVER.INVALID_QUANTIFIER_PART, + }); } } while (this.matchToken('Number') || this.matchToken('Word') || this.matchToken('Dash')); @@ -249,14 +253,14 @@ const createSemverParser = createParser((ParserCore) => if (this.isWildcardToken(token)) { if (this.mode === 'version') { throw this.unexpected({ - message: 'Wildcard aren\'t allowed in a hard version', + description: descriptions.SEMVER.WILDCARD_IN_VERSION, }); } this.nextToken(); } else { throw this.unexpected({ - message: 'This isn\'t a valid version part, expected a number', + description: descriptions.SEMVER.INVALID_VERSION_NUMBER, }); } @@ -289,7 +293,7 @@ const createSemverParser = createParser((ParserCore) => } throw this.unexpected({ - message: 'A semver range can only be defined with versions', + ...descriptions.SEMVER.INVALID_RANGE, start: this.getLoc(node).start, }); } @@ -347,7 +351,7 @@ const createSemverParser = createParser((ParserCore) => return this.parseWildcard(); } else { throw this.unexpected({ - message: 'Bare pipes are only allowed in loose mode', + description: descriptions.SEMVER.BARE_PIPE_WITHOUT_LOOSE, }); } } @@ -359,7 +363,7 @@ const createSemverParser = createParser((ParserCore) => return this.parseVersion(); } else { throw this.unexpected({ - message: markup`Unexpected word ${token.value}`, + description: descriptions.SEMVER.UNEXPECTED_WORD(token.value), }); } } @@ -384,7 +388,9 @@ const createSemverParser = createParser((ParserCore) => return this.parseAtomStartWord(token); default: - throw this.unexpected({message: 'Unknown start of atom'}); + throw this.unexpected({ + description: descriptions.SEMVER.UNKNOWN_START, + }); } } @@ -443,7 +449,7 @@ const createSemverParser = createParser((ParserCore) => // Verify the return value in version mode if (node.type !== 'AbsoluteVersion') { throw this.unexpected({ - message: 'Unexpected value for version', + ...descriptions.SEMVER.EXPECTED_VERSION, start: this.getLoc(node).start, }); } diff --git a/packages/@romejs/codec-spdx-license/parse.ts b/packages/@romejs/codec-spdx-license/parse.ts index ae9672fe6dd..b6d9c096eff 100644 --- a/packages/@romejs/codec-spdx-license/parse.ts +++ b/packages/@romejs/codec-spdx-license/parse.ts @@ -15,7 +15,7 @@ import { } from '@romejs/parser-core'; import {getSPDXLicense, licenseNames} from './index'; import {isAlpha, isDigit} from '@romejs/parser-core'; -import {buildSuggestionAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {inc, Number0, get0} from '@romejs/ob1'; //# Tokens @@ -124,16 +124,11 @@ const createSPDXLicenseParser = createParser((ParserCore) => this.nextToken(); } else { throw this.unexpected({ - message: `Missing dash between SPDX license name and version`, + description: descriptions.SPDX.VALID_LICENSE_WITH_MISSING_DASH( + possibleCorrectLicense, + ), start: this.getPositionFromIndex(token.start), end: this.getPositionFromIndex(nextToken.end), - advice: [ - { - type: 'log', - category: 'info', - message: `Did you mean ${possibleCorrectLicense}?`, - }, - ], }); } } @@ -141,10 +136,9 @@ const createSPDXLicenseParser = createParser((ParserCore) => if (licenseInfo === undefined) { throw this.unexpected({ - message: `Unknown SPDX license ${id}`, + description: descriptions.SPDX.UNKNOWN_LICENSE(id, licenseNames), start: this.getPositionFromIndex(token.start), end: this.getPositionFromIndex(token.end), - advice: buildSuggestionAdvice(id, licenseNames), }); } @@ -160,7 +154,7 @@ const createSPDXLicenseParser = createParser((ParserCore) => this.nextToken(); } else { throw this.unexpected({ - message: 'Only a license id can be on the right side of a WITH', + description: descriptions.SPDX.WITH_RIGHT_LICENSE_ONLY, }); } } @@ -194,19 +188,18 @@ const createSPDXLicenseParser = createParser((ParserCore) => case 'Or': case 'And': throw this.unexpected({ - message: 'Can only use AND/OR in between an expression', + description: descriptions.SPDX.OPERATOR_NOT_BETWEEN_EXPRESSION, }); case 'Plus': throw this.unexpected({ - message: 'A plus can only come after a license id', + description: descriptions.SPDX.PLUS_NOT_AFTER_LICENSE, }); case 'ParenClose': - throw this.unexpected({message: 'Nothing open to close'}); - - case 'EOF': - throw this.unexpected({message: 'Unexpected end of file'}); + throw this.unexpected({ + description: descriptions.SPDX.UNOPENED_PAREN, + }); default: throw this.unexpected(); diff --git a/packages/@romejs/consume/Consumer.ts b/packages/@romejs/consume/Consumer.ts index 753cd78097d..561a5443e5e 100644 --- a/packages/@romejs/consume/Consumer.ts +++ b/packages/@romejs/consume/Consumer.ts @@ -6,14 +6,16 @@ */ import { - PartialDiagnosticAdvice, - PartialDiagnostics, - PartialDiagnostic, + DiagnosticAdvice, + Diagnostics, + Diagnostic, DiagnosticsError, - DiagnosticPointer, + DiagnosticLocation, getDiagnosticsFromError, DiagnosticCategory, buildSuggestionAdvice, + createBlessedDiagnosticMessage, + createSingleDiagnosticError, } from '@romejs/diagnostics'; import {UnknownObject} from '@romejs/typescript-helpers'; import { @@ -58,7 +60,7 @@ type UnexpectedConsumerOptions = { category?: DiagnosticCategory; loc?: SourceLocation; target?: ConsumeSourceLocationRequestTarget; - advice?: PartialDiagnosticAdvice; + advice?: DiagnosticAdvice; at?: 'suffix' | 'prefix' | 'none'; atParent?: boolean; }; @@ -137,9 +139,9 @@ export default class Consumer { ): Promise<{ result: T; definitions: Array; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; }> { - let diagnostics: PartialDiagnostics = []; + let diagnostics: Diagnostics = []; const definitions: Array = []; const consumer = this.clone({ @@ -189,10 +191,10 @@ export default class Consumer { getDiagnosticPointer( target: ConsumeSourceLocationRequestTarget = 'all', - ): undefined | DiagnosticPointer { + ): DiagnosticLocation { const {getDiagnosticPointer} = this.context; if (getDiagnosticPointer === undefined) { - return undefined; + return {}; } const {forceDiagnosticTarget} = this; @@ -204,7 +206,8 @@ export default class Consumer { getLocation(target?: ConsumeSourceLocationRequestTarget): SourceLocation { const pointer = this.getDiagnosticPointer(target); - if (pointer === undefined) { + if (pointer === undefined || pointer.start === undefined || pointer.end === + undefined) { return { filename: this.filename, start: UNKNOWN_POSITION, @@ -302,7 +305,7 @@ export default class Consumer { unexpected(msg: string, opts: UnexpectedConsumerOptions = {}): DiagnosticsError { const {target = 'value'} = opts; - let {loc} = opts; + let loc: undefined | DiagnosticLocation = opts.loc; const {filename} = this; let pointer = this.getDiagnosticPointer(target); @@ -310,7 +313,7 @@ export default class Consumer { msg = this.generateUnexpectedMessage(msg, opts); - const advice: PartialDiagnosticAdvice = [...(opts.advice || [])]; + const advice: DiagnosticAdvice = [...(opts.advice || [])]; // Make the errors more descriptive if (fromSource) { @@ -364,21 +367,23 @@ export default class Consumer { }; } - const diagnostic: PartialDiagnostic = { - category: opts.category === undefined - ? this.context.category : opts.category, - filename: this.filename, - message: msg, - ...loc, - language: pointer.language, - mtime: pointer.mtime, - sourceText: pointer.sourceText, - advice, + const diagnostic: Diagnostic = { + description: { + category: opts.category === undefined + ? this.context.category : opts.category, + message: createBlessedDiagnosticMessage(msg), + advice, + }, + location: { + ...loc, + filename: this.filename, + language: pointer.language, + mtime: pointer.mtime, + sourceText: pointer.sourceText, + }, }; - const errMsg = - `Error occurred while consuming at ${loc.filename} (${loc.start.line}:${loc.start.column}): ${msg}`; - const err = new DiagnosticsError(errMsg, [diagnostic]); + const err = createSingleDiagnosticError(diagnostic); if (this.handleUnexpected === undefined) { throw err; diff --git a/packages/@romejs/consume/types.ts b/packages/@romejs/consume/types.ts index 2c765a2868f..40047e3427b 100644 --- a/packages/@romejs/consume/types.ts +++ b/packages/@romejs/consume/types.ts @@ -6,8 +6,8 @@ */ import { - DiagnosticPointer, - PartialDiagnostic, + DiagnosticLocation, + Diagnostic, DiagnosticCategory, } from '@romejs/diagnostics'; import Consumer from './Consumer'; @@ -28,9 +28,7 @@ export type ConsumeSourceLocationRequestTarget = export type ConsumeContext = { category: DiagnosticCategory; - getDiagnosticPointer?: (keys: ConsumePath, target: ConsumeSourceLocationRequestTarget) => - | undefined - | DiagnosticPointer; + getDiagnosticPointer?: (keys: ConsumePath, target: ConsumeSourceLocationRequestTarget) => DiagnosticLocation; getOriginalValue?: (path: ConsumePath) => unknown; }; @@ -68,7 +66,7 @@ export type ConsumePropertyDefinition = export type ConsumerOnDefinition = (definition: ConsumePropertyDefinition) => void; -export type ConsumerHandleUnexpected = (diagnostic: PartialDiagnostic) => void; +export type ConsumerHandleUnexpected = (diagnostic: Diagnostic) => void; export type ConsumerOptions = { handleUnexpectedDiagnostic?: ConsumerHandleUnexpected; diff --git a/packages/@romejs/core/common/bridges/TestWorkerBridge.ts b/packages/@romejs/core/common/bridges/TestWorkerBridge.ts index 9d942deebae..e21261952f3 100644 --- a/packages/@romejs/core/common/bridges/TestWorkerBridge.ts +++ b/packages/@romejs/core/common/bridges/TestWorkerBridge.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostic} from '@romejs/diagnostics'; +import {Diagnostic} from '@romejs/diagnostics'; import {SourceMap} from '@romejs/codec-source-map'; import {TestRunnerOptions} from '../../master/testing/types'; import {Bridge} from '@romejs/events'; @@ -62,7 +62,7 @@ export default class TestWorkerBridge extends Bridge { testError = this.createEvent<{ ref: undefined | TestRef; - diagnostic: PartialDiagnostic; + diagnostic: Diagnostic; }, void>({name: 'onTestError', direction: 'server<-client'}); testSuccess = this.createEvent<{ref: TestRef}, void>({ diff --git a/packages/@romejs/core/common/bridges/WorkerBridge.ts b/packages/@romejs/core/common/bridges/WorkerBridge.ts index 64ccdcbaee8..4a1d07983d2 100644 --- a/packages/@romejs/core/common/bridges/WorkerBridge.ts +++ b/packages/@romejs/core/common/bridges/WorkerBridge.ts @@ -12,7 +12,7 @@ import {Program, ConstSourceType} from '@romejs/js-ast'; import {CompileResult, TransformStageName} from '@romejs/js-compiler'; import {Profile} from '@romejs/v8'; import {ProfilingStartData} from './MasterBridge'; -import {PartialDiagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; import {ProjectConfigJSON} from '@romejs/project'; import {DiagnosticsError} from '@romejs/diagnostics'; import {Bridge} from '@romejs/events'; @@ -85,11 +85,11 @@ export type PrefetchedModuleSignatures = {[key: string]: export type WorkerFormatResult = { original: string; formatted: string; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; }; export type WorkerLintResult = { - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; suppressions: DiagnosticSuppressions; }; @@ -185,8 +185,7 @@ export default class WorkerBridge extends Bridge { hydrate(err, data) { return new DiagnosticsError( - String(err.message), - ( // rome-suppress lint/noExplicitAny + String(err.message),( // rome-suppress lint/noExplicitAny data.diagnostics as any), ); }, diff --git a/packages/@romejs/core/common/fileHandlers.ts b/packages/@romejs/core/common/fileHandlers.ts index 2c9eb46b335..69d47361712 100644 --- a/packages/@romejs/core/common/fileHandlers.ts +++ b/packages/@romejs/core/common/fileHandlers.ts @@ -9,7 +9,7 @@ import {ProjectConfig} from '@romejs/project'; import {FileReference} from '@romejs/core'; import {PrefetchedModuleSignatures} from '../common/bridges/WorkerBridge'; import Worker, {ParseResult} from '../worker/Worker'; -import {PartialDiagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; import * as compiler from '@romejs/js-compiler'; import {check as typeCheck} from '@romejs/js-analysis'; import {parseJSON, stringifyJSON, consumeJSONExtra} from '@romejs/codec-json'; @@ -84,7 +84,7 @@ export type ExtensionLintInfo = export type ExtensionLintResult = { sourceText: string; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; formatted: string; suppressions: DiagnosticSuppressions; }; diff --git a/packages/@romejs/core/common/types/analyzeDependencies.ts b/packages/@romejs/core/common/types/analyzeDependencies.ts index 9cc7594817c..af484c9cff1 100644 --- a/packages/@romejs/core/common/types/analyzeDependencies.ts +++ b/packages/@romejs/core/common/types/analyzeDependencies.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import { ConstExportModuleKind, ConstImportModuleKind, @@ -74,7 +74,7 @@ export type AnalyzeDependencyImportFirstUsage = Array< export type AnalyzeDependencyResult = { moduleType: AnalyzeModuleType; syntax: Array; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; firstTopAwaitLocation: undefined | SourceLocation; importFirstUsage: AnalyzeDependencyImportFirstUsage; exports: Array; diff --git a/packages/@romejs/core/common/types/bundler.ts b/packages/@romejs/core/common/types/bundler.ts index fd9f334b60c..4d4de848fe2 100644 --- a/packages/@romejs/core/common/types/bundler.ts +++ b/packages/@romejs/core/common/types/bundler.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {SourceMap} from '@romejs/codec-source-map'; import {AbsoluteFilePath} from '@romejs/path'; import {ResolverOptions} from '../../master/fs/Resolver'; @@ -22,7 +22,7 @@ export const BUNDLER_MODES: Array = ['modern', 'legacy']; export type BundleRequestResult = { cached: boolean; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; content: string; map: SourceMap; assets: Map; diff --git a/packages/@romejs/core/common/utils/executeMain.ts b/packages/@romejs/core/common/utils/executeMain.ts index 4bfcc6bb653..d9113c4e718 100644 --- a/packages/@romejs/core/common/utils/executeMain.ts +++ b/packages/@romejs/core/common/utils/executeMain.ts @@ -13,9 +13,10 @@ import internalModule = require('module'); import vm = require('vm'); import { - PartialDiagnostic, + Diagnostic, truncateSourceText, INTERNAL_ERROR_LOG_ADVICE, + descriptions, } from '@romejs/diagnostics'; import {AbsoluteFilePath} from '@romejs/path'; import {Position} from '@romejs/parser-core'; @@ -30,7 +31,7 @@ type ExecuteMainOptions = { export default async function executeMain( opts: ExecuteMainOptions, -): Promise<{syntaxError: undefined | PartialDiagnostic}> { +): Promise<{syntaxError: undefined | Diagnostic}> { const {path, code, sourceMap, globals} = opts; const filename = path.join(); @@ -83,14 +84,17 @@ export default async function executeMain( line: coerce1(line), }; - const syntaxError: PartialDiagnostic = { - message: err.message, - category: 'v8/syntaxError', - start: pos, - end: pos, - filename, - sourceText: truncateSourceText(code, pos, pos), - advice: [INTERNAL_ERROR_LOG_ADVICE], + const syntaxError: Diagnostic = { + description: { + ...descriptions.V8.SYNTAX_ERROR(err.message), + advice: [INTERNAL_ERROR_LOG_ADVICE], + }, + location: { + start: pos, + end: pos, + filename, + sourceText: truncateSourceText(code, pos, pos), + }, }; return {syntaxError}; } diff --git a/packages/@romejs/core/master/Master.ts b/packages/@romejs/core/master/Master.ts index 27aa8251192..5b155ea8893 100644 --- a/packages/@romejs/core/master/Master.ts +++ b/packages/@romejs/core/master/Master.ts @@ -12,7 +12,6 @@ import { } from '@romejs/core'; import { Diagnostics, - PartialDiagnostics, INTERNAL_ERROR_LOG_ADVICE, DiagnosticOrigin, } from '@romejs/diagnostics'; @@ -240,7 +239,7 @@ export default class Master { }) as T); } - async handleDisconnectedDiagnostics(diagnostics: PartialDiagnostics) { + async handleDisconnectedDiagnostics(diagnostics: Diagnostics) { this.connectedReporters.error( 'Generated diagnostics without a current request', ); @@ -269,7 +268,7 @@ export default class Master { origins: Array, ): DiagnosticsProcessor { return new DiagnosticsProcessor({ - onDiagnostics: (diagnostics: PartialDiagnostics) => { + onDiagnostics: (diagnostics: Diagnostics) => { this.handleDisconnectedDiagnostics(diagnostics); }, origins: [ @@ -877,7 +876,13 @@ export default class Master { }); printer.addDiagnostic({ ...errorDiag, - advice: [...(errorDiag.advice || []), INTERNAL_ERROR_LOG_ADVICE], + description: { + ...errorDiag.description, + advice: [ + ...(errorDiag.description.advice || []), + INTERNAL_ERROR_LOG_ADVICE, + ], + }, }); await printer.print(); diff --git a/packages/@romejs/core/master/MasterRequest.ts b/packages/@romejs/core/master/MasterRequest.ts index 7071ec009a7..5b602158ce4 100644 --- a/packages/@romejs/core/master/MasterRequest.ts +++ b/packages/@romejs/core/master/MasterRequest.ts @@ -11,13 +11,15 @@ import { } from '../common/types/client'; import {JSONFileReference} from '../common/types/files'; import { - DiagnosticPointer, + DiagnosticLocation, getDiagnosticsFromError, DiagnosticOrigin, - PartialDiagnosticAdvice, + DiagnosticAdvice, createSingleDiagnosticError, DiagnosticsError, DiagnosticCategory, + Diagnostic, + createBlessedDiagnosticMessage, } from '@romejs/diagnostics'; import {DiagnosticsPrinterFlags} from '@romejs/cli-diagnostics'; import {ProjectDefinition} from '@romejs/project'; @@ -199,22 +201,24 @@ export default class MasterRequest { throwDiagnosticFlagError( message: string, target: SerializeCLITarget = {type: 'none'}, - advice?: PartialDiagnosticAdvice, + advice?: DiagnosticAdvice, ) { const pointer = this.getDiagnosticPointerFromFlags(target); - throw new MasterRequestInvalid(message, [ - { - message, - filename: 'argv', + + const diag: Diagnostic = { + description: { + message: createBlessedDiagnosticMessage(message), category: target.type === 'arg' || target.type === 'arg-range' ? 'args/invalid' : 'flags/invalid', - ...pointer, advice, }, - ]); + location: pointer, + }; + + throw new MasterRequestInvalid(message, [diag]); } - getDiagnosticPointerForClientCwd(): DiagnosticPointer { + getDiagnosticPointerForClientCwd(): DiagnosticLocation { const cwd = this.client.flags.cwd.join(); return { sourceText: cwd, @@ -232,7 +236,7 @@ export default class MasterRequest { }; } - getDiagnosticPointerFromFlags(target: SerializeCLITarget): DiagnosticPointer { + getDiagnosticPointerFromFlags(target: SerializeCLITarget): DiagnosticLocation { const {query} = this; return serializeCLIFlags({ prefix: `rome ${query.commandName}`, @@ -280,7 +284,7 @@ export default class MasterRequest { & MemoryFSGlobOptions & { disabledDiagnosticCategory?: DiagnosticCategory; - advice?: PartialDiagnosticAdvice; + advice?: DiagnosticAdvice; configCategory?: string; verb?: string; noun?: string; @@ -297,7 +301,7 @@ export default class MasterRequest { const rawArgs = [...this.query.args]; const resolvedArgs: Array<{ path: AbsoluteFilePath; - pointer: DiagnosticPointer; + pointer: DiagnosticLocation; project: ProjectDefinition; }> = []; if (rawArgs.length === 0) { @@ -353,8 +357,9 @@ export default class MasterRequest { let category: DiagnosticCategory = 'args/fileNotFound'; - let advice: PartialDiagnosticAdvice = globOpts.advice === undefined - ? [] : [...globOpts.advice]; + let advice: DiagnosticAdvice = globOpts.advice === undefined ? [] : [ + ...globOpts.advice, + ]; // Hint if `path` failed `globOpts.test` if (globOpts.getProjectEnabled !== undefined) { @@ -392,12 +397,10 @@ export default class MasterRequest { const disabledPointer = testSource.value.getDiagnosticPointer( 'value', ); - if (disabledPointer !== undefined) { - advice.push({ - type: 'frame', - ...disabledPointer, - }); - } + advice.push({ + type: 'frame', + location: disabledPointer, + }); } } } @@ -431,28 +434,29 @@ export default class MasterRequest { 'value', ); - if (ignorePointer !== undefined) { - advice.push({ - type: 'log', - category: 'info', - message: 'Ignore patterns were defined here', - }); - - advice.push({ - type: 'frame', - ...ignorePointer, - }); - } + advice.push({ + type: 'log', + category: 'info', + message: 'Ignore patterns were defined here', + }); + + advice.push({ + type: 'frame', + location: ignorePointer, + }); } } } throw createSingleDiagnosticError({ - ...pointer, - category, - message: globOpts.noun === undefined - ? 'No files found' : `No files to ${globOpts.noun} found`, - advice, + location: pointer, + description: { + category, + message: createBlessedDiagnosticMessage(globOpts.noun === undefined + ? 'No files found' : `No files to ${globOpts.noun} found` + ), + advice, + }, }); } diff --git a/packages/@romejs/core/master/bundler/BundleRequest.ts b/packages/@romejs/core/master/bundler/BundleRequest.ts index 0fbf8da1e8e..de8c10dc373 100644 --- a/packages/@romejs/core/master/bundler/BundleRequest.ts +++ b/packages/@romejs/core/master/bundler/BundleRequest.ts @@ -16,7 +16,7 @@ import { import {DependencyOrder} from '../dependencies/DependencyOrderer'; import {CompileResult, BundleCompileResolvedImports} from '@romejs/js-compiler'; import {getPrefixedBundleNamespace} from '@romejs/js-compiler'; -import {DiagnosticsProcessor} from '@romejs/diagnostics'; +import {DiagnosticsProcessor, descriptions} from '@romejs/diagnostics'; import {SourceMapGenerator} from '@romejs/codec-source-map'; import {AbsoluteFilePath} from '@romejs/path'; import {add} from '@romejs/ob1'; @@ -241,12 +241,11 @@ export default class BundleRequest { if (mode === 'legacy') { for (const {loc, mtime} of order.firstTopAwaitLocations) { this.diagnostics.addDiagnostic({ - category: 'bundler/topLevelAwait', - filename: loc.filename, - start: loc.start, - end: loc.end, - message: 'This module contains a top level await which isn\'t supported in wrapper mode', - mtime, + description: descriptions.BUNDLER.TOP_LEVEL_AWAIT_IN_LEGACY, + location: { + ...loc, + mtime, + }, }); } } @@ -334,7 +333,7 @@ export default class BundleRequest { } return { - diagnostics: this.diagnostics.getPartialDiagnostics(), + diagnostics: this.diagnostics.getDiagnostics(), content, map: sourceMap.toJSON(), cached: this.cached, @@ -350,7 +349,7 @@ export default class BundleRequest { return { map: this.sourceMap.toJSON(), content: '', - diagnostics: this.diagnostics.getPartialDiagnostics(), + diagnostics: this.diagnostics.getDiagnostics(), cached: false, assets: this.assets, }; diff --git a/packages/@romejs/core/master/commands/format.ts b/packages/@romejs/core/master/commands/format.ts index 983c9835557..4ae1912263d 100644 --- a/packages/@romejs/core/master/commands/format.ts +++ b/packages/@romejs/core/master/commands/format.ts @@ -8,10 +8,9 @@ import {MasterRequest} from '@romejs/core'; import {createMasterCommand} from '../../commands'; import {commandCategories} from '../../commands'; -import {DiagnosticsProcessor} from '@romejs/diagnostics'; +import {DiagnosticsProcessor, descriptions} from '@romejs/diagnostics'; import {FORMATTABLE_EXTENSIONS} from '@romejs/core/common/fileHandlers'; import {Consumer} from '@romejs/consume'; -import stringDiff from '@romejs/string-diff'; type Flags = {write: boolean}; @@ -88,21 +87,14 @@ export default createMasterCommand({ } if (!flags.write && res.formatted !== res.original) { - // TODO abstract this and the pendingFixes diagnostic in WorkerAPI diagnosticsProcessor.addDiagnostic({ - category: 'lint/pendingFixes', - filename: path.join(), - message: 'Pending fixes', - advice: [ - { - type: 'diff', - diff: stringDiff(res.original, res.formatted), - }, - { - type: 'code', - code: res.formatted, - }, - ], + description: descriptions.LINT.PENDING_FIXES( + res.original, + res.formatted, + ), + location: { + filename: path.join(), + }, }); } else { //await writeFile(path, res.formatted); diff --git a/packages/@romejs/core/master/commands/lint.ts b/packages/@romejs/core/master/commands/lint.ts index d2589678e15..443d49d9adb 100644 --- a/packages/@romejs/core/master/commands/lint.ts +++ b/packages/@romejs/core/master/commands/lint.ts @@ -10,7 +10,7 @@ import {createMasterCommand} from '../../commands'; import Linter from '../linter/Linter'; import {commandCategories} from '../../commands'; import {Consumer} from '@romejs/consume'; -import {DiagnosticPointer} from '@romejs/diagnostics'; +import {DiagnosticLocation} from '@romejs/diagnostics'; type Flags = {fix: boolean}; @@ -43,7 +43,7 @@ export default createMasterCommand({ function initWatchLint( req: MasterRequest, - fix: undefined | DiagnosticPointer, + fix: undefined | DiagnosticLocation, reject: (err: Error) => void, ) { const {master, reporter} = req; @@ -107,7 +107,7 @@ function initWatchLint( async function runLint( req: MasterRequest, - fix: undefined | DiagnosticPointer, + fix: undefined | DiagnosticLocation, ): Promise { const linter = new Linter(req, fix); await linter.lint(); diff --git a/packages/@romejs/core/master/commands/test.ts b/packages/@romejs/core/master/commands/test.ts index 1c5fa51a9bf..b919f45104d 100644 --- a/packages/@romejs/core/master/commands/test.ts +++ b/packages/@romejs/core/master/commands/test.ts @@ -6,7 +6,7 @@ */ import {MasterRequest} from '@romejs/core'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {SourceMap} from '@romejs/codec-source-map'; import {Consumer} from '@romejs/consume'; import {createMasterCommand} from '../../commands'; @@ -79,7 +79,7 @@ export default createMasterCommand({ reporter.info(`Bundling test files`); - let addDiagnostics: PartialDiagnostics = []; + let addDiagnostics: Diagnostics = []; const tests: Map`; - - const message = - `Couldn't find export ${resolved.name} in ${resolvedFileLink}`; - let advice: PartialDiagnosticAdvice = []; - - if (resolved.node.analyze.exports.length === 0) { - advice.push({ - type: 'log', - category: 'info', - message: 'This file doesn\'t have any exports', - }); - } else { - // Provide suggestion on unknown import - const exportedNames = resolved.node.getExportedNames(kind); - - advice = - advice.concat(buildSuggestionAdvice(resolved.name, Array.from( - exportedNames, - ), { - formatItem: (name) => { - const exportInfo = resolved.node.resolveImport(name, undefined); - - if (exportInfo.type === 'NOT_FOUND') { - throw new Error( - `mod.resolveImport returned NOT_FOUND for an export ${name} in ${exportInfo.node.path} despite being returned by getExportedNames`, - ); - } - - const {record} = exportInfo; - - const {loc} = record; - if (loc !== undefined) { - name = - `${name}`; - - if (exportInfo.node !== resolved.node) { - name += - ` (from )`; - } - } - - return name; - }, - })); - } - + ): Diagnostic { return { - category: 'bundler/unknownExport', - ...resolved.loc, - message, - advice, - mtime: this.getMtime(), + description: descriptions.BUNDLER.UNKNOWN_EXPORT( + resolved.name, + resolved.node.id, + Array.from(resolved.node.getExportedNames(kind)), + (name: string) => { + const exportInfo = resolved.node.resolveImport(name, undefined); + + if (exportInfo.type === 'NOT_FOUND') { + throw new Error( + `mod.resolveImport returned NOT_FOUND for an export ${name} in ${exportInfo.node.path} despite being returned by getExportedNames`, + ); + } + + return { + location: exportInfo.record.loc, + source: exportInfo.node !== resolved.node + ? exportInfo.node.path.join() : undefined, + }; + }, + ), + location: { + ...resolved.loc, + mtime: this.getMtime(), + }, }; } @@ -307,36 +274,28 @@ export default class DependencyNode { resolved: ResolvedImportFound, node: DependencyNode, nameInfo: AnalyzeDependencyName, - ): PartialDiagnostic { + ): Diagnostic { const {name, kind, loc} = nameInfo; - const advice: PartialDiagnosticAdvice = []; - const {record} = resolved; - if (record.loc !== undefined) { - advice.push({ - type: 'log', - category: 'info', - message: `Export was defined here in `, - }); - - advice.push({ - type: 'frame', - ...record.loc, - }); - } - return { - category: 'bundler/importTypeMismatch', - ...loc, - message: `The export ${name} in was incorrectly imported as a ${kind} when it's actually a ${record.kind}`, - advice, - mtime: this.getMtime(), + description: descriptions.BUNDLER.IMPORT_TYPE_MISMATCH( + name, + node.id, + kind, + record.kind, + record.loc, + ), + + location: { + ...loc, + mtime: this.getMtime(), + }, }; } resolveImports(): { - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; resolved: BundleCompileResolvedImports; } { const {graph} = this; @@ -346,7 +305,7 @@ export default class DependencyNode { const resolvedImports: BundleCompileResolvedImports = {}; // Diagnostics for unknown imports - const diagnostics: PartialDiagnostics = []; + const diagnostics: Diagnostics = []; // Go through all of our dependencies and check if they have any external exports to forward const allowTypeImportsAsValue = this.analyze.syntax.includes('ts'); diff --git a/packages/@romejs/core/master/dependencies/DependencyOrderer.ts b/packages/@romejs/core/master/dependencies/DependencyOrderer.ts index 2f8bb4b5cd7..b99b6a5e1c5 100644 --- a/packages/@romejs/core/master/dependencies/DependencyOrderer.ts +++ b/packages/@romejs/core/master/dependencies/DependencyOrderer.ts @@ -9,7 +9,7 @@ import {SourceLocation} from '@romejs/parser-core'; import DependencyGraph from './DependencyGraph'; import DependencyNode from './DependencyNode'; import {AnalyzeDependencyImportUsageItem} from '@romejs/core'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics, descriptions} from '@romejs/diagnostics'; import {AbsoluteFilePath} from '@romejs/path'; type FirstTopAwaitLocations = Array<{ @@ -18,7 +18,7 @@ type FirstTopAwaitLocations = Array<{ }>; export type DependencyOrder = { - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; firstTopAwaitLocations: FirstTopAwaitLocations; files: Array; }; @@ -37,7 +37,7 @@ export default class DependencyOrderer { orderedNodes: Set; visitedNodes: Set; possibleCyclePaths: Map>; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; graph: DependencyGraph; handleAlreadyVisitedFile( @@ -142,46 +142,19 @@ export default class DependencyOrderer { (value, index) => path[index - 1] === target, )); - function formatPart(part: string, index?: number): string { - const tagged = ``; - if (part === culprit) { - return `${tagged}[1]`; - } else if (part === target) { - return `${tagged}[2]`; - } else if (index === 0) { - return `${tagged} ENTRY`; - } else { - return tagged; - } - } - this.diagnostics.push({ - category: 'bundler/moduleCycle', - filename: node.path.join(), - mtime: node.getMtime(), - start: imp.loc === undefined ? undefined : imp.loc.start, - end: imp.loc === undefined ? undefined : imp.loc.end, - message: `The variable ${imp.local} won't be initialized yet`, - advice: [ - { - type: 'log', - category: 'info', - message: 'This is because the module it belongs to wont be executed yet. This is due to a circular dependency creating a module cycle.', - }, - { - type: 'log', - category: 'info', - message: `The likely cause is the file ${formatPart(culprit)} that was required by ${formatPart( - target, - )} which created a circular dependency:`, - }, - { - type: 'list', - reverse: true, - ordered: true, - list: path.map(formatPart), - }, - ], + description: descriptions.BUNDLER.DETECTED_CYCLE( + imp.local, + target, + culprit, + path, + ), + location: { + filename: node.path.join(), + mtime: node.getMtime(), + start: imp.loc === undefined ? undefined : imp.loc.start, + end: imp.loc === undefined ? undefined : imp.loc.end, + }, }); } diff --git a/packages/@romejs/core/master/fs/Resolver.ts b/packages/@romejs/core/master/fs/Resolver.ts index 9bc39168692..46a072ab87d 100644 --- a/packages/@romejs/core/master/fs/Resolver.ts +++ b/packages/@romejs/core/master/fs/Resolver.ts @@ -20,7 +20,7 @@ import { RelativeFilePath, createFilePathFromSegments, } from '@romejs/path'; -import {DiagnosticPointer, PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {DiagnosticLocation, DiagnosticAdvice} from '@romejs/diagnostics'; import {IMPLICIT_JS_EXTENSIONS} from '../../common/fileHandlers'; import {writeFile} from '@romejs/fs'; import https = require('https'); @@ -104,7 +104,7 @@ export type ResolverQuerySource = | undefined | { source?: string; - pointer?: DiagnosticPointer; + pointer?: DiagnosticLocation; }; type ResolverQueryResponseFoundType = @@ -132,13 +132,13 @@ export type ResolverQueryResponseMissing = { export type ResolverQueryResponseUnsupported = { type: 'UNSUPPORTED'; source: undefined | ResolverQuerySource; - advice: PartialDiagnosticAdvice; + advice: DiagnosticAdvice; }; export type ResolverQueryResponseFetchError = { type: 'FETCH_ERROR'; source: undefined | ResolverQuerySource; - advice: PartialDiagnosticAdvice; + advice: DiagnosticAdvice; }; type FilenameVariant = { diff --git a/packages/@romejs/core/master/fs/resolverSuggest.ts b/packages/@romejs/core/master/fs/resolverSuggest.ts index 99c17369de3..ec9baab3a9b 100644 --- a/packages/@romejs/core/master/fs/resolverSuggest.ts +++ b/packages/@romejs/core/master/fs/resolverSuggest.ts @@ -15,10 +15,11 @@ import Resolver, { ResolverRemoteQuery, } from './Resolver'; import { - PartialDiagnosticAdvice, + DiagnosticAdvice, buildSuggestionAdvice, createSingleDiagnosticError, DiagnosticCategory, + createBlessedDiagnosticMessage, } from '@romejs/diagnostics'; import {orderBySimilarity} from '@romejs/string-utils'; import {createUnknownFilePath, AbsoluteFilePath} from '@romejs/path'; @@ -55,7 +56,7 @@ export default function resolverSuggest( const {pointer} = querySource; - let advice: PartialDiagnosticAdvice = []; + let advice: DiagnosticAdvice = []; if (query.origin.isAbsolute()) { const localQuery: ResolverLocalQuery = { @@ -146,7 +147,7 @@ export default function resolverSuggest( advice.push({ type: 'frame', - ...origPointer, + location: origPointer, }); } @@ -235,10 +236,12 @@ export default function resolverSuggest( ` ${source} from `; throw createSingleDiagnosticError({ - ...pointer, - category, - message, - advice, + location: pointer, + description: { + category, + message: createBlessedDiagnosticMessage(message), + advice, + }, }); } diff --git a/packages/@romejs/core/master/linter/Linter.ts b/packages/@romejs/core/master/linter/Linter.ts index 2cd124a2c72..27ecfe992e6 100644 --- a/packages/@romejs/core/master/linter/Linter.ts +++ b/packages/@romejs/core/master/linter/Linter.ts @@ -9,16 +9,16 @@ import {MasterRequest} from '@romejs/core'; import CompilerLinter from './CompilerLinter'; import {LINTABLE_EXTENSIONS} from '@romejs/core/common/fileHandlers'; import DependencyGraph from '../dependencies/DependencyGraph'; -import {DiagnosticPointer} from '@romejs/diagnostics'; +import {DiagnosticLocation, descriptions} from '@romejs/diagnostics'; export default class Linter { - constructor(req: MasterRequest, fix: undefined | DiagnosticPointer) { + constructor(req: MasterRequest, fix: undefined | DiagnosticLocation) { this.request = req; this.fix = fix; } request: MasterRequest; - fix: undefined | DiagnosticPointer; + fix: undefined | DiagnosticLocation; async lint(throwAlways: boolean = true) { const {request} = this; @@ -66,10 +66,8 @@ export default class Linter { for (const project of projects) { if (!project.config.format.enabled) { printer.addDiagnostic({ - ...fix, - category: 'format/disabled', - message: 'Format is disabled for this project', - // TODO advice and better error message + location: fix, + description: descriptions.FORMAT.DISABLED, }); } } @@ -80,12 +78,14 @@ export default class Linter { let couldFix = false; let hasPendingFixes = false; - for (const {category, fixable} of printer.processor.getPartialDiagnostics()) { - if (category === 'lint/pendingFixes') { + for (const { + description: metadata, + } of printer.processor.getDiagnostics()) { + if (metadata.category === 'lint/pendingFixes') { hasPendingFixes = true; } - if (fixable) { + if (metadata.fixable) { couldFix = true; } } @@ -116,7 +116,9 @@ export default class Linter { // For example, we don't want to show analysis or parse errors for transitive dependencies if the user only requested a specific file printer.processor.addFilter({ test: (diag) => { - const {filename} = diag; + const { + location: {filename}, + } = diag; if (filename === undefined) { return false; } diff --git a/packages/@romejs/core/master/project/ProjectManager.ts b/packages/@romejs/core/master/project/ProjectManager.ts index a152a67b85a..167ab41e160 100644 --- a/packages/@romejs/core/master/project/ProjectManager.ts +++ b/packages/@romejs/core/master/project/ProjectManager.ts @@ -27,8 +27,9 @@ import { import {WorkerContainer} from '../WorkerManager'; import { DiagnosticsProcessor, - DiagnosticPointer, + DiagnosticLocation, createSingleDiagnosticError, + descriptions, } from '@romejs/diagnostics'; import {matchPathPatterns} from '@romejs/path-match'; import {ManifestDefinition} from '@romejs/codec-js-manifest'; @@ -586,17 +587,11 @@ export default class ProjectManager { } diagnostics.addDiagnostic({ - category: 'projectManager/nameCollision', - filename: def.path.join(), - message: `Duplicate package name ${name}`, - ...def.consumer.get('name').getDiagnosticPointer('inner-value'), - advice: [ - { - type: 'log', - category: 'info', - message: `Defined already by `, - }, - ], + description: descriptions.PROJECT_MANAGER.DUPLICATE_PACKAGE( + name, + existingPackage.path.join(), + ), + location: def.consumer.get('name').getDiagnosticPointer('inner-value'), }); return; } @@ -668,16 +663,13 @@ export default class ProjectManager { } diagnostics.addDiagnostic({ - category: 'projectManager/nameCollision', - filename: hastePath.join(), - message: `Found a haste collision for ${hasteName}`, - advice: [ - { - type: 'log', - category: 'info', - message: `Defined already by `, - }, - ], + description: descriptions.PROJECT_MANAGER.HASTE_COLLISION( + hasteName, + existing.join(), + ), + location: { + filename: hastePath.join(), + }, }); continue; } @@ -727,7 +719,7 @@ export default class ProjectManager { async assertProject( path: AbsoluteFilePath, - pointer?: DiagnosticPointer, + pointer?: DiagnosticLocation, ): Promise { // We won't recurse up and check a parent project if we've already visited it const syncProject = this.findProjectExisting(path); @@ -751,16 +743,8 @@ export default class ProjectManager { } throw createSingleDiagnosticError({ - ...pointer, - category: 'projectManager/missing', - message: `Couldn't find a project`, - advice: [ - { - type: 'log', - category: 'info', - message: 'Run rome init in this folder to initialize a project', - }, - ], + location: pointer, + description: descriptions.PROJECT_MANAGER.NOT_FOUND, }); } @@ -912,11 +896,12 @@ export default class ProjectManager { diagnostics: DiagnosticsProcessor, ) { diagnostics.addDiagnostic({ - category: 'projectManager/incorrectConfigFilename', - filename: path.join(), - message: `Invalid rome config filename, ${ROME_CONFIG_FILENAMES.join( - ' or ', - )} are the only valid filename`, + description: descriptions.PROJECT_MANAGER.INCORRECT_CONFIG_FILENAME( + ROME_CONFIG_FILENAMES, + ), + location: { + filename: path.join(), + }, }); } } diff --git a/packages/@romejs/core/master/testing/TestRunner.ts b/packages/@romejs/core/master/testing/TestRunner.ts index c4e31aced57..28e4fd6e404 100644 --- a/packages/@romejs/core/master/testing/TestRunner.ts +++ b/packages/@romejs/core/master/testing/TestRunner.ts @@ -6,7 +6,11 @@ */ import {Reporter} from '@romejs/cli-reporter'; -import {DiagnosticOrigin, deriveDiagnosticFromError} from '@romejs/diagnostics'; +import { + DiagnosticOrigin, + deriveDiagnosticFromError, + descriptions, +} from '@romejs/diagnostics'; import {TestRef} from '../../common/bridges/TestWorkerBridge'; import {Master, MasterRequest} from '@romejs/core'; import {DiagnosticsPrinter} from '@romejs/cli-diagnostics'; @@ -464,23 +468,29 @@ export default class TestRunner { // If we only have one test to cancel then let's only point the bridge error to this test this.ignoreBridgeEndError.add(bridge); + const errDiag = deriveDiagnosticFromError({ + label: ref.testName, + category: 'tests/failure', + filename: ref.filename, + error, + }); + this.printer.addDiagnostic({ - ...deriveDiagnosticFromError({ - label: ref.testName, - category: 'tests/failure', - filename: ref.filename, - error, - }), + ...errDiag, - // We don't care about the advice - advice: [], + description: { + ...errDiag.description, + // We don't care about the advice + advice: [], + }, }); } else { this.printer.addDiagnostic({ label: ref.testName, - category: 'tests/failure', - filename: ref.filename, - message: 'Test was cancelled', + description: descriptions.TESTS.CANCELLED, + location: { + filename: ref.filename, + }, }); } } diff --git a/packages/@romejs/core/master/testing/types.ts b/packages/@romejs/core/master/testing/types.ts index 171ebedee48..2d0ebb020b3 100644 --- a/packages/@romejs/core/master/testing/types.ts +++ b/packages/@romejs/core/master/testing/types.ts @@ -6,7 +6,7 @@ */ import {CoverageFile} from '@romejs/v8'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {SourceMap} from '@romejs/codec-source-map'; import {AbsoluteFilePath} from '@romejs/path'; import {MasterRequest} from '@romejs/core'; @@ -25,7 +25,7 @@ export type TestSources = Map; export type TestRunnerConstructorOptions = { sources: TestSources; request: MasterRequest; - addDiagnostics: PartialDiagnostics; + addDiagnostics: Diagnostics; options: TestRunnerOptions; }; diff --git a/packages/@romejs/core/test-worker/SnapshotManager.ts b/packages/@romejs/core/test-worker/SnapshotManager.ts index bdcd1174ca3..e9481870698 100644 --- a/packages/@romejs/core/test-worker/SnapshotManager.ts +++ b/packages/@romejs/core/test-worker/SnapshotManager.ts @@ -9,9 +9,8 @@ import {AbsoluteFilePath} from '@romejs/path'; import {writeFile, readFileText, exists, unlink} from '@romejs/fs'; import {TestRunnerOptions} from '../master/testing/types'; import TestWorkerRunner from './TestWorkerRunner'; -import {PartialDiagnosticAdvice, DiagnosticCategory} from '@romejs/diagnostics'; +import {descriptions, DiagnosticDescription} from '@romejs/diagnostics'; import createSnapshotParser from './SnapshotParser'; -import stringDiff from '@romejs/string-diff'; function cleanHeading(key: string): string { if (key[0] === '`') { @@ -54,16 +53,12 @@ export default class SnapshotManager { raw: string; exists: boolean; - async emitDiagnostic( - category: DiagnosticCategory, - message: string, - advice?: PartialDiagnosticAdvice, - ) { + async emitDiagnostic(metadata: DiagnosticDescription) { await this.runner.emitDiagnostic({ - category, - filename: this.path.join(), - message, - advice, + description: metadata, + location: { + filename: this.path.join(), + }, }); } @@ -115,7 +110,7 @@ export default class SnapshotManager { const codeBlock = nodes.shift(); if (codeBlock === undefined || codeBlock.type !== 'CodeBlock') { throw parser.unexpected({ - message: 'Expected a code block after this heading', + description: descriptions.SNAPSHOTS.EXPECTED_CODE_BLOCK_AFTER_HEADING, loc: node.loc, }); } @@ -160,10 +155,7 @@ export default class SnapshotManager { if (this.entries.size === 0) { if (this.exists) { if (this.options.freezeSnapshots) { - await this.emitDiagnostic( - 'tests/snapshots/redundant', - 'Snapshot should not exist', - ); + await this.emitDiagnostic(descriptions.SNAPSHOTS.REDUNDANT); } else { // Remove the snapshot file as there were none ran await unlink(path); @@ -232,21 +224,12 @@ export default class SnapshotManager { if (this.options.freezeSnapshots) { if (!this.exists) { - await this.emitDiagnostic( - 'tests/snapshots/missing', - 'Snapshot does not exist', - ); + await this.emitDiagnostic(descriptions.SNAPSHOTS.MISSING); } else if (formatted !== this.raw) { - await this.emitDiagnostic( - 'tests/snapshots/incorrect', - 'Snapshots do not match', - [ - { - type: 'diff', - diff: stringDiff(this.raw, formatted), - }, - ], - ); + await this.emitDiagnostic(descriptions.SNAPSHOTS.INCORRECT( + this.raw, + formatted, + )); } } else if (formatted !== this.raw) { // Save the file diff --git a/packages/@romejs/core/test-worker/SnapshotParser.ts b/packages/@romejs/core/test-worker/SnapshotParser.ts index d2583658d43..7c975237829 100644 --- a/packages/@romejs/core/test-worker/SnapshotParser.ts +++ b/packages/@romejs/core/test-worker/SnapshotParser.ts @@ -14,6 +14,7 @@ import { isEscaped, } from '@romejs/parser-core'; import {add, get0, Number0} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; type Tokens = & BaseTokens @@ -110,7 +111,7 @@ export default createParser((ParserCore) => codeOffset = add(codeOffset, 1); } else { throw this.unexpected({ - message: 'Newline required after code block', + description: descriptions.SNAPSHOTS.MISSING_NEWLINE_AFTER_CODE_BLOCK, start: this.getPositionFromIndex(codeOffset), }); } @@ -134,13 +135,13 @@ export default createParser((ParserCore) => }, end); } else { throw this.unexpected({ - message: 'Newline required before code block end', + description: descriptions.SNAPSHOTS.MISSING_NEWLINE_BEFORE_CODE_BLOCK, start: this.getPositionFromIndex(end), }); } } else { throw this.unexpected({ - message: 'Unclosed code block', + description: descriptions.SNAPSHOTS.UNCLOSED_CODE_BLOCK, start: this.getPositionFromIndex(end), }); } diff --git a/packages/@romejs/core/test-worker/TestAPI.ts b/packages/@romejs/core/test-worker/TestAPI.ts index f35ab139da3..c4064974ed4 100644 --- a/packages/@romejs/core/test-worker/TestAPI.ts +++ b/packages/@romejs/core/test-worker/TestAPI.ts @@ -5,10 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { - PartialDiagnosticAdvice, - PartialDiagnosticAdviceItem, -} from '@romejs/diagnostics'; +import {DiagnosticAdvice, DiagnosticAdviceItem} from '@romejs/diagnostics'; import SnapshotManager from './SnapshotManager'; import {TestRunnerOptions} from '../master/testing/types'; import {getErrorStackAdvice} from '@romejs/diagnostics'; @@ -120,7 +117,7 @@ export default class TestAPI { timeoutStart: undefined | number; timeoutMax: undefined | number; - advice: PartialDiagnosticAdvice; + advice: DiagnosticAdvice; teardownEvent: Event; testName: string; snapshotCounter: number; @@ -138,7 +135,7 @@ export default class TestAPI { expectedAlias?: string; receivedAlias?: string; } = {}, - ): PartialDiagnosticAdvice { + ): DiagnosticAdvice { let expectedFormat; let receivedFormat; if (typeof received === 'string' && typeof expected === 'string') { @@ -162,7 +159,7 @@ export default class TestAPI { const hasAllTruncated = expectedFormatCode !== expectedFormat && receivedFormatCode !== receivedFormat; - const advice: PartialDiagnosticAdvice = []; + const advice: DiagnosticAdvice = []; if (expectedFormat === receivedFormat) { // Better error message when both values are visually identical @@ -274,7 +271,7 @@ export default class TestAPI { return advice; } - addToAdvice(item: PartialDiagnosticAdviceItem) { + addToAdvice(item: DiagnosticAdviceItem) { this.advice.push(item); } @@ -327,7 +324,7 @@ export default class TestAPI { fail( message: string = 'Test failure triggered by t.fail()', - advice: PartialDiagnosticAdvice = [], + advice: DiagnosticAdvice = [], framesToPop: number = 0, ) { throw createErrorFromStructure({ @@ -549,7 +546,7 @@ export default class TestAPI { // Compare the snapshots if (formatted !== existingSnapshot) { - const advice: PartialDiagnosticAdvice = this.buildMatchAdvice( + const advice: DiagnosticAdvice = this.buildMatchAdvice( formatted, existingSnapshot, { diff --git a/packages/@romejs/core/test-worker/TestWorkerRunner.ts b/packages/@romejs/core/test-worker/TestWorkerRunner.ts index 26f8f5c2555..79a98a8bf28 100644 --- a/packages/@romejs/core/test-worker/TestWorkerRunner.ts +++ b/packages/@romejs/core/test-worker/TestWorkerRunner.ts @@ -7,11 +7,13 @@ import {UnknownObject} from '@romejs/typescript-helpers'; import { - PartialDiagnosticAdvice, - PartialDiagnostic, + DiagnosticAdvice, + Diagnostic, getDiagnosticsFromError, INTERNAL_ERROR_LOG_ADVICE, createSingleDiagnosticError, + descriptions, + createBlessedDiagnosticMessage, } from '@romejs/diagnostics'; import {TestCallback, TestOptions} from '@romejs/test'; import { @@ -82,7 +84,7 @@ export default class TestWorkerRunner { }; } - async emitDiagnostic(diagnostic: PartialDiagnostic) { + async emitDiagnostic(diagnostic: Diagnostic) { await this.bridge.testError.call({ ref: undefined, diagnostic, @@ -102,13 +104,19 @@ export default class TestWorkerRunner { if (res.syntaxError !== undefined) { const message = - `A bundle was generated that contained a syntax error: ${res.syntaxError.message}`; + `A bundle was generated that contained a syntax error: ${res.syntaxError.description.message.value}`; throw createSingleDiagnosticError({ ...res.syntaxError, - message, - filename: this.file.uid, - advice: [INTERNAL_ERROR_LOG_ADVICE], + description: { + ...res.syntaxError.description, + message: createBlessedDiagnosticMessage(message), + advice: [INTERNAL_ERROR_LOG_ADVICE], + }, + location: { + ...res.syntaxError.location, + filename: this.file.uid, + }, }); } } @@ -150,8 +158,8 @@ export default class TestWorkerRunner { testName: undefined | string, opts: { error: Error; - firstAdvice: PartialDiagnosticAdvice; - lastAdvice: PartialDiagnosticAdvice; + firstAdvice: DiagnosticAdvice; + lastAdvice: DiagnosticAdvice; }, ) { const filename = this.file.real.join(); @@ -166,7 +174,7 @@ export default class TestWorkerRunner { }; } - let diagnostic: PartialDiagnostic = deriveDiagnosticFromError({ + let diagnostic: Diagnostic = deriveDiagnosticFromError({ error: opts.error, category: 'tests/failure', label: testName, @@ -213,11 +221,14 @@ export default class TestWorkerRunner { diagnostic = { ...diagnostic, - advice: [ - ...opts.firstAdvice, - ...(diagnostic.advice || []), - ...opts.lastAdvice, - ], + description: { + ...diagnostic.description, + advice: [ + ...opts.firstAdvice, + ...(diagnostic.description.advice || []), + ...opts.lastAdvice, + ], + }, }; this.bridge.testError.send({ @@ -298,9 +309,10 @@ export default class TestWorkerRunner { this.bridge.testError.send({ ref: undefined, diagnostic: { - filename: this.file.uid, - message: 'No tests declared in this file', - category: 'tests/noneDeclared', + location: { + filename: this.file.uid, + }, + description: descriptions.TESTS.UNDECLARED, }, }); } diff --git a/packages/@romejs/core/worker/Worker.ts b/packages/@romejs/core/worker/Worker.ts index 9255821629f..96924cc40da 100644 --- a/packages/@romejs/core/worker/Worker.ts +++ b/packages/@romejs/core/worker/Worker.ts @@ -22,7 +22,7 @@ import {Reporter} from '@romejs/cli-reporter'; import setupGlobalErrorHandlers from '../common/utils/setupGlobalErrorHandlers'; import {UserConfig, loadUserConfig} from '../common/userConfig'; import {hydrateJSONProjectConfig} from '@romejs/project'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import { createUnknownFilePath, AbsoluteFilePath, @@ -267,7 +267,7 @@ export default class Worker { }; } - populateDiagnosticsMtime(diagnostics: PartialDiagnostics): PartialDiagnostics { + populateDiagnosticsMtime(diagnostics: Diagnostics): Diagnostics { return diagnostics; } diff --git a/packages/@romejs/core/worker/WorkerAPI.ts b/packages/@romejs/core/worker/WorkerAPI.ts index d0767d8ffff..549fb3bed4b 100644 --- a/packages/@romejs/core/worker/WorkerAPI.ts +++ b/packages/@romejs/core/worker/WorkerAPI.ts @@ -7,7 +7,7 @@ import {Worker, FileReference} from '@romejs/core'; import {Program} from '@romejs/js-ast'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics, descriptions} from '@romejs/diagnostics'; import { TransformStageName, CompileResult, @@ -26,7 +26,6 @@ import {compile} from '@romejs/js-compiler'; import {catchDiagnostics} from '@romejs/diagnostics'; import * as jsAnalysis from '@romejs/js-analysis'; import {program} from '@romejs/js-ast'; -import diff from '@romejs/string-diff'; import {getFileHandlerAssert, ExtensionLintResult} from '../common/fileHandlers'; import { AnalyzeDependencyResult, @@ -43,25 +42,27 @@ export default class WorkerAPI { worker: Worker; logger: Logger; - interceptAndAddGeneratedToDiagnostics< - T extends {diagnostics: PartialDiagnostics} - >( + interceptAndAddGeneratedToDiagnostics( val: T, generated: boolean, ): T { if (generated) { const diagnostics = val.diagnostics.map((diag) => { - const diagAdvice = diag.advice === undefined ? [] : diag.advice; + const diagAdvice = diag.description.advice === undefined + ? [] : diag.description.advice; return { ...diag, - advice: [ - ...diagAdvice, - { - type: 'log', - category: 'warn', - message: 'This diagnostic was generated on a file that has been converted to JavaScript. The source locations are most likely incorrect', - }, - ], + metadata: { + ...diag.description, + advice: [ + ...diagAdvice, + { + type: 'log', + category: 'warn', + message: 'This diagnostic was generated on a file that has been converted to JavaScript. The source locations are most likely incorrect', + }, + ], + }, }; }); @@ -287,19 +288,10 @@ export default class WorkerAPI { diagnostics: [ ...diagnostics, { - category: 'lint/pendingFixes', - filename: ref.uid, - message: 'Pending fixes', - advice: [ - { - type: 'diff', - diff: diff(raw, formatted), - legend: { - add: 'Code to be added', - delete: 'Code to be removed', - }, - }, - ], + location: { + filename: ref.uid, + }, + description: descriptions.LINT.PENDING_FIXES(raw, formatted), }, ], }; diff --git a/packages/@romejs/diagnostics/DiagnosticsProcessor.ts b/packages/@romejs/diagnostics/DiagnosticsProcessor.ts index c0b1b7f7fa8..63268a7ca8d 100644 --- a/packages/@romejs/diagnostics/DiagnosticsProcessor.ts +++ b/packages/@romejs/diagnostics/DiagnosticsProcessor.ts @@ -7,20 +7,18 @@ import { Diagnostics, - PartialDiagnostics, - PartialDiagnostic, + Diagnostic, DiagnosticFilterWithTest, DiagnosticOrigin, DiagnosticSuppressions, DiagnosticSuppression, } from './types'; -import {MarkupFormatOptions} from '@romejs/string-markup'; import {addOriginsToDiagnostics} from './derive'; import {naturalCompare} from '@romejs/string-utils'; import {DiagnosticsError} from './errors'; -import {normalizeDiagnostics} from './normalize'; import {add} from '@romejs/ob1'; import {DiagnosticCategoryPrefix} from './categories'; +import {descriptions} from './descriptions'; type UniquePart = | 'filename' @@ -37,7 +35,7 @@ export type CollectorOptions = { filters?: Array; unique?: UniqueRules; max?: number; - onDiagnostics?: (diags: PartialDiagnostics) => void; + onDiagnostics?: (diags: Diagnostics) => void; origins?: Array; }; @@ -72,7 +70,7 @@ export default class DiagnosticsProcessor { unique: UniqueRules; includedKeys: Set; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; filters: Array; allowedUnusedSuppressionPrefixes: Set; usedSuppressions: Set; @@ -88,7 +86,7 @@ export default class DiagnosticsProcessor { if (this.hasDiagnostics()) { throw new DiagnosticsError( 'Thrown by DiagnosticsProcessor', - this.getPartialDiagnostics(), + this.getDiagnostics(), ); } } @@ -115,39 +113,42 @@ export default class DiagnosticsProcessor { this.filters.push(filter); } - doesMatchFilter(diag: PartialDiagnostic): boolean { + doesMatchFilter(diag: Diagnostic): boolean { for (const suppression of this.suppressions) { const targetLine = add(suppression.loc.end.line, 1); - if (diag.filename !== undefined && diag.start !== undefined && - diag.filename === suppression.loc.filename && diag.start.line === - targetLine) { + if (diag.location.filename !== undefined && diag.location.start !== + undefined && diag.location.filename === suppression.loc.filename && + diag.location.start.line === targetLine) { this.usedSuppressions.add(suppression); return true; } } for (const filter of this.filters) { - if (filter.message !== undefined && filter.message !== diag.message) { + if (filter.message !== undefined && filter.message !== + diag.description.message.value) { continue; } - if (filter.filename !== undefined && filter.filename !== diag.filename) { + if (filter.filename !== undefined && filter.filename !== + diag.location.filename) { continue; } - if (filter.category !== undefined && filter.category !== diag.category) { + if (filter.category !== undefined && filter.category !== + diag.description.category) { continue; } - if (filter.start !== undefined && diag.start !== undefined) { - if (filter.start.line !== diag.start.line || filter.start.column !== - diag.start.column) { + if (filter.start !== undefined && diag.location.start !== undefined) { + if (filter.start.line !== diag.location.start.line || + filter.start.column !== diag.location.start.column) { continue; } } - if (filter.line !== undefined && diag.start !== undefined && - diag.start.line !== filter.line) { + if (filter.line !== undefined && diag.location.start !== undefined && + diag.location.start.line !== filter.line) { continue; } @@ -161,9 +162,9 @@ export default class DiagnosticsProcessor { return false; } - buildDedupeKeys(diag: PartialDiagnostic): Array { + buildDedupeKeys(diag: Diagnostic): Array { // We don't do anything with `end` in this method, it's fairly meaningless for deduping errors - let {start} = diag; + let {start} = diag.location; const keys: Array = []; @@ -171,15 +172,15 @@ export default class DiagnosticsProcessor { const parts = []; if (rule.includes('category')) { - parts.push(`category:${diag.category}`); + parts.push(`category:${diag.description.category}`); } if (rule.includes('filename')) { - parts.push(`filename:${String(diag.filename)}`); + parts.push(`filename:${String(diag.location.filename)}`); } if (rule.includes('message')) { - parts.push(`message:${diag.message}`); + parts.push(`message:${diag.description.message}`); } if (start !== undefined) { @@ -199,20 +200,17 @@ export default class DiagnosticsProcessor { return keys; } - addDiagnostic(diag: PartialDiagnostic, origin?: DiagnosticOrigin): boolean { + addDiagnostic(diag: Diagnostic, origin?: DiagnosticOrigin): boolean { return this.addDiagnostics([diag], origin).length > 0; } - addDiagnostics( - diags: PartialDiagnostics, - origin?: DiagnosticOrigin, - ): PartialDiagnostics { + addDiagnostics(diags: Diagnostics, origin?: DiagnosticOrigin): Diagnostics { if (diags.length === 0) { return diags; } const {max} = this.options; - const added: PartialDiagnostics = []; + const added: Diagnostics = []; // Add origins to diagnostics const origins: Array = this.options.origins === undefined @@ -261,8 +259,8 @@ export default class DiagnosticsProcessor { return added; } - getPartialDiagnostics(): PartialDiagnostics { - const diagnostics: PartialDiagnostics = [...this.diagnostics]; + getDiagnostics(): Diagnostics { + const diagnostics: Diagnostics = [...this.diagnostics]; // Add errors for remaining suppressions for (const suppression of this.suppressions) { @@ -276,30 +274,23 @@ export default class DiagnosticsProcessor { } diagnostics.push({ - ...suppression.loc, - message: 'Did not hide any error', - category: 'suppressions/unused', + location: suppression.loc, + description: descriptions.SUPPRESSIONS.UNUSED, }); } return diagnostics; } - getCompleteDiagnostics(markupOptions: MarkupFormatOptions = {}): Diagnostics { - return normalizeDiagnostics(this.getPartialDiagnostics(), markupOptions); - } - - getCompleteSortedDiagnostics( - markupOptions: MarkupFormatOptions = {}, - ): Diagnostics { + getSortedDiagnostics(): Diagnostics { // Sort files by filename to ensure they're always in the same order // TODO also sort by line/column - return this.getCompleteDiagnostics(markupOptions).sort((a, b) => { - if (a.filename === undefined || b.filename === undefined) { + return this.getDiagnostics().sort((a, b) => { + if (a.location.filename === undefined || b.location.filename === undefined) { return 0; } else { - return naturalCompare(a.filename, b.filename); + return naturalCompare(a.location.filename, b.location.filename); } }); } diff --git a/packages/@romejs/diagnostics/categories.ts b/packages/@romejs/diagnostics/categories.ts index 142ce6d83e1..e5952904cd4 100644 --- a/packages/@romejs/diagnostics/categories.ts +++ b/packages/@romejs/diagnostics/categories.ts @@ -85,6 +85,7 @@ export type DiagnosticCategory = | 'tests/unhandledRejection' | 'tests/fixtureOptions' | 'tests/failure' + | 'tests/cancelled' | 'typeCheck/incompatible' | 'typeCheck/uncallable' | 'typeCheck/undeclaredVariable' diff --git a/packages/@romejs/diagnostics/constants.ts b/packages/@romejs/diagnostics/constants.ts index 3283cd60ca7..708448423f2 100644 --- a/packages/@romejs/diagnostics/constants.ts +++ b/packages/@romejs/diagnostics/constants.ts @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnosticAdviceItem} from './types'; +import {DiagnosticAdviceItem} from './types'; -export const INTERNAL_ERROR_LOG_ADVICE: PartialDiagnosticAdviceItem = { +export const INTERNAL_ERROR_LOG_ADVICE: DiagnosticAdviceItem = { type: 'log', category: 'warn', message: 'This diagnostic was derived from an internal Rome error. The problem likely isn\'t with your code. Please report this if necessary', diff --git a/packages/@romejs/diagnostics/derive.ts b/packages/@romejs/diagnostics/derive.ts index 4a33346f560..61c451e518a 100644 --- a/packages/@romejs/diagnostics/derive.ts +++ b/packages/@romejs/diagnostics/derive.ts @@ -6,10 +6,9 @@ */ import { + DiagnosticAdvice, Diagnostic, - PartialDiagnosticAdvice, - PartialDiagnostic, - PartialDiagnostics, + Diagnostics, DiagnosticOrigin, } from './types'; import {Position} from '@romejs/parser-core'; @@ -20,6 +19,7 @@ import { getSourceLocationFromErrorFrame, } from '@romejs/v8'; import {DiagnosticCategory} from './categories'; +import {createBlessedDiagnosticMessage} from './descriptions'; function normalizeArray(val: undefined | Array): Array { if (Array.isArray(val)) { @@ -30,23 +30,26 @@ function normalizeArray(val: undefined | Array): Array { } export function mergeDiagnostics( - rootDiag: PartialDiagnostic, -...diags: Array): PartialDiagnostic { - let mergedAdvice: PartialDiagnosticAdvice = [ - ...normalizeArray(rootDiag.advice), + rootDiag: Diagnostic, +...diags: Array): Diagnostic { + let mergedAdvice: DiagnosticAdvice = [ + ...normalizeArray(rootDiag.description.advice), ]; for (const diag of diags) { mergedAdvice = [ ...mergedAdvice, ...deriveRootAdviceFromDiagnostic(diag).advice, - ...normalizeArray(diag.advice), + ...normalizeArray(diag.description.advice), ]; } return { ...rootDiag, - advice: mergedAdvice, + description: { + ...rootDiag.description, + advice: mergedAdvice, + }, }; } @@ -72,7 +75,7 @@ export function getDiagnosticHeader( } export function deriveRootAdviceFromDiagnostic( - diag: PartialDiagnostic | Diagnostic, + diag: Diagnostic, opts: { skipFrame: boolean; includeHeaderInAdvice: boolean; @@ -83,29 +86,30 @@ export function deriveRootAdviceFromDiagnostic( outdated: false, }, ): { - advice: PartialDiagnosticAdvice; + advice: DiagnosticAdvice; header: string; } { - const advice: PartialDiagnosticAdvice = []; + const advice: DiagnosticAdvice = []; + const {description: metadata, location: pointer} = diag; let header = getDiagnosticHeader({ - start: diag.start, - filename: diag.filename, + start: pointer.start, + filename: pointer.filename, }); if (diag.label !== undefined) { header += ` ${diag.label}`; - if (diag.category !== undefined) { - header += ` ${diag.category}`; + if (metadata.category !== undefined) { + header += ` ${metadata.category}`; } } else { - if (diag.category !== undefined) { - header += ` ${diag.category}`; + if (metadata.category !== undefined) { + header += ` ${metadata.category}`; } } - if (diag.fixable === true) { + if (metadata.fixable === true) { header += ` FIXABLE`; } @@ -124,19 +128,15 @@ export function deriveRootAdviceFromDiagnostic( advice.push({ type: 'log', category: 'error', - message: diag.message, + message: metadata.message.value, }); if (opts.skipFrame === false) { - if (diag.start !== undefined && diag.end !== undefined) { + if (pointer.start !== undefined && pointer.end !== undefined) { advice.push({ type: 'frame', - sourceText: diag.sourceText, - filename: diag.filename, - mtime: diag.mtime, + location: diag.location, marker: diag.marker, - start: diag.start, - end: diag.end, }); } else if (diag.marker !== undefined) { // If we have no start/end, but we do have a marker then output is a log error @@ -161,7 +161,7 @@ type DeriveErrorDiagnosticOpts = { export function deriveDiagnosticFromError( opts: DeriveErrorDiagnosticOpts, -): PartialDiagnostic { +): Diagnostic { const {error, filename} = opts; let targetFilename: undefined | string = filename; @@ -190,14 +190,18 @@ export function deriveDiagnosticFromError( advice = [...getErrorStackAdvice(error, undefined, frames), ...advice]; return { - filename: targetFilename, - start: targetLoc === undefined ? undefined : targetLoc.start, - end: targetLoc === undefined ? undefined : targetLoc.end, - sourceText: targetCode, - category: opts.category, + description: { + category: opts.category, + message: createBlessedDiagnosticMessage(message), + advice, + }, + location: { + filename: targetFilename, + start: targetLoc === undefined ? undefined : targetLoc.start, + end: targetLoc === undefined ? undefined : targetLoc.end, + sourceText: targetCode, + }, label: opts.label, - message, - advice, }; } @@ -205,11 +209,11 @@ export function getErrorStackAdvice( errorLike: unknown, title?: string, _frames?: ErrorFrames, -): PartialDiagnosticAdvice { +): DiagnosticAdvice { const error = getErrorStructure(errorLike); const {stack} = error; - const advice: PartialDiagnosticAdvice = []; + const advice: DiagnosticAdvice = []; const frames = _frames === undefined ? error.frames : _frames; if (frames.length === 0 && stack !== undefined) { @@ -299,8 +303,8 @@ export function getErrorStackAdvice( export function addOriginsToDiagnostics( origins: Array, - diagnostics: PartialDiagnostics, -): PartialDiagnostics { + diagnostics: Diagnostics, +): Diagnostics { return diagnostics.map((diag) => { return addOriginsToDiagnostic(origins, diag); }); @@ -308,8 +312,8 @@ export function addOriginsToDiagnostics( export function addOriginsToDiagnostic( origins: Array, - diag: PartialDiagnostic, -): PartialDiagnostic { + diag: Diagnostic, +): Diagnostic { const newOrigins = diag.origins === undefined ? origins : [ ...origins, ...diag.origins, diff --git a/packages/@romejs/diagnostics/descriptions.ts b/packages/@romejs/diagnostics/descriptions.ts new file mode 100644 index 00000000000..ab4e49f0e56 --- /dev/null +++ b/packages/@romejs/diagnostics/descriptions.ts @@ -0,0 +1,1326 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { + DiagnosticDescription, + DiagnosticBlessedMessage, + DiagnosticLocation, + DiagnosticAdvice, +} from './types'; +import {markup} from '@romejs/string-markup'; +import stringDiff from '@romejs/string-diff'; +import {buildSuggestionAdvice, buildDuplicateLocationAdvice} from './helpers'; +import {SourceLocation} from '@romejs/parser-core'; + +type DiagnosticMetadataString = + & Omit, 'message'> + & {message: string}; + +// The purpose of this is so that we're explicit whenever we want to create a diagnostic message outside of this file +export function createBlessedDiagnosticMessage( + value: string, +): DiagnosticBlessedMessage { + return { + type: 'PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE', + value, + }; +} + +// rome-suppress lint/AEciilnnoptxy; +type InputMessagesFactory = (...params: Array) => DiagnosticMetadataString; + +type InputMessagesCategory = {[key: string]: + | string + | DiagnosticMetadataString + | InputMessagesFactory}; + +type InputMessages = {[category: string]: InputMessagesCategory}; + +type OuputMessagesFactoryReturn = + & Omit + & {message: DiagnosticBlessedMessage}; + +type OutputMessagesFactory = (...params: Parameters< + Func +>) => OuputMessagesFactoryReturn>; + +type OutputMessagesValue = Value extends string + ? {message: DiagnosticBlessedMessage} + : Value extends DiagnosticMetadataString + ? OuputMessagesFactoryReturn + : Value extends InputMessagesFactory ? OutputMessagesFactory : never; + +type OutputMessagesCategory = { [Key in keyof Input]: OutputMessagesValue< + Input[Key] +> }; + +type OutputMessages = { [Key in keyof Input]: OutputMessagesCategory< + Input[Key] +> }; + +// This is a lot of gross meta programming +function createMessages( + messages: Input, +): OutputMessages { + // rome-suppress lint/noExplicitAny + const out: OutputMessages = ({} as any); + + for (const categoryName in messages) { + // rome-suppress lint/noExplicitAny + const category: OutputMessagesCategory = {}; + out[categoryName] = category; + + const inputCategory = messages[categoryName]; + for (const key in inputCategory) { + const value = inputCategory[key]; + + if (typeof value === 'string') { + category[key] = { + message: createBlessedDiagnosticMessage(value), + }; + } else if (typeof value === 'function') { + // rome-suppress lint/noExplicitAny + const callback: InputMessagesFactory = (value as any); + + category[key] = function(...params) { + const {message, ...ret} = callback(...params); + return { + ...ret, + message: createBlessedDiagnosticMessage(message), + }; + }; + } else { + // rome-suppress lint/noExplicitAny + const {message, ...obj} = (value as any); + category[key] = { + ...obj, + message: createBlessedDiagnosticMessage(message), + }; + } + } + } + + return out; +} + +function buildJSXOpeningAdvice( + name: string, + openingLoc: SourceLocation, +): DiagnosticAdvice { + return [ + { + type: 'log', + category: 'info', + message: name === '' + ? 'Originated from this opening tag' : `Originated from opening tag of ${name}`, + }, + { + type: 'frame', + location: openingLoc, + }, + ]; +} + +export const descriptions = createMessages({ + // @romejs/parser-core + PARSER_CORE: { + EXPECTED_SPACE: 'Expected no space between', + EXPECTED_EOF: 'Expected end of file', + + UNEXPECTED_CHARACTER: (char: string) => + ({ + message: markup`Unexpected character ${char}`, + }), + + EXPECTED_TOKEN: (got: string, expected: string) => { + return { + message: markup`Expected token ${expected} but got ${got}`, + }; + }, + }, + + // @romejs/codec-js-regexp + REGEX_PARSER: { + INVALID_CAPTURE_GROUP_MODIFIER: 'Invalid capture group modifier', + UNCLOSED_GROUP: 'Unclosed group', + UNOPENED_GROUP: 'Unopened group', + INVALID_QUANTIFIER_TARGET: 'Invalid target for quantifier', + UNKNOWN_REGEX_PART: 'Unknown regex part', + REVERSED_CHAR_SET_RANGE: 'Range values reversed. Start char code is greater than end char code', + UNCLOSED_CHAR_SET: 'Unclosed character set', + DUPLICATE_FLAG: 'Duplicate regular expression flag', + INVALID_FLAG: 'Invalid regular expression flag', + }, + + // @romejs/codec-json + JSON: { + SINGLE_QUOTE_USAGE: 'You can only use double quoted strings', + TRAILING_COMMA_VALUE: 'Trailing comma is only allowed after a value', + UNCLOSED_STRING: 'Unclosed string', + UNCLOSED_BLOCK_COMMENT: 'Unclosed block comment', + MISTAKEN_ARRAY_IDENTITY: 'Trying to use an array element as an object property. Did you mean to make an object?', + REDUNDANT_COMMA: 'Redundant comma', + EMPTY_INPUT_IN_JSON: 'Empty input', + PROPERTY_KEY_UNQUOTED_IN_JSON: 'Property keys must be quoted in JSON', + IMPLICIT_OBJECT_IN_JSON: 'Objects must be wrapped in curly braces in JSON', + COMMENTS_IN_JSON: 'Comments aren\'t allowed in JSON', + TRAILING_COMMA_IN_JSON: 'Trailing commas aren\'t allowed in JSON', + REGEX_IN_JSON: 'Regular expressions aren\'t allowed in JSON', + UNKNOWN_WORD_IN_JSON: (word: string) => + ({ + message: markup`${word} isn't a valid JSON word`, + }), + STRING_NEWLINES_IN_JSON: 'Newlines aren\'t allowed in JSON, you insert a newline by escaping it like this "\\n"', + UNDEFINED_IN_JSON: 'undefined isn\'t allowed in JSON, you could use null instead', + BIGINT_IN_JSON: 'Bigints aren\'t allowed in JSON', + NUMERIC_SEPARATORS_IN_JSON: 'Numeric separators are not allowed in JSON', + }, + + // @romejs/codec-semver + SEMVER: { + MISSING_MINOR_VERSION: 'A minor number is required for a version', + MISSING_PATCH_VERSION: 'A patch number is required for a version', + EXCESSIVE_VERSION_PARTS: 'Too many parts for version', + INVALID_QUANTIFIER_PART: 'Invalid version qualifier part', + WILDCARD_IN_VERSION: 'Wildcard aren\'t allowed in a hard version', + INVALID_VERSION_NUMBER: 'This isn\'t a valid version part, expected a number', + INVALID_RANGE: 'A semver range can only be defined with versions', + BARE_PIPE_WITHOUT_LOOSE: 'Bare pipes are only allowed in loose mode', + UNEXPECTED_WORD: (word: string) => + ({ + message: markup`Unexpected word ${word}`, + }), + UNKNOWN_START: 'Unknown start of atom', + EXPECTED_VERSION: 'Unexpected value for version', + }, + + V8: { + SYNTAX_ERROR: (message: string) => ({message, category: 'v8/syntaxError'}), + }, + + // @romejs/js-compiler + LINT: { + PENDING_FIXES: (original: string, formatted: string) => + ({ + category: 'lint/pendingFixes', + message: 'Pending fixes', + advice: [ + { + type: 'diff', + diff: stringDiff(original, formatted), + }, + { + type: 'code', + code: formatted, + }, + ], + }), + + PREFER_TEMPLATE: { + category: 'lint/preferTemplate', + message: 'You\'re using string concatenation when template literals are preferred', + }, + + UNSAFE_NEGATION: { + fixable: true, + category: 'lint/unsafeNegation', + message: 'Unsafe usage of negation operator in left side of binary expression', + }, + + UNUSED_VARIABLES: (kind: string, name: string) => + ({ + category: 'lint/unusedVariables', + message: markup`Unused ${kind} ${name}`, + }), + + UNDECLARED_VARIABLES: (name: string) => + ({ + category: 'lint/undeclaredVariables', + message: markup`Undeclared variable ${name}`, + }), + + SPARSE_ARRAY: { + fixable: true, + category: 'lint/sparseArray', + message: 'Your array contains an empty slot', + }, + + PREFER_FUNCTION_DECLARATIONS: { + category: 'lint/preferFunctionDeclarations', + message: 'Use a function declaration instead of a const function', + fixable: true, + }, + + NO_VAR: { + category: 'lint/noVar', + message: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.', + }, + + NO_UNSAFE_FINALLY: (type: string) => + ({ + category: 'lint/noUnsafeFinally', + message: markup`Unsafe usage of ${type}.`, + }), + + NO_TEMPLATE_CURLY_IN_STRING: { + category: 'lint/noTemplateCurlyInString', + message: `Unexpected template string expression.`, + }, + + NO_SHADOW_RESTRICTED_NAMES: (name: string) => + ({ + category: 'lint/noShadowRestrictedNames', + message: markup`Shadowing of global property ${name}`, + advice: [ + { + type: 'log', + category: 'info', + message: 'Consider renaming this variable. It\'s easy to confuse the origin of variables when they\'re named after a known global.', + }, + ], + }), + + NO_MULTIPLE_SPACES_IN_REGEX_LITERAL: (count: number) => + ({ + fixable: true, + category: 'lint/noMultipleSpacesInRegularExpressionLiterals', + message: 'Unclear multiple spaces in regular expression', + advice: [ + { + type: 'log', + category: 'info', + message: `It's hard to visually count the amount of spaces, it's clearer if you use a quantifier instead. eg / {${String( + count, + )}}/`, + }, + ], + }), + + NO_LABEL_VAR: { + category: 'lint/noLabelVar', + message: 'Labels should not be variable names', + }, + + NO_IMPORT_ASSIGN: (name: string) => + ({ + category: 'lint/noImportAssign', + message: markup`${name} is read-only`, + }), + + NO_EXTRA_BOOLEAN_CAST: { + category: 'lint/noExtraBooleanCast', + message: `Redundant double negation.`, + }, + + NO_FUNCTION_ASSIGN: { + category: 'lint/noFunctionAssign', + message: 'Reassignment of function declaration', + }, + + NO_EXPLICIT_ANY: { + category: 'lint/noExplicitAny', + message: 'Unexpected any. Specify a different type.', + }, + + NO_EMPTY_CHAR_SET: { + fixable: true, + category: 'lint/noEmptyCharacterClass', + message: 'Empty character classes in regular expressions are not allowed', + }, + + NO_DUPLICATE_KEYS: (key: string) => + ({ + category: 'lint/noDuplicateKeys', + message: markup`Duplicate key ${key}`, + }), + + NO_DUPLICATE_CASE: (value: string) => + ({ + category: 'lint/noDuplicateCase', + message: markup`Duplicate case ${value} not allowed.`, + }), + + NO_DUPE_ARGS: (name: string) => + ({ + category: 'lint/noDupeArgs', + message: markup`Duplicate argument ${name} in function definition`, + }), + + NO_DELETE_VARS: { + category: 'lint/noDeleteVars', + message: 'Variables should not be deleted.', + }, + + NO_DEBUGGER: { + fixable: true, + category: 'lint/noDebugger', + message: 'Unexpected \'debugger\' statement', + }, + + NO_DANGLING_BACKSLASH_IN_REGEX: { + category: 'lint/noDanglingBackslash', + message: 'Dangling backslash in a regular expression', + }, + + NO_COND_ASSIGN: { + category: 'lint/noCondAssign', + message: 'Cannot assign variable in loop condition', + }, + + NO_COMPARE_NEG_ZERO: (op: string) => + ({ + category: 'lint/noCompareNegZero', + message: `Do not use the '${op}' operator to compare against -0`, + fixable: op === '===', + }), + + NO_ASYNC_PROMISE_EXECUTOR: { + category: 'lint/noAsyncPromiseExecutor', + message: 'Promise executor functions should not be async.', + }, + + GETTER_RETURN: (got: string) => + ({ + category: 'lint/getterReturn', + message: `Expected a 'return' at end of a getter method but got ${got}`, + }), + + EMPTY_BLOCKS: { + category: 'lint/emptyBlocks', + message: 'Empty block', + }, + + DUPLICATE_REGEX_GROUP_NAME: ( + name: string, + pointers: Array, + ) => + ({ + category: 'lint/noDuplicateGroupNamesInRegularExpressions', + message: `Duplicate group name ${name} in regular expression`, + advice: buildDuplicateLocationAdvice(pointers), + }), + + DEFAULT_EXPORT_SAME_BASENAME: ( + {defaultName, defaultType, actualFilename, correctFilename}: { + defaultName: string; + defaultType: string; + actualFilename: string; + correctFilename: string; + }, + ) => { + let adviceMessage = ''; + + if (defaultName === '*default*') { + adviceMessage += 'The'; + } else { + adviceMessage += + `Filename should be ${correctFilename} or the`; + } + + adviceMessage += + ` ${defaultType} name should be ${actualFilename}`; + + return { + fixable: true, + category: 'lint/defaultExportSameBasename', + message: `Filename and the name of a default ${defaultType} should match`, + advice: [ + { + type: 'log', + category: 'info', + message: adviceMessage, + }, + ], + }; + }, + }, + + PROJECT_MANAGER: { + DUPLICATE_PACKAGE: (packageName: string, existing: string) => + ({ + category: 'projectManager/nameCollision', + message: `Duplicate package name ${packageName}`, + advice: [ + { + type: 'log', + category: 'info', + message: `Defined already by `, + }, + ], + }), + + HASTE_COLLISION: (hasteName: string, existing: string) => + ({ + category: 'projectManager/nameCollision', + message: `Found a haste collision for ${hasteName}`, + advice: [ + { + type: 'log', + category: 'info', + message: `Defined already by `, + }, + ], + }), + + NOT_FOUND: { + category: 'projectManager/missing', + message: `Couldn't find a project`, + advice: [ + { + type: 'log', + category: 'info', + message: 'Run rome init in this folder to initialize a project', + }, + ], + }, + + INCORRECT_CONFIG_FILENAME: (validFilenames: Array) => + ({ + category: 'projectManager/incorrectConfigFilename', + message: `Invalid rome config filename, ${validFilenames.join( + ' or ', + )} are the only valid filename`, + }), + }, + + FORMAT: { + DISABLED: { + category: 'format/disabled', + message: 'Format is disabled for this project', + // TODO advice and better error message + }, + }, + + // @romejs/js-compiler + COMPILER: { + CLASSES_UNSUPPORTED: { + category: 'compile/classes', + message: 'The classes transform doesn\'t know how to transform this', + }, + + JSX_NOT_XML: { + category: 'compile/jsx', + message: 'JSX is not XML', + }, + }, + + // @romejs/string-escape + STRING_ESCAPE: { + NOT_ENOUGH_CODE_POINTS: 'Not enough code point digits', + INVALID_STRING_CHARACTER: 'Invalid string character (U+0000 to U+001F)', + INVALID_HEX_DIGIT_FOR_ESCAPE: 'Invalid hex digit for unicode escape', + }, + + ANALYZE_DEPENDENCIES: { + CJS_EXPORT_IN_ES: { + category: 'analyzeDependencies/cjsExportInES', + message: 'You cannot use CommonJS exports in an ES module', + }, + }, + + // @romejs/string-markup + STRING_MARKUP: { + UNCLOSED_STRING: 'Unclosed string', + EXPECTED_CLOSING_TAG_NAME: 'Expected closing tag name', + UNKNOWN_START: 'Unknown child start', + EXPECTED_ATTRIBUTE_NAME: 'Expected attribute name', + + INCORRECT_CLOSING_TAG_NAME: (expected: string, got: string) => + ({ + message: markup`Expected to close ${expected} but found ${got}`, + }), + + UNCLOSED_TAG: (tagName: string) => + ({ + message: markup`Unclosed ${tagName} tag`, + }), + + INVALID_ATTRIBUTE_NAME_FOR_TAG: (tagName: string, attributeName: string) => + ({ + message: markup`${attributeName} is not a valid attribute name for <${tagName}>`, + }), + + UNKNOWN_TAG_NAME: (tagName: string) => + ({ + message: markup`Unknown tag name ${tagName}`, + }), + }, + + // @romejs/path-match + PATH_MATCH: { + INVALID_PATTERN_SEGMENT_PART: 'Invalid pattern segment part', + INVALID_PATH_SEGMENT: 'Invalid path segment', + }, + + TESTS: { + CANCELLED: { + category: 'tests/cancelled', + message: 'Test was cancelled', + }, + + UNDECLARED: { + message: 'No tests declared in this file', + category: 'tests/noneDeclared', + }, + }, + + SUPPRESSIONS: { + UNUSED: { + message: 'Unused suppression. Did not hide any errors.', + category: 'suppressions/unused', + }, + + PREFIX_TYPO: (prefix: string, suggestion: string) => + ({ + category: 'suppressions/incorrectPrefix', + message: markup`Invalid suppression prefix ${prefix}`, + advice: [ + { + type: 'log', + category: 'info', + message: `Did you mean ${suggestion}?`, + }, + ], + }), + + DUPLICATE: (category: string) => + ({ + category: 'suppressions/duplicate', + message: markup`Duplicate suppression category ${category}`, + }), + }, + + SNAPSHOTS: { + MISSING_NEWLINE_AFTER_CODE_BLOCK: 'Newline required after code block', + MISSING_NEWLINE_BEFORE_CODE_BLOCK: 'Newline required before code block end', + UNCLOSED_CODE_BLOCK: 'Unclosed code block', + EXPECTED_CODE_BLOCK_AFTER_HEADING: 'Expected a code block after this heading', + + REDUNDANT: { + category: 'tests/snapshots/redundant', + message: 'Snapshot should not exist', + }, + + MISSING: { + category: 'tests/snapshots/missing', + message: 'Snapshot does not exist', + }, + + INCORRECT: (expected: string, got: string) => + ({ + category: 'tests/snapshots/incorrect', + message: 'Snapshots do not match', + advice: [ + { + type: 'diff', + diff: stringDiff(expected, got), + }, + ], + }), + }, + + BUNDLER: { + TOP_LEVEL_AWAIT_IN_LEGACY: { + category: 'bundler/topLevelAwait', + message: 'This module contains a top level await which isn\'t supported in wrapper mode', + }, + + DETECTED_CYCLE: ( + localName: string, + target: string, + culprit: string, + path: Array, + ) => { + function formatPart(part: string, index?: number): string { + const tagged = ``; + if (part === culprit) { + return `${tagged}[1]`; + } else if (part === target) { + return `${tagged}[2]`; + } else if (index === 0) { + return `${tagged} ENTRY`; + } else { + return tagged; + } + } + + return { + category: 'bundler/moduleCycle', + message: `The variable ${localName} won't be initialized yet`, + advice: [ + { + type: 'log', + category: 'info', + message: 'This is because the module it belongs to wont be executed yet. This is due to a circular dependency creating a module cycle.', + }, + { + type: 'log', + category: 'info', + message: `The likely cause is the file ${formatPart(culprit)} that was required by ${formatPart( + target, + )} which created a circular dependency:`, + }, + { + type: 'list', + reverse: true, + ordered: true, + list: path.map(formatPart), + }, + ], + }; + }, + + IMPORT_TYPE_MISMATCH: ( + exportName: string, + source: string, + importedAsKing: string, + actualKind: string, + exportLoc: undefined | SourceLocation, + ) => + ({ + category: 'bundler/importTypeMismatch', + message: `The export ${exportName} in was incorrectly imported as a ${importedAsKing} when it's actually a ${actualKind}`, + advice: exportLoc && + [ + { + type: 'log', + category: 'info', + message: `Export was defined here in `, + }, + + { + type: 'frame', + location: exportLoc, + }, + ], + }), + + UNKNOWN_EXPORT: ( + name: string, + source: string, + exportedNames: Array, + formatExportedName: (name: string) => { + location: undefined | DiagnosticLocation; + source: undefined | string; + }, + ) => + ({ + message: `Couldn't find export ${name} in `, + category: 'bundler/unknownExport', + advice: exportedNames.length === 0 ? [ + { + type: 'log', + category: 'info', + message: 'This file doesn\'t have any exports', + }, + ] : buildSuggestionAdvice(name, exportedNames, { + formatItem: (name) => { + const {location, source} = formatExportedName(name); + + if (location !== undefined) { + if (location.start === undefined) { + name = + `${name}`; + } else { + name = + `${name}`; + } + } + + if (source !== undefined) { + name += ` (from )`; + } + + return name; + }, + }), + }), + }, + + SPDX: { + UNKNOWN_LICENSE: (id: string, knownLicenses: Array) => + ({ + message: markup`Unknown SPDX license ${id}`, + advice: buildSuggestionAdvice(id, knownLicenses), + }), + + VALID_LICENSE_WITH_MISSING_DASH: (possibleCorrectLicense: string) => + ({ + message: `Missing dash between SPDX license name and version`, + advice: [ + { + type: 'log', + category: 'info', + message: `Did you mean ${possibleCorrectLicense}?`, + }, + ], + }), + + WITH_RIGHT_LICENSE_ONLY: 'Only a license id can be on the right side of a WITH', + + OPERATOR_NOT_BETWEEN_EXPRESSION: 'Can only use AND/OR in between an expression', + + PLUS_NOT_AFTER_LICENSE: 'A plus can only come after a license id', + + UNOPENED_PAREN: 'Nothing open to close', + }, + + // @romejs/js-parser + JS_PARSER: { + FLOW_ANNOTATION_WITH_TYPESCRIPT_ENABLED: 'Cannot have a @flow annotation comment when TypeScript syntax has been enabled', + UNTERMINATED_BLOCK_COMMENT: 'Unterminated comment', + UNTERMINATED_JSX_STRING: 'Unterminated string constant', + INVALID_UNICODE_ESCAPE: 'Invalid Unicode escape', + EXPECTED_UNICODE_ESCAPE: 'Expecting Unicode escape sequence \\uXXXX', + BAD_HEX_ESCAPE: 'Bad character escape sequence', + OCTAL_IN_STRICT_MODE: 'Octal literal in strict mode', + UNTERMINATED_TEMPLATE: 'Unterminated template', + UNTERMINATED_STRING: 'Unterminated string constant', + OUT_OF_BOUND_CODE_POINT: 'Code point out of bounds', + IDENTIFIER_AFTER_NUMBER: 'Identifier directly after number', + OCTAL_BIGINT: 'A bigint can\'t be an octal', + DECIMAL_BIGINT: 'A bigint can\'t have a decimal', + INVALID_NUMBER: 'Invalid number', + LEGACY_OCTAL_IN_STRICT_MODE: 'Legacy octal literals are not allowed in strict mode', + INVALID_INT_TOKEN: 'Invalid or unexpected int token', + UNICODE_ESCAPE_IN_REGEX_FLAGS: 'Regular expression flags can\'t contain unicode escapes', + UNTERMINATED_REGEX: 'Unterminated regular expression', + EXPECTED_RELATIONAL_OPERATOR: 'Expected relational operator', + UNEXPECTED_SPACE: 'Unexpected space', + EXPECTED_SEMI_OR_LINE_TERMINATOR: 'Expected a semicolon or a line terminator', + GET_SET_CLASS_CONSTRUCTOR: 'Constructor can\'t have get/set modifier', + ASYNC_CLASS_CONSTRUCTOR: 'Constructor cannot be async', + GENERATOR_CLASS_CONSTRUCTOR: 'Constructor cannot be a generator', + DUPLICATE_CLASS_CONSTRUCTOR: 'Duplicate constructor in the same class', + UNKNOWN_CLASS_PROPERTY_START: 'Unknown class property start', + CLASS_STATIC_PROTOTYPE_PROPERTY: 'Classes may not have static property named prototype', + CLASS_PRIVATE_FIELD_NAMED_CONSTRUCTOR: 'Classes may not have a private field named \'#constructor\'', + CLASS_PROPERTY_NAME_CONSTRUCTOR: 'Classes may not have a non-static field named \'constructor\'', + PROTO_PROP_REDEFINITION: 'Redefinition of __proto__ property', + MISSING_CONDITIONAL_SEPARATOR: 'Missing conditional expression consequent separator', + WRAP_EXPONENTIATION: 'Illegal expression. Wrap left hand side or entire exponentiation in parentheses.', + DELETE_LOCAL_VARIABLE_IN_STRICT: 'Deleting local variable in strict mode', + DELETE_PRIVATE_FIELD: 'Deleting a private field is not allowed', + TAGGED_TEMPLATE_IN_OPTIONAL_CHAIN: 'Tagged Template Literals are not allowed in optionalChain', + YIELD_NAME_IN_GENERATOR: 'Can not use \'yield\' as identifier inside a generator', + AWAIT_NAME_IN_ASYNC: 'Can not use \'await\' as identifier inside an async function', + EMPTY_PARENTHESIZED_EXPRESSION: 'Parenthesized expression didnt contain anything', + AWAIT_IN_ASYNC_PARAMS: 'await is not allowed in async function parameters', + YIELD_IN_GENERATOR_PARAMS: 'yield is not allowed in generator parameters', + PARENTHESIZED_FUNCTION_PARAMS: 'Function parameters can\'t be parenthesized', + NEW_WITH_TYPESCRIPT_TYPE_ARGUMENTS_NO_PARENS: 'In TypeScript, a new expression with type arguments must have parens', + INVALID_TEMPLATE_ESCAPE: 'Invalid escape sequence in template', + EXPECTED_IDENTIFIER: 'Expected an identifier', + IMPORT_EXACT_ARGUMENTS: 'import() requires exactly one argument', + IMPORT_TRAILING_COMMA: 'Trailing comma is disallowed inside import(...) arguments', + IMPORT_SPREAD: 'Spread is not allowed in import()', + IMPORT_NEW_CALLEE: 'Cannot use new with import(...)', + SUPER_OUTSIDE_METHOD: 'super is only allowed in object methods and classes', + INVALID_SUPER_SUFFIX: 'Invalid super suffix operator', + AWAIT_OUTSIDE_ASYNC: 'Can\'t use await outside of an async function', + AWAIT_STAR: 'await* has been removed from the async functions proposal. Use Promise.all() instead.', + NEW_TARGET_OUTSIDE_CLASS: 'new.target can only be used in functions or class properties', + MULTIPLE_DESTRUCTURING_RESTS: 'Cannot have multiple rest elements when destructuring', + TRAILING_COMMA_AFTER_REST: 'A trailing comma is not permitted after the rest element', + GETTER_WITH_PARAMS: 'getter should have no parameters', + SETTER_WITH_REST: 'setter function argument must not be a rest parameter', + SETTER_NOT_ONE_PARAM: 'setter should have exactly one param', + ASYNC_GETTER_SETTER: 'An object setter/getter can\'t be async', + GENERATOR_GETTER_SETTER: 'An object setter/getter can\'t be a generator', + ARGUMENTS_IN_CLASS_FIELD: '\'arguments\' is not allowed in class field initializer', + NON_SIMPLE_PARAM_IN_EXPLICIT_STRICT_FUNCTION: 'Non-simple parameter in strict mode', + STRICT_DIRECTIVE_IN_NON_SIMPLE_PARAMS: 'Illegal \'use strict\' directive in function with non-simple parameter list', + OBJECT_PROPERTY_WITH_TYPE_PARAMETERS: 'Object property cannot have type parameters', + ILLEGAL_VARIANCE: 'Variance is not allowed here', + OBJECT_METHOD_IN_PATTERN: 'Object methods aren\'t allowed in object patterns', + IMPORT_META_OUTSIDE_MODULE: `import.meta may only appear in a module`, + EXPECTED_ARROW_AFTER_ASYNC_TYPE_PARAMS: 'Expected arrow because we are a possible async arrow and type annotated parameters were present', + INVALID_OBJECT_PATTERN_PROP: 'Invalid property node for object pattern', + ASYNC_OBJECT_METHOD_LINE_BREAK: 'There shouldn\'t be any newlines between async and the rest of the function', + SPACE_BETWEEN_PRIVATE_HASH: 'Unexpected space between # and identifier', + CONFUSING_CALL_ARGUMENT: 'Function parameter type annotation? Possibly forgot curlies around an object. Possibly forgot async keyword.', + EXPECTED_ARROW_AFTER_TYPE_PARAMS: 'Expected an arrow function after this type parameter declaration', + REQUIRED_CLASS_NAME: 'Class name is required', + JSX_ELEM_TYPE_ARGUMENTS_OUTSIDE_TS: 'JSX element type arguments are only allowed in TS', + UNWRAPPED_ADJACENT_JHX: `Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...?`, + CONFUSED_OR: 'Unexpected ||, did you mean just |?', + INVALID_ASSIGNMENT_TARGET: 'Not a valid assignment target', + IMPORT_KIND_SPECIFIER_ON_IMPORT_DECLARATION_WITH_KIND: 'The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements', + DESTRUCTURING_IN_IMPORT: 'ES2015 named imports do not destructure. Use another statement for destructuring after the import.', + IMPORT_TYPE_STAR: 'import * is not allowed', + IMPORT_MISSING_SOURCE: 'import missing a source', + EXPORT_TYPE_NAMESPACE: 'Can\'t have a type export namespacer specifier', + EXPORT_MISSING_FROM: 'Expected `from` for an export node', + EXPORT_FROM_NOT_STRING: 'Export from only allows strings', + BINDING_MEMBER_EXPRESSION: 'Binding member expression', + INVALID_OBJECT_PATTERN_PROPERTY: 'Not a valid assignment object pattern property', + OBJECT_PATTERN_CANNOT_CONTAIN_METHODS: 'Object pattern cannot contains methods', + INVALID_ASSIGNMENT_PATTERN_OPERATOR: 'Only \'=\' operator can be used for specifying default value.', + INVALID_OBJECT_REST_ARGUMENT: 'Invalid rest operator\'s argument', + INVALID_EXPORT_DEFAULT: 'Only expressions, functions or classes are allowed as the `default` export.', + INVALID_EXPORT_DECLARATION: 'Invalid export declaration', + DESTRUCTURING_REST_ELEMENT_NOT_LAST: `The rest element has to be the last element when destructuring`, + REST_INVALID_ARGUMENT: 'Invalid rest operator\'s argument', + EXPORT_ASYNC_NO_FUNCTION_KEYWORD: 'Started with `export async` so we expected to receive an async function but no function keyword was found', + TYPE_CAST_WITHOUT_ANNOTATION: 'Type cast expression has no type annotation. Did you mean for this to be a function parameter?', + TYPE_CAST_CANNOT_BE_OPTIONAL: 'Type cast expressions cannot be optional. Did you mean for this to be a function parameter?', + TYPE_CAST_EXPECTED_PARENS: 'The type cast expression is expected to be wrapped with parentheses', + FLOW_SPACE_BETWEEN_PERCENT_CHECKS: 'Spaces between \xb4%\xb4 and \xb4checks\xb4 are not allowed here.', + FLOW_BAD_UNDERSCORE_NAME: '`_` is only allowed as a type argument to call or new', + FLOW_UNINFERRABLE_PREDICATE_ON_FUNCTION: 'Predicate function declarations need to declare a predicate expression', + FLOW_DECLARE_MODULE_IN_DECLARE_MODULE: '`declare module` cannot be used inside another `declare module`', + FLOW_UNKNOWN_DECLARATION_START: 'Unknown start to Flow declaration', + FLOW_IMPORT_KINDLESS_IN_DECLARE_MODULE: 'Imports within a `declare module` body must always be `import type` or `import typeof`', + FLOW_MIXED_DECLARE_EXPORTS: 'Found both `declare module.exports` and `declare export` in the same module. Modules can only have 1 since they are either an ES module or they are a CommonJS module', + FLOW_DUPLICATE_DECLARE_MODULE_EXPORTS: 'Duplicate `declare module.exports` statement', + FLOW_DISALLOW_DEFAULT_TYPE_PARAMETER: 'Default type parameters arent allowed here', + FLOW_DISALLOWED_SPREAD: 'Spread operator cannot appear in class or interface definitions', + FLOW_DEFAULT_TYPE_PARAMETER_REQUIRED: 'Type parameter declaration needs a default, since a preceding type parameter declaration has a default.', + FLOW_INEXACT_SYNTAX_NOT_ALLOWED: 'Explicit inexact syntax is only allowed inside inexact objects', + FLOW_INEXACT_CANNOT_APPEAR_IN_EXPLICIT_EXACT: 'Explicit inexact syntax cannot appear inside an explicit exact object type', + FLOW_INEXACT_MUST_BE_AT_END: 'Explicit inexact syntax must appear at the end of an inexact object', + FLOW_TYPE_CAST_IN_TS: 'Flow type cast expressions aren\'t allowed in TypeScript', + TYPE_NUMERIC_LITERAL_PLUS: 'Numeric literal type annotations cannot stand with a +, omit it instead', + TYPE_NUMERIC_LITERAL_EXPECTED: `Unexpected token, expected "number"`, + FLOW_INVALID_ASYNC_ARROW_WITH_TYPE_PARAMS: 'Invalid async arrow with type parameters', + FLOW_UNKNOWN_PRIMARY_START: 'Unknown flow primarty type start', + FLOW_UNKNOWN_DECLARE_EXPORT_START: 'No valid start for Flow declare export declaration found', + FLOW_DECLARE_MODULE_INVALID_CHILD: 'Only declares and type imports are allowed inside declare module', + JSX_INVALID_ATTRIBUTE_VALUE: 'JSX attribute value should be either an expression or a quoted JSX text', + JSX_UNCLOSED_SELF_CLOSING_TAG: 'Unclosed JSX element open', + JSX_UNCLOSED_CLOSING_TAG: 'Unclosed JSX element close', + JSX_EMPTY_ATTRIBUTE_VALUE: 'JSX attribute cannot be an empty expression', + JSX_UNKNOWN_IDENTIFIER_TOKEN: 'Unknown JSX identifier token', + TS_IMPORT_ARG_NOT_STRING: 'Argument in a type import must be a string literal', + TS_CONSTANT_NOT_LITERAL: 'Only literal values are allowed as a constant type', + TS_INVALID_SIGNATURE_BINDING_NODE: 'Invalid node in signature binding list', + TS_REQUIRED_FOLLOWS_OPTIONAL: 'A required element cannot follow an optional element.', + TS_TEMPLATE_LITERAL_WITH_SUBSTITUION: 'Template literal types cannot have any substitution', + TS_UNKNOWN_NON_ARRAY_START: 'Unknown TS non array type start', + TS_INVALID_READONLY_MODIFIER: '\'readonly\' type modifier is only permitted on array and tuple literal types.', + TS_EXTERNAL_MODULE_REFERENCE_ARG_NOT_STRING: 'TypeScript require() must have a single string argument', + TS_UNKNOWN_DECLARE_START: 'Unknown TypeScript declare start', + TS_UNEXPECTED_CAST_IN_PARAMETER_POSITION: 'Unexpected type cast in parameter position', + TS_DISABLED_BUT_ACCESSIBILITY_OR_READONLY: 'Accessibility and readonly syntax found but TS is not enabled', + TS_PARAMETER_PROPERTY_BINDING_PATTERN: 'A parameter property may not be declared using a binding pattern.', + TYPE_ANNOTATION_AFTER_ASSIGNMENT: 'Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`', + TYPE_BINDING_PARAMETER_OPTIONAL: 'A binding pattern parameter cannot be optional in an implementation signature.', + ILLEGAL_FUNCTION_IN_STRICT: 'In strict mode code, functions can only be declared at top level or inside a block', + ILLEGAL_FUNCTION_IN_NON_STRICT: 'In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement', + ILLEGAL_GENERATOR_DEFINITION: 'Generators can only be declared at the top level or inside a block', + ILLEGAL_ASYNC_DEFINITION: 'Async functions can only be declared at the top level or inside a block', + LEXICAL_DECLARATION_IN_SINGLE_STATEMENT_CONTEXT: 'Lexical declaration cannot appear in a single-statement context', + IMPORT_EXPORT_MUST_TOP_LEVEL: '\'import\' and \'export\' may only appear at the top level', + REGULAR_FOR_AWAIT: 'Can\'t have an await on a regular for loop', + RETURN_OUTSIDE_FUNCTION: '\'return\' outside of function', + MULTIPLE_DEFAULT_CASE: 'Multiple default clauses', + SWITCH_STATEMENT_OUTSIDE_CASE: 'Statement outside of a case or default block', + NEWLINE_AFTER_THROW: 'Illegal newline after throw', + TRY_MISSING_FINALLY_OR_CATCH: 'Missing catch or finally clause', + INVALID_LABEL_DECLARATION: 'Invalid labeled declaration', + WITH_IN_STRICT: '\'with\' in strict mode', + OCTAL_IN_STRICT: 'Octal literal in strict mode', + FOR_IN_OF_WITH_INITIALIZER: 'Loop variable declaration may not have an initializer', + CONST_WITHOUT_INITIALIZER: 'A constant must have an initializer', + COMPLEX_BINDING_WITHOUT_INITIALIZER: 'Complex binding patterns require an initialization value', + ACCESSOR_WITH_TYPE_PARAMS: 'An accessor cannot have type parameters', + + DUPLICATE_LABEL: (label: string, loc: undefined | SourceLocation) => + ({ + message: markup`Label ${label} is already declared`, + advice: buildDuplicateLocationAdvice([loc]), + }), + + UNKNOWN_LABEL: (label: undefined | string) => + ({ + message: label === undefined + ? 'No loop label found' : markup`Unknown label ${label}`, + }), + + IMPORT_EXPORT_IN_SCRIPT: (manifestPath: string) => + ({ + message: `import and export can only appear in a module`, + advice: [ + // TODO this advice is pointless if you have syntax extensions enabled + + { + type: 'log', + category: 'info', + message: 'Change the extension to .mjs to turn this file into a module', + }, + { + type: 'log', + category: 'info', + message: `Add "type": "module" to your `, + }, + ], + }), + + SUPER_CALL_OUTSIDE_CONSTRUCTOR: { + message: 'super() is only valid inside a class constructor of a subclass', + advice: [ + { + type: 'log', + category: 'info', + message: 'Maybe a typo in the method name (\'constructor\') or not extending another class?', + }, + ], + }, + + JSX_DISABLED: { + message: 'JSX syntax isn\'t enabled', + advice: [ + { + type: 'log', + category: 'info', + message: 'Are you using TypeScript? Change the file extension to .tsx', + }, + { + type: 'log', + category: 'info', + message: 'Are you using Flow? Add a @flow comment annotation to the top of the file', + }, + { + type: 'log', + category: 'info', + message: 'Not using either? Change the file extension to .jsx', + }, + // TODO you can also add `@jsx whatever` at the top of a file + ], + }, + + JSX_IN_TS_EXTENSION: { + message: 'JSX isn\'t allowed in regular TypeScript files', + advice: [ + { + type: 'log', + category: 'info', + message: 'Change the file extension to .tsx to enable JSX support', + }, + ], + }, + + INVALID_PARENTEHSIZED_LVAL: (patternType: undefined | 'object' | 'array') => + ({ + message: 'Invalid parenthesized binding', + advice: patternType === 'object' ? [ + { + type: 'log', + category: 'info', + message: 'Did you use `({a}) = 0` instead of `({a} = 0)`?', + }, + ] : patternType === 'array' ? [ + { + type: 'log', + category: 'info', + message: 'Did you use `([a]) = 0` instead of `([a] = 0)`?', + }, + ] : [], + }), + + EXPECTED_COMMA_SEPARATOR: (context: string) => + ({ + message: `Expected a comma to separate items in ${context}`, + }), + + INVALID_LEFT_HAND_SIDE: (context: string) => + ({ + message: `Invalid left-hand side in ${context}`, + }), + + TS_EMPTY_LIST: (descriptor: string) => + ({ + message: `${descriptor} list cannot be empty`, + }), + + JSX_EXPECTED_CLOSING_TAG: (name: string, openingLoc: SourceLocation) => + ({ + message: `Expected a corresponding JSX closing tag for ${name}`, + advice: buildJSXOpeningAdvice(name, openingLoc), + }), + + JSX_EXPECTED_CLOSING_FRAGMENT_TAG: (name: string, openingLoc: SourceLocation) => + ({ + message: 'Expected JSX closing fragment tag', + advice: buildJSXOpeningAdvice(name, openingLoc), + }), + + JSX_UNKNOWN_CHILD_START: (name: string, openingLoc: SourceLocation) => + ({ + message: 'Unknown JSX children start', + advice: buildJSXOpeningAdvice(name, openingLoc), + }), + + JSX_UNCLOSED_ELEMENT: (name: string, openingLoc: SourceLocation) => + ({ + message: 'Unclosed JSX element', + advice: buildJSXOpeningAdvice(name, openingLoc), + }), + + FLOW_RESERVED_TYPE: (word: string) => + ({ + message: `Cannot overwrite primitive type ${word}`, + }), + + FLOW_DECLARE_EXPORT_UNSUPPORTED: (label: string, suggestion: string) => + ({ + message: `\`declare export ${label}\` is not supported. Use \`${suggestion}\` instead`, + }), + + FLOW_REQUIRED: (label: string) => + ({ + message: `A ${label} is only valid inside of a Flow file`, + advice: [ + { + type: 'log', + category: 'info', + message: 'To enable Flow support, add a @flow comment annotation to the top of the file', + }, + ], + }), + + TS_REQUIRED: (label: string) => + ({ + message: `A ${label} is only valid inside of a TypeScript file`, + advice: [ + { + type: 'log', + category: 'info', + message: 'To enable TypeScript support, the file extension should end in .ts or .tsx', + }, + ], + }), + + FLOW_OR_TEST_REQUIRED: (label: string) => + ({ + message: `A ${label} is only valid inside of a TypeScript or Flow file`, + advice: [ + { + type: 'log', + category: 'info', + message: 'Did you mean TypeScript? Change the file extension to .ts or .tsx', + }, + { + type: 'log', + category: 'info', + message: 'Did you mean Flow? Add a @flow comment annotation to the top of the file', + }, + ], + }), + + DUPLICATE_EXPORT: (name: string, existing: SourceLocation) => + ({ + message: name === 'default' + ? 'Only one default export allowed per module.' : `\`${name}\` has already been exported. Exported identifiers must be unique.`, + advice: buildDuplicateLocationAdvice([existing]), + }), + + NEW_IN_OPTIONAL_CHAIN: (responsiblePointer?: DiagnosticLocation) => + ({ + message: 'constructors in/after an Optional Chain are not allowed', + advice: responsiblePointer && [ + { + type: 'log', + category: 'info', + message: 'Optional chain member responsible', + }, + { + type: 'frame', + location: responsiblePointer, + }, + ], + }), + + UNKNOWN_EXPRESSION_ATOM_START: (context: string) => + ({ + message: `Unknown start to an ${context}`, + }), + + INVALID_META_PROPERTY: (metaName: string, propertyName: string) => + ({ + message: `The only valid meta property for ${metaName} is ${metaName}.${propertyName}`, + }), + + ARGUMENT_CLASH_IN_STRICT: (name: string, loc: undefined | SourceLocation) => + ({ + message: markup`Argument ${name} name clash in strict mode`, + advice: buildDuplicateLocationAdvice([loc]), + }), + + RESERVED_WORD: (word: string) => + ({ + message: `${word} is a reserved word`, + }), + + UNEXPECTED_KEYWORD: (keyword: string) => + ({ + message: `Unexpected keyword ${keyword}`, + }), + + UNEXPECTED_TOKEN: ( + expected: undefined | string, + possibleShiftMistake: boolean, + ) => + ({ + message: expected === undefined + ? 'Unexpected token' : `Unexpected token, expected ${expected}`, + advice: possibleShiftMistake ? [ + { + type: 'log', + category: 'info', + message: `Did you accidently hold shift?`, + }, + ] : [], + }), + + EXPECTED_CLOSING: (name: string, char: string, location: DiagnosticLocation) => + ({ + message: `Unclosed ${name}`, + + advice: [ + { + type: 'log', + category: 'info', + message: `We expected to find the closing character ${char} here`, + }, + { + type: 'frame', + location, + }, + ], + }), + + EXPECTED_KEYWORD: (keyword: string) => + ({ + message: markup`Expected keyword ${keyword}`, + }), + + ESCAPE_SEQUENCE_IN_WORD: (word: string) => + ({ + message: markup`${word} can't contain a unicode escape`, + }), + + EXPECTED_ENABLE_SYNTAX: (syntaxName: string) => + ({ + message: markup`Expected ${syntaxName} syntax to be enabled`, + }), + + UNEXPECTED_HASH: (exclamationFollowed: boolean) => + ({ + message: 'Unexpected character #', + advice: exclamationFollowed ? [ + { + type: 'log', + category: 'info', + message: 'Did you want to write a hashbang? A hashbang can only be the first thing in a file.', + }, + ] : [], + }), + + UNEXPECTED_UNICODE_CHARACTER: ( + char: string, + unicodeName: string, + equivalentChar: string, + equivalentName: string, + ) => + ({ + message: markup`Unexpected Unicode character '${char}' (${unicodeName})`, + + advice: [ + { + type: 'log', + category: 'info', + message: markup`Did you mean '${equivalentChar}' (${equivalentName})? Both characters look the same, but are not.`, + }, + ], + }), + + EXPECTED_NUMBER_IN_RADIX: (radix: number) => + ({ + message: `Expected number in radix ${String(radix)}`, + }), + + INVALID_IDENTIFIER_NAME: (name: string) => + ({ + message: `Invalid identifier ${name}`, + }), + + ESCAPE_SEQUENCE_IN_KEYWORD: (keyword: string) => + ({ + message: `Escape sequence in keyword ${keyword}`, + }), + }, + + // @romejs/js-analysis + TYPE_CHECK: { + NOT_CALLABLE: { + category: 'typeCheck/uncallable', + message: `This type isn't callable`, + }, + + INCOMPATIBILITY: (upper: string, originLoc: undefined | SourceLocation) => + ({ + category: 'typeCheck/incompatible', + message: 'Type incompatibility found', + advice: [ + { + type: 'log', + category: 'error', + message: `This type is incompatible with expected type of`, + }, + + originLoc === undefined ? { + type: 'log', + category: 'info', + message: upper, + } : { + type: 'frame', + location: originLoc, + marker: upper, + }, + ], + }), + + UNKNOWN_IMPORT: ( + importedName: string, + source: string, + possibleNames: Array, + ) => + ({ + category: 'typeCheck/unknownImport', + message: `Unknown import '${importedName}' in '${source}'`, + advice: buildSuggestionAdvice(importedName, possibleNames), + }), + + UNKNOWN_PROP: (key: string, possibleNames: Array) => + ({ + message: markup`Property ${key} not found in`, + category: 'typeCheck/unknownProperty', + advice: buildSuggestionAdvice(key, possibleNames), + }), + + UNDECLARED_VARIABLE: (name: string, possibleNames: Array) => + ({ + category: 'typeCheck/undeclaredVariable', + message: markup`Undeclared variable ${name}`, + advice: buildSuggestionAdvice(name, possibleNames), + }), + + NOT_EXHAUSTIVE: (only: string, target: string) => + ({ + category: 'typeCheck/notExhaustive', + //message += `but allows ${this.extraenous.map(type => this.utils.humanize(type)).join(' | ')}`; + message: `Expected only a ${only} but got ${target}`, + }), + + MISSING_CONDITION: (missing: Array) => + ({ + category: 'typeCheck/missingCondition', + message: `Missing the conditions ${missing.join(', ')}`, + }), + }, +}); diff --git a/packages/@romejs/diagnostics/errors.ts b/packages/@romejs/diagnostics/errors.ts index 6bf36b20d51..9ed1ac192d7 100644 --- a/packages/@romejs/diagnostics/errors.ts +++ b/packages/@romejs/diagnostics/errors.ts @@ -5,16 +5,16 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics, DiagnosticsProcessor} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticsProcessor} from '@romejs/diagnostics'; import {escapeMarkup} from '@romejs/string-markup'; import {stripAnsi} from '@romejs/string-ansi'; import {printDiagnosticsToString} from '@romejs/cli-diagnostics'; -import {PartialDiagnostic, DiagnosticSuppressions} from './types'; +import {Diagnostic, DiagnosticSuppressions} from './types'; export class DiagnosticsError extends Error { constructor( message: string, - diagnostics: PartialDiagnostics, + diagnostics: Diagnostics, suppressions: DiagnosticSuppressions = [], ) { if (diagnostics.length === 0) { @@ -25,9 +25,9 @@ export class DiagnosticsError extends Error { message += stripAnsi(printDiagnosticsToString(diagnostics, { origins: [], })); - message += stripAnsi(diagnostics.map((diag) => `- ${diag.message}`).join( - '\n', - )); + message += stripAnsi(diagnostics.map((diag) => + `- ${diag.description.message.value}` + ).join('\n')); super(escapeMarkup(message)); this.diagnostics = diagnostics; @@ -35,25 +35,27 @@ export class DiagnosticsError extends Error { this.name = 'DiagnosticsError'; } - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; suppressions: DiagnosticSuppressions; } export function createSingleDiagnosticError( - diag: PartialDiagnostic, + diag: Diagnostic, suppressions?: DiagnosticSuppressions, ): DiagnosticsError { - return new DiagnosticsError(diag.message, [diag], suppressions); + return new DiagnosticsError( + diag.description.message.value, + [diag], + suppressions, + ); } -export function getDiagnosticsFromError( - err: Error, -): undefined | PartialDiagnostics { +export function getDiagnosticsFromError(err: Error): undefined | Diagnostics { if (err instanceof DiagnosticsError) { const processor = new DiagnosticsProcessor({}); processor.addSuppressions(err.suppressions); processor.addDiagnostics(err.diagnostics); - return processor.getPartialDiagnostics(); + return processor.getDiagnostics(); } return undefined; diff --git a/packages/@romejs/diagnostics/helpers.ts b/packages/@romejs/diagnostics/helpers.ts index f37dfdab54f..376ac242913 100644 --- a/packages/@romejs/diagnostics/helpers.ts +++ b/packages/@romejs/diagnostics/helpers.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnosticAdvice} from './types'; +import {DiagnosticAdvice, DiagnosticLocation} from './types'; import {orderBySimilarity} from '@romejs/string-utils'; import diff from '@romejs/string-diff'; import {Position} from '@romejs/parser-core'; @@ -22,8 +22,8 @@ export function buildSuggestionAdvice( value: string, items: Array, {minRating = 0.5, ignoreCase, formatItem}: BuildSuggestionAdviceOptions = {}, -): PartialDiagnosticAdvice { - const advice: PartialDiagnosticAdvice = []; +): DiagnosticAdvice { + const advice: DiagnosticAdvice = []; const ratings = orderBySimilarity(value, items, { minRating, @@ -99,6 +99,34 @@ export function buildSuggestionAdvice( return advice; } +export function buildDuplicateLocationAdvice( + pointers: Array, +): DiagnosticAdvice { + const locationAdvice: DiagnosticAdvice = pointers.map((location) => { + if (location === undefined) { + return { + type: 'log', + category: 'warn', + message: 'Unable to find location', + }; + } else { + return { + type: 'frame', + location, + }; + } + }); + + return [ + { + type: 'log', + category: 'info', + message: 'Defined already here', + }, + ...locationAdvice, + ]; +} + // Sometimes we'll have big blobs of JS in a diagnostic when we'll only show a snippet. This method pads it out then truncates the rest for efficient transmission. We will have crappy ANSI formatting in the console and elsewhere but for places where we need to truncate we probably don't care (generated code). export function truncateSourceText( code: string, diff --git a/packages/@romejs/diagnostics/index.ts b/packages/@romejs/diagnostics/index.ts index d0dd6070dc5..782f1020cfd 100644 --- a/packages/@romejs/diagnostics/index.ts +++ b/packages/@romejs/diagnostics/index.ts @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -export * from './normalize'; - export * from './errors'; export * from './types'; @@ -21,3 +19,5 @@ export {default as DiagnosticsProcessor} from './DiagnosticsProcessor'; export * from './constants'; export * from './categories'; + +export * from './descriptions'; diff --git a/packages/@romejs/diagnostics/normalize.ts b/packages/@romejs/diagnostics/normalize.ts deleted file mode 100644 index 03508883d6c..00000000000 --- a/packages/@romejs/diagnostics/normalize.ts +++ /dev/null @@ -1,274 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {Position} from '@romejs/parser-core'; -import {MarkupFormatOptions} from '@romejs/string-markup'; -import { - Diagnostic, - DiagnosticAdviceItem, - DiagnosticAdvice, - Diagnostics, - DiagnosticLanguage, - DiagnosticAdviceStackFrame, - DiagnosticDependencies, - PartialDiagnostic, - PartialDiagnosticAdvice, - PartialDiagnosticAdviceItem, - PartialDiagnosticAdviceStackFrame, - PartialDiagnostics, -} from './types'; -import {coerce1, coerce0, number1, number0, number0Neg1} from '@romejs/ob1'; - -function normalizeLanguage( - language: undefined | DiagnosticLanguage, -): DiagnosticLanguage { - if (language === undefined) { - return 'unknown'; - } else { - return language; - } -} - -function normalizePositionAssert(position: undefined | Position): Position { - const normalized = normalizePosition(position); - if (normalized === undefined) { - return { - index: number0Neg1, - line: number1, - column: number0, - }; - } else { - return normalized; - } -} - -export function normalizePosition( - position: undefined | Position, -): undefined | Position { - if (position === undefined) { - return undefined; - } - - const {line, column, index} = position; - - if (typeof line !== 'number' || typeof column !== 'number' || typeof index !== - 'number') { - return undefined; - } - - return { - index: coerce0(Math.max(index, -1)), - line: coerce1(Math.max(line, 1)), - column: coerce0(Math.max(column, 0)), - }; -} - -function normalizeValue(value: undefined | T, def: T): T { - if (value === undefined) { - return def; - } else { - return value; - } -} - -export function normalizeDiagnostics( - diagnostics: PartialDiagnostics, - opts: MarkupFormatOptions, -): Diagnostics { - return diagnostics.map((diag) => normalizeDiagnostic(diag, opts)); -} - -function normalizeFilename( - filename: undefined | string, - opts: MarkupFormatOptions, -): string { - if (filename === undefined) { - return 'unknown'; - } else if (opts.normalizeFilename === undefined) { - return filename; - } else { - return opts.normalizeFilename(filename); - } -} - -export function normalizeDiagnostic( - diagnostic: PartialDiagnostic, - opts: MarkupFormatOptions, -): Diagnostic { - const filename = normalizeFilename(diagnostic.filename, opts); - const mtime = diagnostic.mtime; - const origins = normalizeValue(diagnostic.origins, []); - - const start = normalizePosition(diagnostic.start); - const end = normalizePosition(diagnostic.end); - - const fixable = normalizeValue(diagnostic.fixable, false); - const sourceText = diagnostic.sourceText; - const language = normalizeLanguage(diagnostic.language); - const sourceType = normalizeValue(diagnostic.sourceType, 'unknown'); - const message = normalizeValue(diagnostic.message, 'No message provided'); - const marker = diagnostic.marker; - const dependencies = normalizeDependencies(diagnostic.dependencies, opts); - - const diag: Diagnostic = { - category: diagnostic.category, - label: diagnostic.label, - message, - origins, - marker, - language, - sourceType, - sourceText, - fixable, - dependencies, - advice: [], - filename, - mtime, - start, - end, - }; - - const advice = normalizeDiagnosticAdvice(diag, diagnostic.advice, opts); - - return { - ...diag, - advice, - }; -} - -function normalizeDependencies( - value: PartialDiagnostic['dependencies'], - opts: MarkupFormatOptions, -): DiagnosticDependencies { - if (value === undefined) { - return []; - } else { - const deps: DiagnosticDependencies = []; - - for (const elem of value) { - if (typeof elem === 'object' && elem != null && typeof elem.filename === - 'string' && typeof elem.mtime === 'number') { - deps.push({ - filename: normalizeFilename(elem.filename, opts), - mtime: elem.mtime, - }); - } - } - - return deps; - } -} - -function normalizeAdviceStackFrame( - value: PartialDiagnosticAdviceStackFrame, - opts: MarkupFormatOptions, -): DiagnosticAdviceStackFrame { - return { - prefix: value.prefix, - suffix: value.suffix, - object: value.object, - property: value.property, - filename: normalizeFilename(value.filename, opts), - line: value.line, - column: value.column, - sourceText: value.sourceText, - language: normalizeLanguage(value.language), - }; -} - -function normalizeAdviceStackFrames( - value: Array, - opts: MarkupFormatOptions, -): Array { - if (Array.isArray(value)) { - return value.map((item) => normalizeAdviceStackFrame(item, opts)); - } else { - return []; - } -} - -function normalizeDiagnosticAdvice( - diag: Diagnostic, - value: undefined | PartialDiagnosticAdvice, - opts: MarkupFormatOptions, -): DiagnosticAdvice { - if (Array.isArray(value)) { - return value.map((item) => normalizeDiagnosticAdviceItem(diag, item, opts)); - } else { - return []; - } -} - -export function normalizeDiagnosticAdviceItem( - diag: Diagnostic, - part: PartialDiagnosticAdviceItem, - opts: MarkupFormatOptions, -): DiagnosticAdviceItem { - switch (part.type) { - case 'log': - return { - type: 'log', - category: part.category, - message: normalizeValue(part.message, 'No message provided'), - compact: normalizeValue(part.compact, false), - }; - - case 'list': - return { - type: 'list', - list: part.list, - truncate: normalizeValue(part.truncate, false), - reverse: normalizeValue(part.reverse, false), - ordered: normalizeValue(part.ordered, false), - }; - - case 'code': - return { - type: 'code', - code: normalizeValue(part.code, ''), - language: normalizeLanguage(part.language || diag.language), - sourceType: normalizeValue(part.sourceType || diag.sourceType, 'unknown'), - }; - - case 'frame': - return { - type: 'frame', - sourceType: normalizeValue(part.sourceType || diag.sourceType, 'unknown'), - language: normalizeLanguage(part.language || diag.language), - sourceText: part.sourceText, - marker: part.marker, - filename: normalizeFilename(part.filename, opts), - mtime: part.mtime, - start: normalizePositionAssert(part.start), - end: normalizePositionAssert(part.end), - }; - - case 'diff': - return { - type: 'diff', - diff: part.diff, - legend: part.legend, - }; - - case 'stacktrace': - return { - type: 'stacktrace', - title: part.title, - frames: normalizeAdviceStackFrames(part.frames, opts), - truncate: normalizeValue(part.truncate, false), - }; - - case 'inspect': - return { - type: 'inspect', - // @ts-ignore TODO - - // rome-suppress lint/noExplicitAny - data: (part.data as any), - }; - } -} diff --git a/packages/@romejs/diagnostics/types.ts b/packages/@romejs/diagnostics/types.ts index 5512a8342f8..47f8c71b7bb 100644 --- a/packages/@romejs/diagnostics/types.ts +++ b/packages/@romejs/diagnostics/types.ts @@ -31,14 +31,15 @@ export type DiagnosticSuppressions = Array; export type DiagnosticFilterWithTest = & DiagnosticFilter - & {test?: (diagnostic: PartialDiagnostic) => boolean}; + & {test?: (diagnostic: Diagnostic) => boolean}; -export type DiagnosticPointer = - & SourceLocation +export type DiagnosticLocation = + & Partial & { sourceText?: string; mtime?: number; language?: DiagnosticLanguage; + sourceType?: DiagnosticSourceType; }; export type DiagnosticOrigin = { @@ -46,53 +47,82 @@ export type DiagnosticOrigin = { message?: string; }; -//# FULL export type DiagnosticLogCategory = 'none' | 'info' | 'warn' | 'error'; export type DiagnosticLanguage = 'json' | 'js' | 'url' | 'shell' | 'unknown'; export type DiagnosticSourceType = 'unknown' | ConstSourceType; -export type DiagnosticAdviceItemLog = { +export type Diagnostic = { + description: DiagnosticDescription; + location: DiagnosticLocation; + label?: string; + origins?: Array; + dependencies?: Array<{ + filename: string; + mtime: number; + }>; + marker?: string; +}; + +export type Diagnostics = Array; + +export type DiagnosticDescription = { + fixable?: boolean; + category: DiagnosticCategory; + message: DiagnosticBlessedMessage; + advice?: DiagnosticAdvice; +}; + +// TS doesn't have opaque types so we need to use an intermediate object +export type DiagnosticBlessedMessage = { + type: 'PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE'; + value: string; +}; + +export type DiagnosticAdviceItem = + | DiagnosticAdviceLog + | DiagnosticAdviceList + | DiagnosticAdviceInspect + | DiagnosticAdviceCode + | DiagnosticAdviceFrame + | DiagnosticAdviceDiff + | DiagnosticAdviceStacktrace; + +export type DiagnosticAdviceLog = { type: 'log'; category: DiagnosticLogCategory; message: string; - compact: boolean; + compact?: boolean; }; -export type DiagnosticAdviceItemList = { +export type DiagnosticAdviceList = { type: 'list'; list: Array; - truncate: boolean; - reverse: boolean; - ordered: boolean; + truncate?: boolean; + reverse?: boolean; + ordered?: boolean; +}; + +export type DiagnosticAdviceInspect = { + type: 'inspect'; + data: JSONPropertyValue; }; -export type DiagnosticAdviceItemCode = { +export type DiagnosticAdviceCode = { type: 'code'; code: string; - language: DiagnosticLanguage; - sourceType: DiagnosticSourceType; + sourceType?: ConstSourceType; + language?: DiagnosticLanguage; }; -export type DiagnosticAdviceItemFrame = { +export type DiagnosticAdviceFrame = { type: 'frame'; - language: DiagnosticLanguage; - sourceType: DiagnosticSourceType; - sourceText: undefined | string; - marker: undefined | string; - filename: string; - mtime: undefined | number; - start: Position; - end: Position; -}; - -export type DiagnosticAdviceItemInspect = { - type: 'inspect'; - data: JSONPropertyValue; + location: DiagnosticLocation; + marker?: string; }; -export type DiagnosticAdviceItemDiff = { +export type DiagnosticAdviceDiff = { type: 'diff'; diff: Diffs; legend?: { @@ -101,143 +131,16 @@ export type DiagnosticAdviceItemDiff = { }; }; -export type DiagnosticAdviceItemStacktrace = { +export type DiagnosticAdviceStacktrace = { type: 'stacktrace'; - title: undefined | string; + title?: string; + truncate?: boolean; frames: Array; - truncate: boolean; }; -export type DiagnosticAdviceItem = - | DiagnosticAdviceItemLog - | DiagnosticAdviceItemList - | DiagnosticAdviceItemCode - | DiagnosticAdviceItemFrame - | DiagnosticAdviceItemInspect - | DiagnosticAdviceItemDiff - | DiagnosticAdviceItemStacktrace; - export type DiagnosticAdvice = Array; -export type DiagnosticDependency = { - filename: string; - mtime: number; -}; - -export type DiagnosticDependencies = Array; - -export type Diagnostic = { - category: DiagnosticCategory; - message: string; - label: undefined | string; - filename: undefined | string; - origins: Array; - mtime: undefined | number; - dependencies: DiagnosticDependencies; - sourceType: DiagnosticSourceType; - language: DiagnosticLanguage; - sourceText: undefined | string; - start: undefined | Position; - end: undefined | Position; - marker: undefined | string; - fixable: boolean; - advice: DiagnosticAdvice; -}; - -export type Diagnostics = Array; - export type DiagnosticAdviceStackFrame = { - suffix: undefined | string; - prefix: undefined | string; - object: undefined | string; - property: undefined | string; - filename: undefined | string; - line: undefined | Number1; - column: undefined | Number0; - language: DiagnosticLanguage; - sourceText: undefined | string; -}; - -//# PARTIAL -export type PartialDiagnostic = { - category: DiagnosticCategory; - label?: string; - message: string; - origins?: Array; - dependencies?: Array<{ - filename: string; - mtime: string; - }>; - filename?: string; - mtime?: number; - sourceType?: DiagnosticSourceType; - language?: DiagnosticLanguage; - fixable?: boolean; - sourceText?: string; - marker?: string; - start?: Position; - end?: Position; - advice?: PartialDiagnosticAdvice; -}; - -export type PartialDiagnostics = Array; - -export type PartialDiagnosticAdviceItem = - | { - type: 'log'; - category: DiagnosticLogCategory; - message: string; - compact?: boolean; - } - | { - type: 'list'; - list: Array; - truncate?: boolean; - reverse?: boolean; - ordered?: boolean; - } - | { - type: 'inspect'; - data: JSONPropertyValue; - } - | { - type: 'code'; - code: string; - sourceType?: ConstSourceType; - language?: DiagnosticLanguage; - } - | { - type: 'frame'; - mtime?: number; - language?: DiagnosticLanguage; - sourceType?: ConstSourceType; - sourceText?: string; - marker?: string; - filename?: string; - start: Position; - end: Position; - - // From SourceLocation, will never appear in the final diagnostic, makes it easy to spread - identifierName?: string; - } - | { - type: 'diff'; - diff: Diffs; - legend?: { - add: string; - delete: string; - }; - } - | { - type: 'stacktrace'; - title?: string; - truncate?: boolean; - frames: Array; - }; - -export type PartialDiagnosticAdvice = Array; - -export type PartialDiagnosticAdviceStackFrame = { prefix?: string; suffix?: string; object?: string; diff --git a/packages/@romejs/diagnostics/wrap.ts b/packages/@romejs/diagnostics/wrap.ts index 777190fcdde..3ff27f567a9 100644 --- a/packages/@romejs/diagnostics/wrap.ts +++ b/packages/@romejs/diagnostics/wrap.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics, DiagnosticOrigin} from './types'; +import {Diagnostics, DiagnosticOrigin} from './types'; import {addOriginsToDiagnostics} from './derive'; import {getDiagnosticsFromError} from './errors'; @@ -16,7 +16,7 @@ type WrapResult = } | { readonly value: undefined; - readonly diagnostics: PartialDiagnostics; + readonly diagnostics: Diagnostics; }; export async function catchDiagnostics( diff --git a/packages/@romejs/js-analysis/api/check.ts b/packages/@romejs/js-analysis/api/check.ts index 02e21ed893e..fdaf992a726 100644 --- a/packages/@romejs/js-analysis/api/check.ts +++ b/packages/@romejs/js-analysis/api/check.ts @@ -6,7 +6,7 @@ */ import {CheckProvider} from '../types'; -import {PartialDiagnostics, PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticAdvice, descriptions} from '@romejs/diagnostics'; import {Program} from '@romejs/js-ast'; import Hub from '../Hub'; import E from '../types/errors/E'; @@ -21,7 +21,7 @@ export default async function check( project: TransformProjectDefinition; provider: CheckProvider; }, -): Promise { +): Promise { const hub = await buildGraph({ ast: opts.ast, connected: true, @@ -36,7 +36,7 @@ function isError(t: undefined | T): boolean { return t !== undefined && t instanceof E; } -function resolveGraph(hub: Hub): PartialDiagnostics { +function resolveGraph(hub: Hub): Diagnostics { const {graph, utils, context} = hub; // we track caught errors here as if a normal type returns a error in it's reduce() method @@ -61,20 +61,14 @@ function resolveGraph(hub: Hub): PartialDiagnostics { caughtErrors.add(reduced); } - const { - category, - lowerTarget, - upperTarget, - advice: rawAdvice, - message, - } = reduced.getError(); + let {description, lowerTarget, upperTarget} = reduced.getError(); // ignore errors inside if (isError(lowerTarget) || isError(upperTarget)) { continue; } - let advice: PartialDiagnosticAdvice = []; + let advice: DiagnosticAdvice = []; if (upperTarget !== undefined) { const marker = upperTarget && !(upperTarget instanceof @@ -90,22 +84,23 @@ function resolveGraph(hub: Hub): PartialDiagnostics { } else if (originLoc !== undefined) { advice.push({ type: 'frame', - filename: originLoc.filename, - start: originLoc.start, - end: originLoc.end, + location: { + filename: originLoc.filename, + start: originLoc.start, + end: originLoc.end, + }, marker, }); } } - if (rawAdvice !== undefined) { - advice = advice.concat(rawAdvice); - } + description = { + ...description, + advice: [...advice, ...(description.advice || [])], + }; context.addNodeDiagnostic(lowerTarget.originNode, { - category, - message, - advice, + description, marker: lowerTarget && !(lowerTarget instanceof reduced.constructor) ? utils.humanize(lowerTarget) : undefined, }); @@ -127,36 +122,11 @@ function resolveGraph(hub: Hub): PartialDiagnostics { continue; } - const advice: PartialDiagnosticAdvice = [ - { - type: 'log', - category: 'error', - message: `This type is incompatible with expected type of`, - }, - ]; - - const {originLoc} = upper; - if (originLoc === undefined) { - advice.push({ - type: 'log', - category: 'info', - message: utils.humanize(upper), - }); - } else { - advice.push({ - type: 'frame', - filename: originLoc.filename, - start: originLoc.start, - end: originLoc.end, - marker: utils.humanize(upper), - }); - } - context.addNodeDiagnostic(compatibility.lower.originNode, { - category: 'typeCheck/incompatible', - message: 'Type incompatibility found', + description: descriptions.TYPE_CHECK.INCOMPATIBILITY(utils.humanize( + upper, + ), upper.originLoc), marker: utils.humanize(compatibility.lower), - advice, }); } } diff --git a/packages/@romejs/js-analysis/tests/basic.test.ts b/packages/@romejs/js-analysis/tests/basic.test.ts index 0f1738dc4f6..42cdc156e87 100644 --- a/packages/@romejs/js-analysis/tests/basic.test.ts +++ b/packages/@romejs/js-analysis/tests/basic.test.ts @@ -5,14 +5,14 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {DEFAULT_PROJECT_CONFIG} from '@romejs/project'; import test from '@romejs/test'; import {check} from '@romejs/js-analysis'; import {parseJS} from '@romejs/js-parser'; import {createUnknownFilePath} from '@romejs/path'; -async function testCheck(code: string): Promise { +async function testCheck(code: string): Promise { const ast = parseJS({ input: code, sourceType: 'module', diff --git a/packages/@romejs/js-analysis/types/ExhaustiveT.ts b/packages/@romejs/js-analysis/types/ExhaustiveT.ts index 3e0ea32a370..6cdd6c383eb 100644 --- a/packages/@romejs/js-analysis/types/ExhaustiveT.ts +++ b/packages/@romejs/js-analysis/types/ExhaustiveT.ts @@ -13,6 +13,7 @@ import {HumanBuilder} from '../Utils'; import E, {ErrorDefinition} from './errors/E'; import AnyT from './AnyT'; import T from './T'; +import {descriptions} from '@romejs/diagnostics'; class ENotExhaustive extends E { constructor( @@ -35,14 +36,10 @@ class ENotExhaustive extends E { static type = 'ENotExhaustive'; getError(): ErrorDefinition { - let message = - `Expected only a ${this.utils.humanize(this.only)} but got ${this.utils.humanize( - this.target, - )}`; - //message += `but allows ${this.extraenous.map(type => this.utils.humanize(type)).join(' | ')}`; return { - category: 'typeCheck/notExhaustive', - message, + description: descriptions.TYPE_CHECK.NOT_EXHAUSTIVE(this.utils.humanize( + this.only, + ), this.utils.humanize(this.target)), lowerTarget: this.target, }; } diff --git a/packages/@romejs/js-analysis/types/errors/E.ts b/packages/@romejs/js-analysis/types/errors/E.ts index a927d5c6dfa..ca90434156a 100644 --- a/packages/@romejs/js-analysis/types/errors/E.ts +++ b/packages/@romejs/js-analysis/types/errors/E.ts @@ -6,18 +6,13 @@ */ import {Scope} from '../../scopes'; -import { - PartialDiagnosticAdviceItem, - DiagnosticCategory, -} from '@romejs/diagnostics'; +import {DiagnosticDescription} from '@romejs/diagnostics'; import {AnyNode} from '@romejs/js-ast'; import AnyT from '../AnyT'; import T from '../T'; export type ErrorDefinition = { - category: DiagnosticCategory; - advice?: Array; - message: string; + description: DiagnosticDescription; lowerTarget: T; upperTarget?: T; }; @@ -30,7 +25,7 @@ export default class E extends T { } humanize(): string { - return this.getError().message; + return this.getError().description.message.value; } getError(): ErrorDefinition { diff --git a/packages/@romejs/js-analysis/types/errors/MissingUnionE.ts b/packages/@romejs/js-analysis/types/errors/MissingUnionE.ts index d3ac71d78f3..32fe7b54bdc 100644 --- a/packages/@romejs/js-analysis/types/errors/MissingUnionE.ts +++ b/packages/@romejs/js-analysis/types/errors/MissingUnionE.ts @@ -9,6 +9,7 @@ import {Scope} from '../../scopes'; import E, {ErrorDefinition} from './E'; import T from '../T'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default class MissingUnionE extends E { constructor( @@ -31,10 +32,9 @@ export default class MissingUnionE extends E { getError(): ErrorDefinition { return { - category: 'typeCheck/missingCondition', - message: `Missing the conditions ${this.missing.map((type) => - this.utils.humanize(type) - ).join(', ')}`, + description: descriptions.TYPE_CHECK.MISSING_CONDITION(this.missing.map(( + type, + ) => this.utils.humanize(type))), lowerTarget: this.target, }; } diff --git a/packages/@romejs/js-analysis/types/errors/NotCallableE.ts b/packages/@romejs/js-analysis/types/errors/NotCallableE.ts index 4cc4885e8e5..01742c1f3fd 100644 --- a/packages/@romejs/js-analysis/types/errors/NotCallableE.ts +++ b/packages/@romejs/js-analysis/types/errors/NotCallableE.ts @@ -9,6 +9,7 @@ import {AnyNode} from '@romejs/js-ast'; import {Scope} from '../../scopes'; import E, {ErrorDefinition} from './E'; import T from '../T'; +import {descriptions} from '@romejs/diagnostics'; export default class NotCallableE extends E { constructor(scope: Scope, originNode: undefined | AnyNode, callee: T) { @@ -21,8 +22,7 @@ export default class NotCallableE extends E { getError(): ErrorDefinition { return { - category: 'typeCheck/uncallable', - message: `This type isn't callable`, + description: descriptions.TYPE_CHECK.NOT_CALLABLE, lowerTarget: this.callee, }; } diff --git a/packages/@romejs/js-analysis/types/errors/UndeclaredVarE.ts b/packages/@romejs/js-analysis/types/errors/UndeclaredVarE.ts index 2519bd1d582..083dfd4b614 100644 --- a/packages/@romejs/js-analysis/types/errors/UndeclaredVarE.ts +++ b/packages/@romejs/js-analysis/types/errors/UndeclaredVarE.ts @@ -6,7 +6,7 @@ */ import {AnyNode} from '@romejs/js-ast'; -import {buildSuggestionAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {Scope} from '../../scopes'; import E, {ErrorDefinition} from './E'; @@ -22,9 +22,10 @@ export default class UndeclaredVarE extends E { getError(): ErrorDefinition { const possibleNames = this.scope.getBindingNames(); return { - category: 'typeCheck/undeclaredVariable', - message: `Undeclared variable '${this.name}'`, - advice: buildSuggestionAdvice(this.name, possibleNames), + description: descriptions.TYPE_CHECK.UNDECLARED_VARIABLE( + this.name, + possibleNames, + ), lowerTarget: this, }; } diff --git a/packages/@romejs/js-analysis/types/errors/UnknownImportE.ts b/packages/@romejs/js-analysis/types/errors/UnknownImportE.ts index 50c0484122e..1c4f186b29c 100644 --- a/packages/@romejs/js-analysis/types/errors/UnknownImportE.ts +++ b/packages/@romejs/js-analysis/types/errors/UnknownImportE.ts @@ -5,9 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {Scope} from '../../scopes'; -import {findClosestStringMatch} from '@romejs/string-utils'; import E, {ErrorDefinition} from './E'; import {AnyNode} from '@romejs/js-ast'; @@ -33,41 +32,12 @@ export default class UnknownImportE extends E { possibleNames: Array; getError(): ErrorDefinition { - const {possibleNames} = this; - const suggestion = findClosestStringMatch(this.importedName, possibleNames); - - let infoMessage = undefined; - let infoList = undefined; - - if (possibleNames.length === 0) { - infoMessage = 'This file contains no exports.'; - } else { - if (suggestion === undefined) { - infoList = this.possibleNames; - infoMessage = 'Did you mean one of these?'; - } else { - infoMessage = `Did you mean ${suggestion}?`; - } - } - - const advice: PartialDiagnosticAdvice = [ - { - type: 'log', - category: 'info', - message: infoMessage, - }, - ]; - if (infoList !== undefined) { - advice.push({ - type: 'list', - list: infoList, - }); - } - return { - category: 'typeCheck/unknownImport', - message: `Unknown import '${this.importedName}' in '${this.source}'`, - advice, + description: descriptions.TYPE_CHECK.UNKNOWN_IMPORT( + this.importedName, + this.source, + this.possibleNames, + ), lowerTarget: this, }; } diff --git a/packages/@romejs/js-analysis/types/errors/UnknownPropE.ts b/packages/@romejs/js-analysis/types/errors/UnknownPropE.ts index 34836535b0c..86094169ead 100644 --- a/packages/@romejs/js-analysis/types/errors/UnknownPropE.ts +++ b/packages/@romejs/js-analysis/types/errors/UnknownPropE.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {buildSuggestionAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {Scope} from '../../scopes'; import T from '../T'; import {orderBySimilarity} from '@romejs/string-utils'; @@ -52,12 +52,8 @@ export default class UnknownPropE extends E { } getError(): ErrorDefinition { - let message: string = `Property '${this.key}' not found in`; - return { - category: 'typeCheck/unknownProperty', - message, - advice: buildSuggestionAdvice(this.key, this.allProps), + description: descriptions.TYPE_CHECK.UNKNOWN_PROP(this.key, this.allProps), lowerTarget: this.property, upperTarget: this.object, }; diff --git a/packages/@romejs/js-ast/core/Program.ts b/packages/@romejs/js-ast/core/Program.ts index 946da5c1afa..f4748ddcfdc 100644 --- a/packages/@romejs/js-ast/core/Program.ts +++ b/packages/@romejs/js-ast/core/Program.ts @@ -14,7 +14,7 @@ import { AnyComment, ConstProgramSyntax, } from '../index'; -import {PartialDiagnostics} from '@romejs/diagnostics'; +import {Diagnostics} from '@romejs/diagnostics'; import {createBuilder} from '../utils'; export type Program = @@ -28,7 +28,7 @@ export type Program = mtime: undefined | number; corrupt: boolean; sourceType: ConstSourceType; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; comments: Array; syntax: Array; hasHoistedVars: boolean; diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts index 150bf981508..acdd4bd21d1 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts +++ b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts @@ -29,6 +29,7 @@ import { AnalyzeDependencyImportFirstUsage, AnalyzeModuleType, } from '@romejs/core'; +import {descriptions} from '@romejs/diagnostics'; const analyzeCache: Cache = new Cache(); @@ -231,8 +232,7 @@ export default async function analyzeDependencies( } else if (record instanceof CJSExportRecord) { if (moduleType === 'es') { context.addNodeDiagnostic(record.node, { - category: 'analyzeDependencies/cjsExportInES', - message: 'You cannot use CommonJS exports in an ES module', + description: descriptions.ANALYZE_DEPENDENCIES.CJS_EXPORT_IN_ES, }); } } diff --git a/packages/@romejs/js-compiler/api/compile.ts b/packages/@romejs/js-compiler/api/compile.ts index 63ff330e64b..d483820f67b 100644 --- a/packages/@romejs/js-compiler/api/compile.ts +++ b/packages/@romejs/js-compiler/api/compile.ts @@ -6,7 +6,7 @@ */ import {Mappings} from '@romejs/codec-source-map'; -import {PartialDiagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; import {CompileRequest} from '../types'; import {Cache} from '@romejs/js-compiler'; import {generateJS} from '@romejs/js-generator'; @@ -14,7 +14,7 @@ import transform from '../methods/transform'; export type CompileResult = { mappings: Mappings; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; suppressions: DiagnosticSuppressions; cacheDependencies: Array; compiledCode: string; diff --git a/packages/@romejs/js-compiler/api/lint.ts b/packages/@romejs/js-compiler/api/lint.ts index df46c5da60c..55aae5ed24c 100644 --- a/packages/@romejs/js-compiler/api/lint.ts +++ b/packages/@romejs/js-compiler/api/lint.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; import {TransformRequest} from '../types'; import {lintTransforms} from '../transforms/lint/index'; import {program} from '@romejs/js-ast'; @@ -14,7 +14,7 @@ import {generateJS} from '@romejs/js-generator'; import {extractSuppressionsFromProgram} from '../suppressions'; export type LintResult = { - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; suppressions: DiagnosticSuppressions; src: string; }; diff --git a/packages/@romejs/js-compiler/lib/Context.ts b/packages/@romejs/js-compiler/lib/Context.ts index 846f87f4260..086045b4dba 100644 --- a/packages/@romejs/js-compiler/lib/Context.ts +++ b/packages/@romejs/js-compiler/lib/Context.ts @@ -18,9 +18,10 @@ import { CompilerOptions, } from '@romejs/js-compiler'; import { - PartialDiagnostic, - PartialDiagnostics, + Diagnostic, + Diagnostics, DiagnosticOrigin, + DiagnosticLocation, } from '@romejs/diagnostics'; import Record from './Record'; import {RootScope} from '../scope/Scope'; @@ -36,7 +37,9 @@ export type ContextArg = { }; // We only want a Context to create diagnostics that belong to itself -type ContextPartialDiagnostic = Omit; +type ContextDiagnostic = + & Omit + & {location?: Omit}; export default class Context { constructor(arg: ContextArg) { @@ -60,7 +63,7 @@ export default class Context { sourceType: ConstSourceType; cacheDependencies: Set; records: Array; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; rootScope: undefined | RootScope; @@ -110,14 +113,11 @@ export default class Context { this.records.push(record); } - addDiagnostics(diagnostics: PartialDiagnostics) { + addDiagnostics(diagnostics: Diagnostics) { this.diagnostics = [...this.diagnostics, ...diagnostics]; } - addLocDiagnostic( - loc: undefined | SourceLocation, - diag: ContextPartialDiagnostic, - ) { + addLocDiagnostic(loc: undefined | SourceLocation, diag: ContextDiagnostic) { let origins: Array = []; if (this.origin !== undefined) { origins.push(this.origin); @@ -132,28 +132,34 @@ export default class Context { ); } + const location: DiagnosticLocation = diag.location === undefined + ? {} : diag.location; + this.diagnostics.push({ ...diag, - mtime: this.mtime, - filename: this.filename, - start: loc === undefined ? diag.start : loc.start, - end: loc === undefined ? diag.end : loc.end, - language: 'js', - sourceType: this.sourceType, + location: { + ...location, + mtime: this.mtime, + filename: this.filename, + start: loc === undefined ? location.start : loc.start, + end: loc === undefined ? location.end : loc.end, + language: 'js', + sourceType: this.sourceType, + }, origins, }); } addNodeDiagnostic( node: undefined | {loc?: SourceLocation}, - diag: ContextPartialDiagnostic, + diag: ContextDiagnostic, ) { return this.addLocDiagnostic(node === undefined ? undefined : node.loc, diag); } addNodesRangeDiagnostic( nodes: Array<{loc?: SourceLocation}>, - diag: ContextPartialDiagnostic, + diag: ContextDiagnostic, ) { return this.addLocDiagnostic( extractSourceLocationRangeFromNodes(nodes), diff --git a/packages/@romejs/js-compiler/lib/Path.ts b/packages/@romejs/js-compiler/lib/Path.ts index 729b5dc4d7f..9d8601a91a4 100644 --- a/packages/@romejs/js-compiler/lib/Path.ts +++ b/packages/@romejs/js-compiler/lib/Path.ts @@ -13,7 +13,7 @@ import { AnyHookDescriptor, HookDescriptor, } from '../api/createHook'; -import {PartialDiagnostic} from '@romejs/diagnostics'; +import {Diagnostic} from '@romejs/diagnostics'; import reduce from '../methods/reduce'; import {TransformExitResult} from '../types'; @@ -257,7 +257,7 @@ export default class Path { ); } - addDiagnostic(opts: PartialDiagnostic) { + addDiagnostic(opts: Diagnostic) { return this.context.addNodeDiagnostic(this.node, opts); } } diff --git a/packages/@romejs/js-compiler/methods/transform.ts b/packages/@romejs/js-compiler/methods/transform.ts index 08a596fe961..26ccdfb3377 100644 --- a/packages/@romejs/js-compiler/methods/transform.ts +++ b/packages/@romejs/js-compiler/methods/transform.ts @@ -6,7 +6,7 @@ */ import {Program} from '@romejs/js-ast'; -import {PartialDiagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; +import {Diagnostics, DiagnosticSuppressions} from '@romejs/diagnostics'; import {TransformRequest, TransformVisitors} from '../types'; import {program} from '@romejs/js-ast'; import {stageTransforms, stageOrder, hookVisitors} from '../transforms/index'; @@ -17,7 +17,7 @@ import {extractSuppressionsFromProgram} from '../suppressions'; type TransformResult = { ast: Program; suppressions: DiagnosticSuppressions; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; cacheDependencies: Array; }; @@ -44,7 +44,7 @@ export default async function transform( return cached; } - let prevStageDiagnostics: PartialDiagnostics = []; + let prevStageDiagnostics: Diagnostics = []; let prevStageCacheDeps: Array = []; // Run the previous stage diff --git a/packages/@romejs/js-compiler/suppressions.ts b/packages/@romejs/js-compiler/suppressions.ts index be7a6101a5a..104681d8afd 100644 --- a/packages/@romejs/js-compiler/suppressions.ts +++ b/packages/@romejs/js-compiler/suppressions.ts @@ -6,15 +6,18 @@ */ import {Program, AnyComment} from '@romejs/js-ast'; -import {DiagnosticSuppressions, PartialDiagnostics} from '@romejs/diagnostics'; -import {markup} from '@romejs/string-markup'; +import { + DiagnosticSuppressions, + Diagnostics, + descriptions, +} from '@romejs/diagnostics'; const SUPPRESSION_START = 'rome-suppress'; const PREFIX_MISTAKES = ['@rome-suppress', 'rome-ignore', '@rome-ignore']; type ExtractedSuppressions = { suppressions: DiagnosticSuppressions; - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; }; function extractSuppressionsFromComment( @@ -26,7 +29,7 @@ function extractSuppressionsFromComment( } const suppressedCategories: Set = new Set(); - const diagnostics: PartialDiagnostics = []; + const diagnostics: Diagnostics = []; const suppressions: DiagnosticSuppressions = []; const lines = comment.value.split('\n'); @@ -40,16 +43,11 @@ function extractSuppressionsFromComment( for (const prefix of PREFIX_MISTAKES) { if (line.startsWith(prefix)) { diagnostics.push({ - category: 'suppressions/incorrectPrefix', - message: `Invalid suppression prefix ${prefix}`, - advice: [ - { - type: 'log', - category: 'info', - message: `Did you mean ${SUPPRESSION_START}?`, - }, - ], - ...loc, + description: descriptions.SUPPRESSIONS.PREFIX_TYPO( + prefix, + SUPPRESSION_START, + ), + location: loc, }); } } @@ -73,9 +71,8 @@ function extractSuppressionsFromComment( if (suppressedCategories.has(category)) { diagnostics.push({ - category: 'suppressions/duplicate', - message: markup`Duplicate suppression category ${category}`, - ...loc, + description: descriptions.SUPPRESSIONS.DUPLICATE(category), + location: loc, }); } else { suppressedCategories.add(category); @@ -102,7 +99,7 @@ function extractSuppressionsFromComment( export function extractSuppressionsFromComments( comments: Array, ): ExtractedSuppressions { - let diagnostics: PartialDiagnostics = []; + let diagnostics: Diagnostics = []; let suppressions: DiagnosticSuppressions = []; for (const comment of comments) { diff --git a/packages/@romejs/js-compiler/transforms/compile/jsx.ts b/packages/@romejs/js-compiler/transforms/compile/jsx.ts index 8eb5c5f14a4..58ad7b6cb92 100644 --- a/packages/@romejs/js-compiler/transforms/compile/jsx.ts +++ b/packages/@romejs/js-compiler/transforms/compile/jsx.ts @@ -42,6 +42,7 @@ import { } from '@romejs/js-ast'; import {Path} from '@romejs/js-compiler'; import {template, isValidIdentifierName, inheritLoc} from '@romejs/js-ast-utils'; +import {descriptions} from '@romejs/diagnostics'; function convertJSXIdentifier( path: Path, @@ -271,8 +272,7 @@ export default { if (jsxNamespacedName.is(node.name)) { // TODO better handle this context.addNodeDiagnostic(type, { - category: 'compile/jsx', - message: 'JSX is not XML', + description: descriptions.COMPILER.JSX_NOT_XML, }); } diff --git a/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts b/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts index 3a3d3f3c1db..a9f339d5232 100644 --- a/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts +++ b/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts @@ -33,6 +33,7 @@ import { } from '@romejs/js-ast'; import {template} from '@romejs/js-ast-utils'; import {TransformExitResult} from '@romejs/js-compiler'; +import {descriptions} from '@romejs/diagnostics'; function transformClass( node: ClassDeclaration | ClassExpression, @@ -211,8 +212,7 @@ function transformClass( for (const bodyNode of newNode.meta.body) { if (bodyNode.type !== 'ClassMethod') { context.addNodeDiagnostic(bodyNode, { - category: 'compile/classes', - message: 'The classes transform doesn\'t know how to transform this', + description: descriptions.COMPILER.CLASSES_UNSUPPORTED, }); continue; } diff --git a/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts b/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts index 07d04c752e8..40908ec7c36 100644 --- a/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts +++ b/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts @@ -16,6 +16,7 @@ import {toCamelCase} from '@romejs/string-utils'; import {UnknownFilePath} from '@romejs/path'; import {renameBindings} from '@romejs/js-ast-utils'; import {TransformExitResult} from '@romejs/js-compiler/types'; +import {descriptions} from '@romejs/diagnostics'; function isValidDeclaration( node: AnyNode, @@ -63,29 +64,13 @@ export default { if (basename !== id.name) { const correctFilename = id.name + context.path.getExtensions(); - let adviceMessage = ''; - - if (id.name === '*default*') { - adviceMessage += 'The'; - } else { - adviceMessage += - `Filename should be ${correctFilename} or the`; - } - - adviceMessage += - ` ${type} name should be ${basename}`; - context.addNodeDiagnostic(id, { - fixable: true, - category: 'lint/defaultExportSameBasename', - message: `Filename and the name of a default ${type} should match`, - advice: [ - { - type: 'log', - category: 'info', - message: adviceMessage, - }, - ], + description: descriptions.LINT.DEFAULT_EXPORT_SAME_BASENAME({ + defaultName: id.name, + defaultType: type, + actualFilename: basename, + correctFilename, + }), }); return renameBindings(path, new Map([[id.name, basename]])); diff --git a/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts b/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts index fb485053ab3..8e0e64c474f 100644 --- a/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts +++ b/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts @@ -8,6 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {TransformExitResult} from '@romejs/js-compiler/types'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; function isEmpty(node: AnyNode): boolean { if (node.innerComments !== undefined && node.innerComments.length > 0) { @@ -33,8 +34,7 @@ export default { if (node.type === 'IfStatement') { if (isEmpty(node.consequent)) { context.addNodeDiagnostic(node.consequent, { - category: 'lint/emptyBlocks', - message: 'Empty block', + description: descriptions.LINT.EMPTY_BLOCKS, }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts b/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts index cffd8aba3d3..95c33e13c3b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts +++ b/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts @@ -8,6 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; import {getCompletionRecords} from '@romejs/js-ast-utils'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'getterReturn', @@ -19,8 +20,7 @@ export default { for (const record of getCompletionRecords(node.body)) { if (record.type === 'INVALID') { path.context.addNodeDiagnostic(record.node, { - category: 'lint/getterReturn', - message: `Expected a 'return' at end of a getter method but got ${record.description}`, + description: descriptions.LINT.GETTER_RETURN(record.description), }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts index 5f88044602e..39c8f52f0c3 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {TransformExitResult} from '@romejs/js-compiler/types'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noAsyncPromiseExecutor', @@ -19,8 +20,7 @@ export default { 'ArrowFunctionExpression' || node.arguments[0].type === 'FunctionExpression') && node.arguments[0].head.async) { context.addNodeDiagnostic(node.arguments[0], { - category: 'lint/noAsyncPromiseExecutor', - message: 'Promise executor functions should not be async.', + description: descriptions.LINT.NO_ASYNC_PROMISE_EXECUTOR, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts index d65ea0f46fb..e8a30e316c7 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts @@ -7,6 +7,7 @@ import {AnyNode} from '@romejs/js-ast'; import {Path} from '@romejs/js-compiler'; import {template} from '@romejs/js-ast-utils'; +import {descriptions} from '@romejs/diagnostics'; const OPERATORS_TO_CHECK = ['>', '>=', '<', '<=', '==', '===', '!=', '!==']; @@ -24,11 +25,11 @@ export default { node.operator, ) && (isNegZero(node.left) || isNegZero(node.right))) { path.context.addNodeDiagnostic(node, { - category: 'lint/noCompareNegZero', - message: `Do not use the '${node.operator}' operator to compare against -0`, - fixable: true, + description: descriptions.LINT.NO_COMPARE_NEG_ZERO(node.operator), }); - return template.expression`Object.is(${node.left}, ${node.right})`; + if (node.operator === '===') { + return template.expression`Object.is(${node.left}, ${node.right})`; + } } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts index a2de21acfe0..c0ffe487617 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noCondAssign', @@ -17,8 +18,7 @@ export default { node.type === 'WhileStatement' || node.type === 'DoWhileStatement') && node.test && node.test.type === 'AssignmentExpression') { path.context.addNodeDiagnostic(node, { - category: 'lint/noCondAssign', - message: 'Cannot assign variable in loop condition', + description: descriptions.LINT.NO_COND_ASSIGN, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts index 6a30c60a8cf..07e8efa3797 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDanglingBackslash', @@ -19,8 +20,7 @@ export default { const last = body[body.length - 1]; if (last && last.type === 'RegExpCharacter' && !last.value) { context.addNodeDiagnostic(last, { - category: 'lint/noDanglingBackslash', - message: 'Dangling backslash in a regular expression', + description: descriptions.LINT.NO_DANGLING_BACKSLASH_IN_REGEX, }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts b/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts index 670339dff66..21ccb35551f 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts @@ -7,6 +7,7 @@ import {Path, TransformExitResult} from '@romejs/js-compiler'; import {REDUCE_REMOVE} from '@romejs/js-compiler'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDebugger', @@ -15,9 +16,7 @@ export default { if (node.type === 'DebuggerStatement') { path.context.addNodeDiagnostic(node, { - fixable: true, - category: 'lint/noDebugger', - message: 'Unexpected \'debugger\' statement', + description: descriptions.LINT.NO_DEBUGGER, }); return REDUCE_REMOVE; diff --git a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts index 4f843503ffa..53c80f1db6d 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDeleteVars', @@ -16,8 +17,7 @@ export default { if (node.type === 'UnaryExpression' && node.operator === 'delete' && node.argument.type === 'ReferenceIdentifier') { path.context.addNodeDiagnostic(node, { - category: 'lint/noDeleteVars', - message: 'Variables should not be deleted.', + description: descriptions.LINT.NO_DELETE_VARS, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.test.ts b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.test.ts index 2e242048e5a..b9c0b750f22 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.test.ts @@ -17,6 +17,6 @@ test('no duplicated args allowed', async (t) => { `); t.truthy(duplicatedArgs.diagnostics.find((d) => - d.category === 'lint/noDupeArgs' + d.description.category === 'lint/noDupeArgs' )); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts index a476f19c332..fc7aef0d102 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts @@ -8,6 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; import {getBindingIdentifiers} from '@romejs/js-ast-utils'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDupeArgs', @@ -21,8 +22,7 @@ export default { for (const {name} of getBindingIdentifiers(param)) { if (uniqueIdentifiers.has(name)) { context.addNodeDiagnostic(param, { - category: 'lint/noDupeArgs', - message: `Duplicate argument ${name} in function definition`, + description: descriptions.LINT.NO_DUPE_ARGS(name), }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.test.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.test.ts index 80ab9a24a63..124f5e8de05 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.test.ts @@ -28,6 +28,6 @@ test('no duplicated switch cases allowed', async (t) => { `); t.truthy(duplicatedSwitchCase.diagnostics.find((d) => - d.category === 'lint/noDuplicateCase' + d.description.category === 'lint/noDuplicateCase' )); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts index 370771122f8..b18010574a0 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDuplicateCase', @@ -22,8 +23,7 @@ export default { if (uniqueSwitchCases.has(test.value)) { context.addNodeDiagnostic(param, { - category: 'lint/noDuplicateCase', - message: `Duplicate case ${test.value} not allowed.`, + description: descriptions.LINT.NO_DUPLICATE_CASE(test.value), }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts index eca20134985..b510502ff20 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts @@ -7,7 +7,7 @@ import {AnyNode, RegExpGroupCapture} from '@romejs/js-ast'; import {Path} from '@romejs/js-compiler'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noDuplicateGroupNamesInRegularExpressions', @@ -40,34 +40,11 @@ export default { const firstUsage = usages[0]; - const duplicateAdvice: PartialDiagnosticAdvice = usages.slice(1).map(( - node, - ) => { - if (node.loc === undefined) { - return { - type: 'log', - category: 'warn', - message: 'Unable to find location', - }; - } else { - return { - type: 'frame', - ...node.loc, - }; - } - }); - context.addNodeDiagnostic(firstUsage, { - category: 'lint/noDuplicateGroupNamesInRegularExpressions', - message: `Duplicate group name ${name} in regular expression`, - advice: [ - { - type: 'log', - category: 'info', - message: 'Defined again here', - }, - ...duplicateAdvice, - ], + description: descriptions.LINT.DUPLICATE_REGEX_GROUP_NAME( + name, + usages.slice(1).map((node) => node.loc), + ), }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts index 9b023e5e059..ac5ac35201e 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts @@ -8,7 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {ObjectProperty, ObjectMethod, SpreadProperty} from '@romejs/js-ast'; import {TransformExitResult} from '@romejs/js-compiler/types'; -import {markup} from '@romejs/string-markup'; +import {descriptions} from '@romejs/diagnostics'; function extractPropertyKey( node: ObjectProperty | ObjectMethod | SpreadProperty, @@ -45,8 +45,7 @@ export default { if (key !== undefined) { if (previousKeys.has(key)) { path.context.addNodeDiagnostic(prop, { - category: 'lint/noDuplicateKeys', - message: markup`Duplicate key ${key}`, + description: descriptions.LINT.NO_DUPLICATE_KEYS(key), }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts index 04dfbb4e60b..9965e2658ae 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts @@ -6,6 +6,7 @@ */ import {Path, REDUCE_REMOVE, TransformExitResult} from '@romejs/js-compiler'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noEmptyCharacterClass', @@ -14,9 +15,7 @@ export default { if (node.type === 'RegExpCharSet' && node.body.length === 0 && !node.invert) { context.addNodeDiagnostic(node, { - fixable: true, - category: 'lint/noEmptyCharacterClass', - message: 'Empty character classes in regular expressions are not allowed', + description: descriptions.LINT.NO_EMPTY_CHAR_SET, }); return REDUCE_REMOVE; } diff --git a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts index 528bedbc6f5..e4d3dc6cba5 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts @@ -7,6 +7,7 @@ import {AnyNode} from '@romejs/js-ast'; import {Path} from '@romejs/js-compiler'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noExplicitAny', @@ -15,8 +16,7 @@ export default { if (node.type === 'AnyKeywordTypeAnnotation') { context.addNodeDiagnostic(node, { - category: 'lint/noExplicitAny', - message: 'Unexpected any. Specify a different type.', + description: descriptions.LINT.NO_EXPLICIT_ANY, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.test.ts b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.test.ts index 21ba545ed16..c6040e1f38a 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.test.ts @@ -16,7 +16,7 @@ test('disallow unnecessary boolean casts', async (t) => { `); t.truthy(ifTest.diagnostics.find((d) => - d.message === `Redundant double negation.` + d.description.message.value === `Redundant double negation.` )); const whileTest = await testLint(` @@ -26,7 +26,7 @@ test('disallow unnecessary boolean casts', async (t) => { `); t.truthy(whileTest.diagnostics.find((d) => - d.message === `Redundant double negation.` + d.description.message.value === `Redundant double negation.` )); const doWhileTest = await testLint(` @@ -38,7 +38,7 @@ test('disallow unnecessary boolean casts', async (t) => { `); t.truthy(doWhileTest.diagnostics.find((d) => - d.message === `Redundant double negation.` + d.description.message.value === `Redundant double negation.` )); const forTest = await testLint(` @@ -48,6 +48,6 @@ test('disallow unnecessary boolean casts', async (t) => { `); t.truthy(forTest.diagnostics.find((d) => - d.message === `Redundant double negation.` + d.description.message.value === `Redundant double negation.` )); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts index 47e515981e5..47a7c07edc1 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts @@ -14,6 +14,7 @@ import { ForStatement, ConditionalExpression, } from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; function isBooleanConstructorCall(node: AnyNode) { return node.type === 'NewExpression' && node.callee.type === @@ -58,8 +59,7 @@ export default { '!' || node.type === 'CallExpression' && node.callee.type === 'ReferenceIdentifier' && node.callee.name === 'Boolean') { context.addNodeDiagnostic(node, { - category: 'lint/noExtraBooleanCast', - message: `Redundant double negation.`, + description: descriptions.LINT.NO_EXTRA_BOOLEAN_CAST, }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.test.ts b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.test.ts index 1e8e0a8fb8e..2db98484250 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.test.ts @@ -7,11 +7,11 @@ import test from '@romejs/test'; import {testLint} from '../../api/lint.test'; -import {PartialDiagnostic} from '@romejs/diagnostics/types'; +import {Diagnostic} from '@romejs/diagnostics/types'; test('no function reassignment', async (t) => { - function checkCategory(diagnostic: PartialDiagnostic): Boolean { - return diagnostic.category === 'lint/noFunctionAssign'; + function checkCategory(diagnostic: Diagnostic): Boolean { + return diagnostic.description.category === 'lint/noFunctionAssign'; } const validTestCases = [ diff --git a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts index 8ad33b28eeb..50db3b19885 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts @@ -8,6 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; import {FunctionBinding} from '@romejs/js-compiler/scope/bindings'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noFunctionAssign', @@ -17,8 +18,7 @@ export default { if (node.type === 'AssignmentIdentifier' && scope.getBinding(node.name) instanceof FunctionBinding) { path.context.addNodeDiagnostic(node, { - category: 'lint/noFunctionAssign', - message: 'Reassignment of function declaration', + description: descriptions.LINT.NO_FUNCTION_ASSIGN, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.test.ts b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.test.ts index cd30618a5c7..015abead691 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.test.ts @@ -25,7 +25,9 @@ test('no import assign', async (t) => { ]; for (let failingCase of failingCases) { const res = await testLint(failingCase); - if (!res.diagnostics.some((d) => d.category === 'lint/noImportAssign')) { + if (!res.diagnostics.some((d) => + d.description.category === 'lint/noImportAssign' + )) { t.fail( `expected "\n${failingCase}\n" to report a lint/noImportAssign diagnostic but it didn't`, [ diff --git a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts index 4067697dc15..9d01ea16477 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts @@ -7,7 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; -import {markup} from '@romejs/string-markup'; +import {descriptions} from '@romejs/diagnostics'; function isAssignment(path: Path) { switch (path.parentPath.node.type) { @@ -29,12 +29,11 @@ export default { if (node.type === 'AssignmentIdentifier' && isAssignment(path) || node.type === 'ReferenceIdentifier' && path.parentPath.node.type === 'UpdateExpression') { - let binding = scope.getBinding(node.name); + const binding = scope.getBinding(node.name); if (binding !== undefined && binding.kind === 'import') path.context.addNodeDiagnostic( node, { - category: 'lint/noImportAssign', - message: markup`${node.name} is read-only`, + description: descriptions.LINT.NO_IMPORT_ASSIGN(node.name), }, ); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.test.ts b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.test.ts index 872f11b5594..be37c21425e 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.test.ts @@ -14,12 +14,16 @@ test('no label var', async (t) => { x: const y = "test"; `); - t.truthy(badLabel.diagnostics.find((d) => d.category === 'lint/noLabelVar')); + t.truthy(badLabel.diagnostics.find((d) => + d.description.category === 'lint/noLabelVar' + )); const okLabel = await testLint(` const x = "test"; z: const y = "test"; `); - t.falsy(okLabel.diagnostics.find((d) => d.category === 'lint/noLabelVar')); + t.falsy(okLabel.diagnostics.find((d) => + d.description.category === 'lint/noLabelVar' + )); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts index ff615f5d78c..b4654aa73d8 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noLabelVar', @@ -22,8 +23,7 @@ export default { if (isDefined) { path.context.addNodeDiagnostic(node, { - category: 'lint/noLabelVar', - message: 'Labels should not be variable names', + description: descriptions.LINT.NO_LABEL_VAR, }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts index 19c4012a613..fa9bcd7b813 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts @@ -15,6 +15,7 @@ import { } from '@romejs/js-ast'; import {Path, Context} from '@romejs/js-compiler'; import {extractSourceLocationRangeFromNodes} from '@romejs/parser-core'; +import {descriptions} from '@romejs/diagnostics'; function isSpaceChar( node: undefined | AnyRegExpBodyItem, @@ -49,16 +50,9 @@ function checkRegex( } context.addLocDiagnostic(extractSourceLocationRangeFromNodes(spaceNodes), { - fixable: true, - category: 'lint/noMultipleSpacesInRegularExpressionLiterals', - message: 'Unclear multiple spaces in regular expression', - advice: [ - { - type: 'log', - category: 'info', - message: `It's hard to visually count the amount of spaces, it's clearer if you use a quantifier instead. eg / {${spaceNodes.length}}/`, - }, - ], + description: descriptions.LINT.NO_MULTIPLE_SPACES_IN_REGEX_LITERAL( + spaceNodes.length, + ), }); const quantifiedSpace: RegExpQuantified = regExpQuantified.create({ diff --git a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.test.ts b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.test.ts index 60006aadb8a..c3d79588733 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.test.ts @@ -21,7 +21,7 @@ test('no shadow restricted names', async (t) => { for (let failingCase of failingCases) { const res = await testLint(failingCase); if (!res.diagnostics.some((d) => - d.category === 'lint/noShadowRestrictedNames' + d.description.category === 'lint/noShadowRestrictedNames' )) { t.fail( `expected "\n${failingCase}\n" to report a lint/noShadowRestrictedNames diagnostic but it didn't`, diff --git a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts index 40277a73489..3e216e99f94 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts @@ -8,7 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {TransformExitResult} from '@romejs/js-compiler/types'; import {builtin, es5, es2015, es2017} from '@romejs/js-compiler/scope/globals'; -import {markup} from '@romejs/string-markup'; +import {descriptions} from '@romejs/diagnostics'; const restrictedNames = new Set([...builtin, ...es5, ...es2015, ...es2017]); @@ -21,15 +21,7 @@ export default { for (const [name, binding] of scope.getOwnBindings()) { if (restrictedNames.has(name)) { context.addNodeDiagnostic(binding.node, { - category: 'lint/noShadowRestrictedNames', - message: markup`Shadowing of global property ${name}`, - advice: [ - { - type: 'log', - category: 'info', - message: 'Consider renaming this variable. It\'s easy to confuse the origin of variables when they\'re named after a known global.', - }, - ], + description: descriptions.LINT.NO_SHADOW_RESTRICTED_NAMES(name), }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts index 562d605f8ea..90c7f1ce4c2 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts @@ -6,7 +6,7 @@ */ import {Path} from '@romejs/js-compiler'; -import {markup} from '@romejs/string-markup'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noTemplateCurlyInString', @@ -18,8 +18,7 @@ export default { if (regex.test(node.value)) { context.addNodeDiagnostic(node, { - category: 'lint/noTemplateCurlyInString', - message: markup`Unexpected template string expression.`, + description: descriptions.LINT.NO_TEMPLATE_CURLY_IN_STRING, }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.test.ts b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.test.ts index 5074854948d..6f6b85fa130 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.test.ts @@ -26,7 +26,7 @@ test( `); t.truthy(returnTest.diagnostics.find((d) => - d.message === `Unsafe usage of ReturnStatement.` + d.description.message.value === `Unsafe usage of ReturnStatement.` )); const breakTest = await testLint(` @@ -45,7 +45,7 @@ test( `); t.truthy(breakTest.diagnostics.find((d) => - d.message === `Unsafe usage of BreakStatement.` + d.description.message.value === `Unsafe usage of BreakStatement.` )); const continueTest = await testLint(` @@ -63,7 +63,7 @@ test( `); t.truthy(continueTest.diagnostics.find((d) => - d.message === `Unsafe usage of ContinueStatement.` + d.description.message.value === `Unsafe usage of ContinueStatement.` )); const throwTest = await testLint(` @@ -81,7 +81,7 @@ test( `); t.truthy(throwTest.diagnostics.find((d) => - d.message === `Unsafe usage of ThrowStatement.` + d.description.message.value === `Unsafe usage of ThrowStatement.` )); }, ); diff --git a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts index bc683e8ad92..edaf7ecf6d1 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noUnsafeFinally', @@ -22,8 +23,7 @@ export default { 'ContinueStatement' || statement.type === 'BreakStatement' || statement.type === 'ReturnStatement') { context.addNodeDiagnostic(statement, { - category: 'lint/noUnsafeFinally', - message: `Unsafe usage of ${statement.type}.`, + description: descriptions.LINT.NO_UNSAFE_FINALLY(statement.type), }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noVar.ts b/packages/@romejs/js-compiler/transforms/lint/noVar.ts index e8cf2dccc68..208f49d12fe 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noVar.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noVar.ts @@ -7,6 +7,7 @@ import {AnyNode} from '@romejs/js-ast'; import {Path} from '@romejs/js-compiler'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'noVar', @@ -15,8 +16,7 @@ export default { if (declaration.type === 'VariableDeclaration' && declaration.kind === 'var') { context.addNodeDiagnostic(declaration, { - category: 'lint/noVar', - message: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.', + description: descriptions.LINT.NO_VAR, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts index 17115d8ea76..0e10e89045d 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts +++ b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts @@ -19,6 +19,7 @@ import { ThisExpression, } from '@romejs/js-ast'; import {isFunctionNode} from '@romejs/js-ast-utils'; +import {descriptions} from '@romejs/diagnostics'; type State = {declarators: Array}; @@ -88,9 +89,7 @@ const hook = createHook({ } path.context.addNodeDiagnostic(init, { - category: 'lint/preferFunctionDeclarations', - message: 'Use a function declaration instead of a const function', - fixable: true, + description: descriptions.LINT.PREFER_FUNCTION_DECLARATIONS, }); // Convert arrow function body if necessary diff --git a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts index 6a11b896c94..71b36be3253 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts +++ b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'preferTemplate', @@ -17,8 +18,7 @@ export default { (node.left.type === 'StringLiteral' && !node.left.value.includes('`') || node.right.type === 'StringLiteral' && !node.right.value.includes('`'))) { path.context.addNodeDiagnostic(node, { - category: 'lint/preferTemplate', - message: 'You\'re using string concatenation when template literals are preferred', + description: descriptions.LINT.PREFER_TEMPLATE, }); } diff --git a/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts b/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts index 103f81c74be..7219bc10688 100644 --- a/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts +++ b/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts @@ -8,6 +8,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode} from '@romejs/js-ast'; import {referenceIdentifier, arrayExpression} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'sparseArray', @@ -16,9 +17,7 @@ export default { if (node.type === 'ArrayExpression' && node.elements.includes(undefined)) { path.context.addNodeDiagnostic(node, { - fixable: true, - category: 'lint/sparseArray', - message: 'Your array contains an empty slot', + description: descriptions.LINT.SPARSE_ARRAY, }); return arrayExpression.quick(node.elements.map((elem) => diff --git a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts index 49bd8aeaa80..55bac1a3470 100644 --- a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts +++ b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts @@ -6,9 +6,9 @@ */ import {Path} from '@romejs/js-compiler'; -import {markup} from '@romejs/string-markup'; import {isInTypeAnnotation} from '@romejs/js-ast-utils'; import {AnyNode} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; const NODE_VARIABLES = [ 'require', @@ -55,8 +55,7 @@ export default { if (!isDefined) { path.context.addNodeDiagnostic(node, { - category: 'lint/undeclaredVariables', - message: markup`Undeclared variable ${name}`, + description: descriptions.LINT.UNDECLARED_VARIABLES(name), }); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts index fcf68388f3a..af9d1e14fd0 100644 --- a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts +++ b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts @@ -7,6 +7,7 @@ import {Path} from '@romejs/js-compiler'; import {AnyNode, unaryExpression} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export default { name: 'unsafeNegation', @@ -17,9 +18,7 @@ export default { node.operator === 'instanceof') && node.left.type === 'UnaryExpression' && node.left.operator === '!') { path.context.addNodeDiagnostic(node, { - fixable: true, - category: 'lint/unsafeNegation', - message: 'Unsafe usage of negation operator in left side of binary expression', + description: descriptions.LINT.UNSAFE_NEGATION, }); return unaryExpression.create({ diff --git a/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts b/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts index 2811a0ba501..e996b207098 100644 --- a/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts +++ b/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts @@ -10,6 +10,7 @@ import {Path, Scope, createHook} from '@romejs/js-compiler'; import {getBindingIdentifiers} from '@romejs/js-ast-utils'; import {Dict} from '@romejs/typescript-helpers'; import {ArgumentsBinding} from '@romejs/js-compiler/scope/bindings'; +import {descriptions} from '@romejs/diagnostics'; type State = { usedBindings: Dict; @@ -64,8 +65,7 @@ const provider = createHook({ if (used === false && binding !== undefined) { path.context.addNodeDiagnostic(binding.node, { - category: 'lint/unusedVariables', - message: `Unused ${binding.kind} ${name}`, + description: descriptions.LINT.UNUSED_VARIABLES(binding.kind, name), }); } } diff --git a/packages/@romejs/js-parser-utils/index.ts b/packages/@romejs/js-parser-utils/index.ts index ea69a08d0b5..67ecda6f9f7 100644 --- a/packages/@romejs/js-parser-utils/index.ts +++ b/packages/@romejs/js-parser-utils/index.ts @@ -12,5 +12,3 @@ export * from './location'; export * from './regex'; export * from './whitespace'; - -export {default as messages} from './messages'; diff --git a/packages/@romejs/js-parser-utils/messages.ts b/packages/@romejs/js-parser-utils/messages.ts deleted file mode 100644 index a8eeee9ec70..00000000000 --- a/packages/@romejs/js-parser-utils/messages.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {createMessageFactory} from '@romejs/messages'; - -export default createMessageFactory({ - DUPLICATE_REGEX_FLAG: 'Duplicate regular expression flag', - INVALID_REGEX_FLAG: 'Invalid regular expression flag', -}); diff --git a/packages/@romejs/js-parser-utils/regex.ts b/packages/@romejs/js-parser-utils/regex.ts index 53b284323b4..f25b4717983 100644 --- a/packages/@romejs/js-parser-utils/regex.ts +++ b/packages/@romejs/js-parser-utils/regex.ts @@ -5,14 +5,14 @@ * LICENSE file in the root directory of this source tree. */ -import messages from './messages'; +import {descriptions, DiagnosticDescription} from '@romejs/diagnostics'; const VALID_REGEX_FLAGS: Array = 'gmsiyu'.split(''); // This is used by both rome-json and rome-js-parser to validate regex flags export function validateRegexFlags( flags: string, - onUnexpected: (message: string, index: number) => void, + onUnexpected: (metadata: Omit, index: number) => void, ): Set { const foundFlags: Set = new Set(); @@ -21,12 +21,12 @@ export function validateRegexFlags( if (VALID_REGEX_FLAGS.includes(flag)) { if (foundFlags.has(flag)) { - onUnexpected(messages.DUPLICATE_REGEX_FLAG(), i); + onUnexpected(descriptions.REGEX_PARSER.DUPLICATE_FLAG, i); } else { foundFlags.add(flag); } } else { - onUnexpected(messages.INVALID_REGEX_FLAG(), i); + onUnexpected(descriptions.REGEX_PARSER.INVALID_FLAG, i); } } diff --git a/packages/@romejs/js-parser/index.test.ts b/packages/@romejs/js-parser/index.test.ts index 26b452bfbd7..d3de4aa7bc5 100644 --- a/packages/@romejs/js-parser/index.test.ts +++ b/packages/@romejs/js-parser/index.test.ts @@ -107,7 +107,7 @@ const promise = createFixtureTests((fixture, t) => { let matches = false; for (const diag of diagnostics) { - if (escapeMarkup(diag.message).includes(expectError)) { + if (escapeMarkup(diag.description.message.value).includes(expectError)) { matches = true; break; } @@ -120,7 +120,9 @@ const promise = createFixtureTests((fixture, t) => { expectError, )}"`; if (diagnostics.length === 1) { - msg += ` but got "${escapeMarkup(diagnostics[0].message)}"`; + msg += ` but got "${escapeMarkup( + diagnostics[0].description.message.value, + )}"`; } msg; //throw new DiagnosticsError(msg, diagnostics); diff --git a/packages/@romejs/js-parser/index.ts b/packages/@romejs/js-parser/index.ts index 2366c2db749..e4af97b62ff 100644 --- a/packages/@romejs/js-parser/index.ts +++ b/packages/@romejs/js-parser/index.ts @@ -31,8 +31,8 @@ export function tokenizeJS( // If we have any diagnostics, then mark anything from the first as invalid if (diagnostics.length > 0) { const firstDiag = diagnostics[0]; - const invalidStart = firstDiag.start; - const invalidEnd = firstDiag.end; + const invalidStart = firstDiag.location.start; + const invalidEnd = firstDiag.location.end; if (invalidStart === undefined || invalidEnd === undefined) { throw new Error('All parser diagnostics are expected to have a start/end'); } diff --git a/packages/@romejs/js-parser/parser.ts b/packages/@romejs/js-parser/parser.ts index 685c8f15f2a..c4b99ef68e9 100644 --- a/packages/@romejs/js-parser/parser.ts +++ b/packages/@romejs/js-parser/parser.ts @@ -21,9 +21,10 @@ import { } from '@romejs/parser-core'; import {JSParserOptions} from './options'; import { - PartialDiagnosticAdvice, - PartialDiagnostics, + Diagnostics, DiagnosticFilter, + DiagnosticDescription, + descriptions, } from '@romejs/diagnostics'; import {State} from './tokenizer/state'; import ParserBranchFinder from './ParserBranchFinder'; @@ -34,7 +35,7 @@ import {lineBreak} from '@romejs/js-parser-utils'; import {parseTopLevel} from './parser/index'; import {createInitialState} from './tokenizer/state'; import {sub, Number0, number0} from '@romejs/ob1'; -import {Dict} from '@romejs/typescript-helpers'; +import {Dict, OptionalProps} from '@romejs/typescript-helpers'; import {attachComments} from './parser/comments'; const TOKEN_MISTAKES: Dict = { @@ -258,19 +259,21 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => }; } - assertNoSpace(message: string = 'Unexpected space'): void { + assertNoSpace( + _metadata: Omit = descriptions.JS_PARSER.UNEXPECTED_SPACE, + ): void { const {state} = this; if (state.startPos.index > state.lastEndPos.index) { this.addDiagnostic({ start: state.lastEndPos, end: state.lastEndPos, - message, + description: _metadata, }); } } - getDiagnostics(): PartialDiagnostics { + getDiagnostics(): Diagnostics { const collector = new DiagnosticsProcessor({ origins: [ { @@ -292,7 +295,7 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => this.state.diagnosticFilters.push(diag); } - addCompleteDiagnostic(diags: PartialDiagnostics) { + addCompleteDiagnostic(diags: Diagnostics) { this.state.diagnostics = [...this.state.diagnostics, ...diags]; } @@ -329,13 +332,12 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => } addDiagnostic( - diag: { - message: string; + opts: { + description: Omit; start?: Position; end?: Position; loc?: SourceLocation; index?: Number0; - advice?: PartialDiagnosticAdvice; }, ) { if (this.isLookahead) { @@ -356,16 +358,16 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => //return; } - let {start, end} = diag; + let {start, end} = opts; - if (diag.index !== undefined) { - start = this.getPositionFromIndex(diag.index); + if (opts.index !== undefined) { + start = this.getPositionFromIndex(opts.index); end = start; } - if (diag.loc !== undefined) { - start = diag.loc.start; - end = diag.loc.end; + if (opts.loc !== undefined) { + start = opts.loc.start; + end = opts.loc.end; } // If we weren't given a start then default to the provided end, or the current token start @@ -383,14 +385,16 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => } this.state.diagnostics.push({ - filename: this.filename, - sourceType: this.sourceType, - mtime: this.mtime, - message: diag.message, - advice: diag.advice, - start, - end, - category: 'parse/js', + description: { + category: 'parse/js', + ...opts.description, + }, + location: { + sourceType: this.sourceType, + mtime: this.mtime, + start, + end, + }, }); } @@ -405,7 +409,7 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => expectSyntaxEnabled(syntax: ConstProgramSyntax) { if (!this.isSyntaxEnabled(syntax)) { this.addDiagnostic({ - message: `Expected ${syntax} to be enabled`, + description: descriptions.JS_PARSER.EXPECTED_ENABLE_SYNTAX(syntax), }); } } @@ -419,7 +423,7 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => return true; } else { this.addDiagnostic({ - message: 'Expected relational operator', + description: descriptions.JS_PARSER.EXPECTED_RELATIONAL_OPERATOR, }); return false; } @@ -434,7 +438,7 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => if (index !== undefined) { this.addDiagnostic({ index, - message: `${name} can't contain a unicode escape`, + description: descriptions.JS_PARSER.ESCAPE_SEQUENCE_IN_WORD(name), }); } } @@ -474,13 +478,15 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => // Asserts that following token is given contextual keyword. expectContextual( name: string, - message: string = `Expected keyword ${name}`, + _metadata: OptionalProps = descriptions.JS_PARSER.EXPECTED_KEYWORD( + name, + ), ): boolean { if (this.eatContextual(name)) { return true; } else { this.addDiagnostic({ - message, + description: _metadata, }); return false; } @@ -509,7 +515,7 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => semicolon(): void { if (!this.isLineTerminator()) { this.addDiagnostic({ - message: 'Expected a semicolon or a line terminator', + description: descriptions.JS_PARSER.EXPECTED_SEMI_OR_LINE_TERMINATOR, }); } } @@ -545,50 +551,25 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => expectClosing(context: OpeningContext) { if (this.match(context.close)) { - if (this.state.indentLevel !== context.indent) { - this.state.possibleIncorrectOpenParens.push(context); - } this.next(); return true; } else { const currPos = this.getPosition(); - const advice: PartialDiagnosticAdvice = [ - { - type: 'log', - category: 'info', - message: `We expected to find the closing character ${context.close.label} here`, - }, - { - type: 'frame', - filename: this.filename, - start: currPos, - end: currPos, - }, - ]; - - const possibleThief = this.state.possibleIncorrectOpenParens.shift(); - if (possibleThief !== undefined) { - advice.push({ - type: 'log', - category: 'info', - message: `We found this ${possibleThief.name} that looks suspicious. It could be the real culprit that's unclosed.`, - }); - - advice.push({ - type: 'frame', - filename: this.filename, - start: possibleThief.start, - end: possibleThief.start, - }); - } - this.addDiagnostic({ - message: `Unclosed ${context.name}`, + description: descriptions.JS_PARSER.EXPECTED_CLOSING( + context.name, + context.close.label, + { + filename: this.filename, + start: currPos, + end: currPos, + }, + ), start: context.start, end: context.start, - advice, }); + return false; } } @@ -597,27 +578,24 @@ const createJSParser = createParser((ParserCore, ParserWithRequiredPath) => // instead of a message string. unexpectedToken(pos?: Position, tokenType?: TokenType) { - const advice: PartialDiagnosticAdvice = []; - let message = 'Unexpected token'; // + new Error().stack; + let expectedToken: undefined | string; + let possibleShiftMistake: boolean = false; + if (tokenType !== undefined) { - message += `, expected "${tokenType.label}"`; + expectedToken = tokenType.label; const possibleMistake = TOKEN_MISTAKES[tokenType.label]; - if (possibleMistake !== undefined && possibleMistake === - this.state.tokenType.label) { - advice.push({ - type: 'log', - category: 'info', - message: `Did you accidently hold shift?`, - }); - } + possibleShiftMistake = possibleMistake !== undefined && + possibleMistake === this.state.tokenType.label; } this.addDiagnostic({ - message, + description: descriptions.JS_PARSER.UNEXPECTED_TOKEN( + expectedToken, + possibleShiftMistake, + ), start: pos === undefined ? this.state.startPos : pos, end: pos === undefined ? this.state.endPos : pos, - advice, }); } diff --git a/packages/@romejs/js-parser/parser/classes.ts b/packages/@romejs/js-parser/parser/classes.ts index ab43f6113ce..11f2b7a0931 100644 --- a/packages/@romejs/js-parser/parser/classes.ts +++ b/packages/@romejs/js-parser/parser/classes.ts @@ -51,6 +51,7 @@ import { } from './index'; import {inc, dec} from '@romejs/ob1'; import {parseBindingIdentifier, toBindingIdentifier} from './expression'; +import {descriptions} from '@romejs/diagnostics'; export function parseClassExpression( parser: JSParser, @@ -269,7 +270,7 @@ function parseClassMember( if (escapePosition !== undefined) { parser.addDiagnostic({ index: escapePosition, - message: 'No escapes allowed in static contextual keyword', + description: descriptions.JS_PARSER.ESCAPE_SEQUENCE_IN_WORD('static'), }); } @@ -357,7 +358,7 @@ function parseClassMemberWithIsStatic( if (isNonstaticConstructor(parser, key, meta)) { parser.addDiagnostic({ loc: key.loc, - message: 'Constructor can\'t be a generator', + description: descriptions.JS_PARSER.GENERATOR_CLASS_CONSTRUCTOR, }); } @@ -401,7 +402,7 @@ function parseClassMemberWithIsStatic( if (state.hadConstructor && !parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ loc: key.loc, - message: 'Duplicate constructor in the same class', + description: descriptions.JS_PARSER.DUPLICATE_CLASS_CONSTRUCTOR, }); } state.hadConstructor = true; @@ -465,7 +466,7 @@ function parseClassMemberWithIsStatic( if (isNonstaticConstructor(parser, key, meta)) { parser.addDiagnostic({ loc: key.loc, - message: 'Constructor can\'t be an async function', + description: descriptions.JS_PARSER.ASYNC_CLASS_CONSTRUCTOR, }); } @@ -515,7 +516,7 @@ function parseClassMemberWithIsStatic( if (isNonstaticConstructor(parser, key, meta)) { parser.addDiagnostic({ loc: methodKey.loc, - message: 'Constructor can\'t have get/set modifier', + description: descriptions.JS_PARSER.GET_SET_CLASS_CONSTRUCTOR, }); } @@ -534,7 +535,7 @@ function parseClassMemberWithIsStatic( } parser.addDiagnostic({ - message: 'Unknown class property start', + description: descriptions.JS_PARSER.UNKNOWN_CLASS_PROPERTY_START, }); return undefined; } @@ -563,27 +564,21 @@ function parseClassPropertyMeta( key.value.type === 'Identifier' && key.value.name === 'prototype') { parser.addDiagnostic({ loc: key.loc, - message: 'Classes may not have static property named prototype', + description: descriptions.JS_PARSER.CLASS_STATIC_PROTOTYPE_PROPERTY, }); } if (key.value.type === 'PrivateName' && key.value.id.name === 'constructor') { parser.addDiagnostic({ loc: key.loc, - message: 'Classes may not have a private field named \'#constructor\'', + description: descriptions.JS_PARSER.CLASS_PRIVATE_FIELD_NAMED_CONSTRUCTOR, }); } let optional = false; if (parser.match(tt.question)) { optional = true; - - if (!parser.isSyntaxEnabled('ts')) { - parser.addDiagnostic({ - message: 'Optional syntax but ts is not enabled', - }); - } - + parser.expectSyntaxEnabled('ts'); parser.next(); } @@ -608,7 +603,7 @@ function pushClassProperty( if (isNonstaticConstructor(parser, key, meta)) { parser.addDiagnostic({ loc: key.loc, - message: 'Classes may not have a non-static field named \'constructor\'', + description: descriptions.JS_PARSER.CLASS_PROPERTY_NAME_CONSTRUCTOR, }); } @@ -633,7 +628,7 @@ function parseClassMethod( if (key.variance !== undefined) { parser.addDiagnostic({ loc: key.variance.loc, - message: 'variance not allowed here', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -698,7 +693,7 @@ function parseClassPrivateMethod( if (variance !== undefined) { parser.addDiagnostic({ loc: variance.loc, - message: 'variance not allowed here', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -769,12 +764,7 @@ function parseClassProperty( let definite; if (!meta.optional && parser.eat(tt.bang)) { definite = true; - - if (!parser.isSyntaxEnabled('ts')) { - parser.addDiagnostic({ - message: 'Definite syntax but ts is not enabled', - }); - } + parser.expectSyntaxEnabled('ts'); } let typeAnnotation; @@ -832,7 +822,7 @@ function parseClassId( id = parseBindingIdentifier(parser); } else if (!optionalId) { parser.addDiagnostic({ - message: 'A class name is required', + description: descriptions.JS_PARSER.REQUIRED_CLASS_NAME, }); id = toBindingIdentifier(parser, parser.createUnknownIdentifier( 'required class name', diff --git a/packages/@romejs/js-parser/parser/expression.ts b/packages/@romejs/js-parser/parser/expression.ts index 27322b37dd6..ca32ea3e958 100644 --- a/packages/@romejs/js-parser/parser/expression.ts +++ b/packages/@romejs/js-parser/parser/expression.ts @@ -120,6 +120,7 @@ import { import {number0, number0Neg1, Number0, get0, inc} from '@romejs/ob1'; import {splitFunctionParams} from './statement'; import {createRegExpParser} from '@romejs/codec-js-regexp'; +import {descriptions} from '@romejs/diagnostics'; // Check if property name clashes with already added. @@ -151,7 +152,7 @@ export function checkPropClash( if (name === '__proto__') { if (props.has('proto')) { parser.addDiagnostic({ - message: 'Redefinition of __proto__ property', + description: descriptions.JS_PARSER.PROTO_PROP_REDEFINITION, loc: key.loc, }); } else { @@ -299,7 +300,7 @@ export function parseMaybeAssign( } else { parser.addDiagnostic({ loc: typeParameters.loc, - message: 'Expected an arrow function after this type parameter declaration', + description: descriptions.JS_PARSER.EXPECTED_ARROW_AFTER_TYPE_PARAMS, }); return toReferenceIdentifier(parser, parser.createUnknownIdentifier( 'type params without arrow function', @@ -497,7 +498,7 @@ export function parseConditional( if (!parser.eat(tt.colon)) { parser.addDiagnostic({ - message: 'Missing conditional expression consequent separator', + description: descriptions.JS_PARSER.MISSING_CONDITIONAL_SEPARATOR, }); } @@ -627,7 +628,7 @@ export function parseExpressionOp( !parser.isParenthesized(left)) { parser.addDiagnostic({ loc: left.argument.loc, - message: 'Illegal expression. Wrap left hand side or entire exponentiation in parentheses.', + description: descriptions.JS_PARSER.WRAP_EXPONENTIATION, }); } @@ -711,13 +712,13 @@ export function parseMaybeUnary( if (argument.type === 'ReferenceIdentifier') { parser.addDiagnostic({ loc: argument.loc, - message: 'Deleting local variable in strict mode', + description: descriptions.JS_PARSER.DELETE_LOCAL_VARIABLE_IN_STRICT, }); } else if (argument.type === 'MemberExpression' && argument.property.value.type === 'PrivateName') { parser.addDiagnostic({ loc: argument.property.loc, - message: 'Deleting a private field is not allowed', + description: descriptions.JS_PARSER.DELETE_PRIVATE_FIELD, }); } } @@ -1133,7 +1134,7 @@ export function parseTaggedTemplateExpression( ): TaggedTemplateExpression { if (state.optionalChainMember) { parser.addDiagnostic({ - message: 'Tagged Template Literals are not allowed in optionalChain', + description: descriptions.JS_PARSER.TAGGED_TEMPLATE_IN_OPTIONAL_CHAIN, }); } @@ -1151,14 +1152,14 @@ export function checkYieldAwaitInDefaultParams(parser: JSParser) { parser.state.yieldPos < parser.state.awaitPos)) { parser.addDiagnostic({ index: parser.state.yieldPos, - message: 'Yield cannot be used as name inside a generator function', + description: descriptions.JS_PARSER.YIELD_IN_GENERATOR_PARAMS, }); } if (get0(parser.state.awaitPos) > 0) { parser.addDiagnostic({ index: parser.state.awaitPos, - message: 'Await cannot be used as name inside an async function', + description: descriptions.JS_PARSER.AWAIT_IN_ASYNC_PARAMS, }); } } @@ -1243,7 +1244,7 @@ export function parseCallExpressionArguments( funcParams.push(elt); } else { parser.addDiagnostic({ - message: 'Function parameter type annotation? Possibly forgot curlies around an object. Possibly forgot async keyword.', + description: descriptions.JS_PARSER.CONFUSING_CALL_ARGUMENT, loc: elt.loc, }); } @@ -1259,7 +1260,7 @@ export function parseCallExpressionArguments( if (forceAsyncArrow && !shouldParseAsyncArrow(parser)) { parser.addDiagnostic({ - message: 'Expected arrow because we are a possible async arrow and type annotated parameters were present', + description: descriptions.JS_PARSER.EXPECTED_ARROW_AFTER_ASYNC_TYPE_PARAMS, }); } @@ -1268,7 +1269,7 @@ export function parseCallExpressionArguments( shouldParseAsyncArrow(parser)) { parser.addDiagnostic({ start: innerParenStart, - message: 'Inner paren inside of an async arrow function params', + description: descriptions.JS_PARSER.PARENTHESIZED_FUNCTION_PARAMS, }); } @@ -1523,7 +1524,9 @@ export function parseExpressionAtom( { const start = parser.getPosition(); parser.addDiagnostic({ - message: `Unknown start to an ${context}`, + description: descriptions.JS_PARSER.UNKNOWN_EXPRESSION_ATOM_START( + context, + ), }); parser.next(); return toReferenceIdentifier(parser, parser.createUnknownIdentifier( @@ -1550,7 +1553,7 @@ export function parseMaybePrivateName(parser: JSParser): PrivateName | Identifie if (isPrivate) { const start = parser.getPosition(); parser.next(); - parser.assertNoSpace('Unexpected space between # and identifier'); + parser.assertNoSpace(descriptions.JS_PARSER.SPACE_BETWEEN_PRIVATE_HASH); const id = parseIdentifier(parser, true); return parser.finishNode(start, { type: 'PrivateName', @@ -1611,7 +1614,10 @@ export function parseMetaProperty( } else { parser.addDiagnostic({ loc: property.loc, - message: `The only valid meta property for ${meta.name} is ${meta.name}.${propertyName}`, + description: descriptions.JS_PARSER.INVALID_META_PROPERTY( + meta.name, + propertyName, + ), }); } @@ -1631,7 +1637,7 @@ export function parseImportMetaProperty(parser: JSParser): MetaProperty { if (!parser.inModule) { parser.addDiagnostic({ loc: node.loc, - message: `import.meta may appear only with 'sourceType: "module"'`, + description: descriptions.JS_PARSER.IMPORT_META_OUTSIDE_MODULE, }); } @@ -1742,7 +1748,7 @@ export function parseParenAndDistinguishExpression( if (parser.isParenthesized(param)) { parser.addDiagnostic({ loc: param.loc, - message: 'Function parameters can\'t be parenthesized', + description: descriptions.JS_PARSER.PARENTHESIZED_FUNCTION_PARAMS, }); } } @@ -1774,7 +1780,7 @@ export function parseParenAndDistinguishExpression( parser.addDiagnostic({ start: innerStart, end: innerEnd, - message: 'Parenthesized expression didnt contain anything', + description: descriptions.JS_PARSER.EMPTY_PARENTHESIZED_EXPRESSION, }); exprList.push(toReferenceIdentifier(parser, parser.createUnknownIdentifier( @@ -1936,7 +1942,7 @@ export function parseNew(parser: JSParser): NewExpression | MetaProperty { )) { parser.addDiagnostic({ loc: metaProp.loc, - message: 'new.target can only be used in functions or class properties', + description: descriptions.JS_PARSER.NEW_TARGET_OUTSIDE_CLASS, }); } @@ -1948,7 +1954,7 @@ export function parseNew(parser: JSParser): NewExpression | MetaProperty { if (callee.type === 'ImportCall') { parser.addDiagnostic({ loc: callee.loc, - message: 'Cannot use new with import(...)', + description: descriptions.JS_PARSER.SUPER_OUTSIDE_METHOD, }); } @@ -1957,26 +1963,13 @@ export function parseNew(parser: JSParser): NewExpression | MetaProperty { const memberLoc = parser.getLoc(optionalMember); parser.addDiagnostic({ - message: 'constructors in/after an Optional Chain are not allowed', - advice: [ - { - type: 'log', - category: 'info', - message: 'Optional chain member responsible', - }, - { - type: 'frame', - filename: parser.filename, - start: memberLoc.start, - end: memberLoc.end, - }, - ], + description: descriptions.JS_PARSER.NEW_IN_OPTIONAL_CHAIN(memberLoc), }); } if (parser.eat(tt.questionDot)) { parser.addDiagnostic({ - message: 'constructors in/after an Optional Chain are not allowed', + description: descriptions.JS_PARSER.NEW_IN_OPTIONAL_CHAIN(), }); } @@ -2005,7 +1998,7 @@ export function parseNew(parser: JSParser): NewExpression | MetaProperty { args = toReferencedList(parser, args); } else if (parser.isSyntaxEnabled('ts') && typeArguments !== undefined) { parser.addDiagnostic({ - message: 'In TypeScript, a new expression with type arguments must have parens', + description: descriptions.JS_PARSER.NEW_WITH_TYPESCRIPT_TYPE_ARGUMENTS_NO_PARENS, }); } @@ -2050,7 +2043,7 @@ export function parseTemplateElement( } else { parser.addDiagnostic({ index: parser.state.invalidTemplateEscapePosition, - message: 'Invalid escape sequence in template', + description: descriptions.JS_PARSER.INVALID_TEMPLATE_ESCAPE, }); } } @@ -2174,7 +2167,7 @@ export function parseObjectExpression( } else { if (parser.hasPrecedingLineBreak()) { parser.addDiagnostic({ - message: 'There shouldn\'t be any newlines between async and the rest of the function', + description: descriptions.JS_PARSER.ASYNC_OBJECT_METHOD_LINE_BREAK, }); } @@ -2262,7 +2255,7 @@ export function parseObjectPattern( if (firstRestLocation !== undefined) { parser.addDiagnostic({ loc: argument.loc, - message: 'Cannot have multiple rest elements when destructuring', + description: descriptions.JS_PARSER.MULTIPLE_DESTRUCTURING_RESTS, }); } @@ -2273,7 +2266,7 @@ export function parseObjectPattern( if (parser.match(tt.comma) && parser.lookaheadState().tokenType === tt.braceR) { parser.addDiagnostic({ - message: 'A trailing comma is not permitted after the rest element', + description: descriptions.JS_PARSER.TRAILING_COMMA_AFTER_REST, }); parser.eat(tt.comma); break; @@ -2304,7 +2297,7 @@ export function parseObjectPattern( if (prop.type !== 'BindingObjectPatternProperty') { parser.addDiagnostic({ - message: 'Invalid property node for object pattern', + description: descriptions.JS_PARSER.INVALID_OBJECT_PATTERN_PROP, loc: prop.loc, }); continue; @@ -2365,19 +2358,19 @@ export function checkGetterSetterParamCount( if (head.rest !== undefined || head.params.length !== 0) { parser.addDiagnostic({ loc: method.loc, - message: 'getter should have no parameters', + description: descriptions.JS_PARSER.GETTER_WITH_PARAMS, }); } } else if (kind === 'set') { if (head.rest !== undefined) { parser.addDiagnostic({ loc: head.rest.loc, - message: 'setter function argument must not be a rest parameter', + description: descriptions.JS_PARSER.SETTER_WITH_REST, }); } else if (head.params.length !== 1) { parser.addDiagnostic({ loc: method.loc, - message: 'setter should have exactly one param', + description: descriptions.JS_PARSER.SETTER_NOT_ONE_PARAM, }); } } @@ -2406,7 +2399,7 @@ export function parseObjectMethod( if (isAsync || isGenerator || parser.match(tt.parenL)) { if (isPattern) { parser.addDiagnostic({ - message: 'Object methods aren\'t allowed in object patterns', + description: descriptions.JS_PARSER.OBJECT_METHOD_IN_PATTERN, }); } @@ -2435,13 +2428,13 @@ export function parseObjectMethod( if (isGetterOrSetterMethod(parser, key, key.value, isPattern)) { if (isAsync) { parser.addDiagnostic({ - message: 'An object setter/getter can\'t be async', + description: descriptions.JS_PARSER.ASYNC_GETTER_SETTER, }); } if (isGenerator) { parser.addDiagnostic({ - message: 'An object setter/getter can\'t be a generator', + description: descriptions.JS_PARSER.GENERATOR_GETTER_SETTER, }); } @@ -2573,7 +2566,7 @@ export function parseObjectPropertyValue( if (key.variance !== undefined) { parser.addDiagnostic({ loc: key.variance.loc, - message: 'variance not allowed here', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -2609,7 +2602,7 @@ export function parseObjectPropertyValue( 'BindingObjectPatternProperty') { parser.addDiagnostic({ loc: typeParameters.loc, - message: 'Object property cannot have type parameters', + description: descriptions.JS_PARSER.OBJECT_PROPERTY_WITH_TYPE_PARAMETERS, }); return node; } @@ -2777,7 +2770,7 @@ export function parseArrowExpression( if (parser.state.yieldInPossibleArrowParameters) { parser.addDiagnostic({ start: parser.state.yieldInPossibleArrowParameters, - message: 'Yield cannot be used as name inside a generator function', + description: descriptions.JS_PARSER.YIELD_NAME_IN_GENERATOR, }); } @@ -3008,7 +3001,7 @@ export function checkFunctionNameAndParams( if (firstDirective !== undefined && firstDirective.value === 'use strict') { parser.addDiagnostic({ loc: firstDirective.loc, - message: 'Illegal \'use strict\' directive in function with non-simple parameter list', + description: descriptions.JS_PARSER.STRICT_DIRECTIVE_IN_NON_SIMPLE_PARAMS, }); } } @@ -3041,7 +3034,7 @@ export function checkFunctionNameAndParams( if (_isStrictBody && param.type !== 'BindingIdentifier') { parser.addDiagnostic({ loc: param.loc, - message: 'Non-simple parameter in strict mode', + description: descriptions.JS_PARSER.NON_SIMPLE_PARAM_IN_EXPLICIT_STRICT_FUNCTION, }); } checkLVal(parser, param, true, clashes, 'function parameter list'); @@ -3287,7 +3280,7 @@ export function parseIdentifierName( } } else { parser.addDiagnostic({ - message: 'Expected an identifier here', + description: descriptions.JS_PARSER.EXPECTED_IDENTIFIER, }); name = ''; } @@ -3320,28 +3313,28 @@ export function checkReservedWord( if (parser.inScope('GENERATOR') && word === 'yield') { parser.addDiagnostic({ loc, - message: 'Can not use \'yield\' as identifier inside a generator', + description: descriptions.JS_PARSER.YIELD_NAME_IN_GENERATOR, }); } if (parser.inScope('ASYNC') && word === 'await') { parser.addDiagnostic({ loc, - message: 'Can not use keyword \'await\' outside an async function', + description: descriptions.JS_PARSER.AWAIT_NAME_IN_ASYNC, }); } if (parser.inScope('CLASS_PROPERTY') && word === 'arguments') { parser.addDiagnostic({ loc, - message: '\'arguments\' is not allowed in class field initializer', + description: descriptions.JS_PARSER.ARGUMENTS_IN_CLASS_FIELD, }); } if (checkKeywords && isKeyword(word)) { parser.addDiagnostic({ loc, - message: `Unexpected keyword '${word}'`, + description: descriptions.JS_PARSER.UNEXPECTED_KEYWORD(word), }); } @@ -3360,12 +3353,12 @@ export function checkReservedWord( if (!parser.inScope('ASYNC') && word === 'await') { parser.addDiagnostic({ loc, - message: 'Can not use keyword \'await\' outside an async function', + description: descriptions.JS_PARSER.AWAIT_OUTSIDE_ASYNC, }); } else { parser.addDiagnostic({ loc, - message: `${word} is a reserved word`, + description: descriptions.JS_PARSER.RESERVED_WORD(word), }); } } @@ -3379,7 +3372,7 @@ export function parseAwait(parser: JSParser): AwaitExpression { if (!parser.inScope('ASYNC')) { parser.addDiagnostic({ - message: 'Can\'t use await outside of an async function', + description: descriptions.JS_PARSER.AWAIT_OUTSIDE_ASYNC, }); } @@ -3388,14 +3381,14 @@ export function parseAwait(parser: JSParser): AwaitExpression { if (parser.inScope('PARAMETERS')) { parser.addDiagnostic({ - message: 'await is not allowed in async function parameters', + description: descriptions.JS_PARSER.AWAIT_IN_ASYNC_PARAMS, }); } if (parser.eat(tt.star)) { parser.addDiagnostic({ start, - message: 'await* has been removed from the async functions proposal. Use Promise.all() instead.', + description: descriptions.JS_PARSER.AWAIT_STAR, }); } @@ -3414,7 +3407,7 @@ export function parseYield(parser: JSParser, noIn?: boolean): YieldExpression { if (parser.inScope('PARAMETERS')) { parser.addDiagnostic({ start, - message: 'yield is not allowed in generator parameters', + description: descriptions.JS_PARSER.YIELD_IN_GENERATOR_PARAMS, }); } @@ -3539,7 +3532,7 @@ function parseImportCall(parser: JSParser): ImportCall { if (parser.match(tt.parenR)) { parser.addDiagnostic({ - message: 'import() requires exactly one argument', + description: descriptions.JS_PARSER.IMPORT_EXACT_ARGUMENTS, }); argument = toReferenceIdentifier(parser, parser.createUnknownIdentifier( @@ -3561,14 +3554,14 @@ function parseImportCall(parser: JSParser): ImportCall { parser.addDiagnostic({ start: parser.state.lastStartPos, end: parser.state.lastEndPos, - message: 'Trailing comma is disallowed inside import(...) arguments', + description: descriptions.JS_PARSER.IMPORT_TRAILING_COMMA, }); } if (argument.type === 'SpreadElement') { parser.addDiagnostic({ loc: argument.loc, - message: 'Spread is not allowed in import()', + description: descriptions.JS_PARSER.IMPORT_SPREAD, }); } @@ -3587,7 +3580,7 @@ function parseSuper(parser: JSParser): Super { if (!parser.inScope('METHOD') && !parser.inScope('CLASS_PROPERTY') && parser.sourceType !== 'template') { parser.addDiagnostic({ - message: 'super is only allowed in object methods and classes', + description: descriptions.JS_PARSER.SUPER_OUTSIDE_METHOD, }); } @@ -3598,7 +3591,7 @@ function parseSuper(parser: JSParser): Super { tt.dot, )) { parser.addDiagnostic({ - message: 'Invalid super suffix operator', + description: descriptions.JS_PARSER.INVALID_SUPER_SUFFIX, }); } @@ -3610,14 +3603,7 @@ function parseSuper(parser: JSParser): Super { ) !== 'derived') && parser.sourceType !== 'template') { parser.addDiagnostic({ loc, - message: 'super() is only valid inside a class constructor of a subclass', - advice: [ - { - type: 'log', - category: 'info', - message: 'Maybe a typo in the method name (\'constructor\') or not extending another class?', - }, - ], + description: descriptions.JS_PARSER.SUPER_CALL_OUTSIDE_CONSTRUCTOR, }); } diff --git a/packages/@romejs/js-parser/parser/flow.ts b/packages/@romejs/js-parser/parser/flow.ts index 03f4e811143..4a31d219945 100644 --- a/packages/@romejs/js-parser/parser/flow.ts +++ b/packages/@romejs/js-parser/parser/flow.ts @@ -80,6 +80,7 @@ import { parseTypeLiteralAnnotation, } from './index'; import {get0} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; const primitiveTypes = [ 'any', @@ -112,7 +113,7 @@ function checkNotUnderscore(parser: JSParser, id: Identifier) { if (id.name === '_') { parser.addDiagnostic({ loc: id.loc, - message: '`_` is only allowed as a type argument to call or new', + description: descriptions.JS_PARSER.FLOW_BAD_UNDERSCORE_NAME, }); } } @@ -198,7 +199,7 @@ function parseFlowPredicate( ) - 1) { parser.addDiagnostic({ start: moduloPos, - message: 'Spaces between \xb4%\xb4 and \xb4checks\xb4 are not allowed here.', + description: descriptions.JS_PARSER.FLOW_SPACE_BETWEEN_PERCENT_CHECKS, }); } @@ -286,7 +287,7 @@ function parseFlowDeclareFunction( if (predicate !== undefined && predicate.type === 'FlowInferredPredicate') { parser.addDiagnostic({ loc: predicate.loc, - message: 'Predicate function declarations need to declare a predicate expression', + description: descriptions.JS_PARSER.FLOW_UNINFERRABLE_PREDICATE_ON_FUNCTION, }); } @@ -336,7 +337,7 @@ export function parseFlowDeclare( } else { if (insideModule) { parser.addDiagnostic({ - message: '`declare module` cannot be used inside another `declare module`', + description: descriptions.JS_PARSER.FLOW_DECLARE_MODULE_IN_DECLARE_MODULE, }); } return parseFlowDeclareModule(parser, start); @@ -360,7 +361,7 @@ export function parseFlowDeclare( } parser.addDiagnostic({ - message: 'Unknown start to Flow declaration', + description: descriptions.JS_PARSER.FLOW_UNKNOWN_DECLARATION_START, }); // Fake node @@ -419,7 +420,7 @@ function parseFlowDeclareModule( const lookahead = parser.lookaheadState(); if (lookahead.tokenValue !== 'type' && lookahead.tokenValue !== 'typeof') { parser.addDiagnostic({ - message: 'Imports within a `declare module` body must always be `import type` or `import typeof`', + description: descriptions.JS_PARSER.FLOW_IMPORT_KINDLESS_IN_DECLARE_MODULE, }); } parser.next(); @@ -427,7 +428,7 @@ function parseFlowDeclareModule( } else { if (!parser.expectContextual( 'declare', - 'Only declares and type imports are allowed inside declare module', + descriptions.JS_PARSER.FLOW_DECLARE_MODULE_INVALID_CHILD, )) { break; } @@ -447,15 +448,13 @@ function parseFlowDeclareModule( let kind: undefined | 'commonjs' | 'es'; let hasModuleExport = false; - const errorMessage = - 'Found both `declare module.exports` and `declare export` in the same module. Modules can only have 1 since they are either an ES module or they are a CommonJS module'; for (const bodyElement of body) { if (isEsModuleType(bodyElement)) { if (kind === 'commonjs') { parser.addDiagnostic({ loc: bodyElement.loc, - message: errorMessage, + description: descriptions.JS_PARSER.FLOW_MIXED_DECLARE_EXPORTS, }); } kind = 'es'; @@ -463,14 +462,14 @@ function parseFlowDeclareModule( if (hasModuleExport) { parser.addDiagnostic({ loc: bodyElement.loc, - message: 'Duplicate `declare module.exports` statement', + description: descriptions.JS_PARSER.FLOW_DUPLICATE_DECLARE_MODULE_EXPORTS, }); } if (kind === 'es') { parser.addDiagnostic({ loc: bodyElement.loc, - message: errorMessage, + description: descriptions.JS_PARSER.FLOW_MIXED_DECLARE_EXPORTS, }); } @@ -518,7 +517,10 @@ function parseExportLocalDeclaration( const label = String(parser.state.tokenValue); const suggestion = String(exportSuggestions.get(label)); parser.addDiagnostic({ - message: `\`declare export ${label}\` is not supported. Use \`${suggestion}\` instead`, + description: descriptions.JS_PARSER.FLOW_DECLARE_EXPORT_UNSUPPORTED( + label, + suggestion, + ), }); } @@ -562,7 +564,7 @@ function parseExportLocalDeclaration( parser.addDiagnostic({ start, - message: 'No valid start for Flow declare export declaration found', + description: descriptions.JS_PARSER.FLOW_UNKNOWN_DECLARE_EXPORT_START, }); // Fake node @@ -750,7 +752,7 @@ export function checkReservedType( if (primitiveTypes.includes(word)) { parser.addDiagnostic({ loc, - message: `Cannot overwrite primitive type ${word}`, + description: descriptions.JS_PARSER.FLOW_RESERVED_TYPE(word), }); } } @@ -847,7 +849,7 @@ function parseFlowTypeParameter( if (parser.match(tt.eq)) { if (!allowDefault) { parser.addDiagnostic({ - message: 'Default type parameters arent allowed here', + description: descriptions.JS_PARSER.FLOW_DISALLOW_DEFAULT_TYPE_PARAMETER, }); } @@ -855,7 +857,7 @@ function parseFlowTypeParameter( def = parseFlowType(parser); } else if (requireDefault) { parser.addDiagnostic({ - message: 'Type parameter declaration needs a default, since a preceding type parameter declaration has a default.', + description: descriptions.JS_PARSER.FLOW_DEFAULT_TYPE_PARAMETER_REQUIRED, }); } @@ -1096,7 +1098,7 @@ function parseFlowObjectType( if (variance) { parser.addDiagnostic({ loc: variance.loc, - message: 'Variance not allowed', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -1117,7 +1119,7 @@ function parseFlowObjectType( if (variance) { parser.addDiagnostic({ loc: variance.loc, - message: 'Variance not allowed', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -1198,7 +1200,7 @@ function parseFlowObjectTypeProperty( if (parser.match(tt.ellipsis)) { if (!allowSpread) { parser.addDiagnostic({ - message: 'Spread operator cannot appear in class or interface definitions', + description: descriptions.JS_PARSER.FLOW_DISALLOWED_SPREAD, }); } @@ -1209,7 +1211,7 @@ function parseFlowObjectTypeProperty( if (variance) { parser.addDiagnostic({ loc: variance.loc, - message: 'Spread properties cannot have variance', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -1223,19 +1225,19 @@ function parseFlowObjectTypeProperty( } parser.addDiagnostic({ - message: 'Explicit inexact syntax is only allowed inside inexact objects', + description: descriptions.JS_PARSER.FLOW_INEXACT_SYNTAX_NOT_ALLOWED, }); } if (parser.match(tt.braceBarR)) { parser.addDiagnostic({ - message: 'Explicit inexact syntax cannot appear inside an explicit exact object type', + description: descriptions.JS_PARSER.FLOW_INEXACT_CANNOT_APPEAR_IN_EXPLICIT_EXACT, }); } if (isInexactToken) { parser.addDiagnostic({ - message: 'Explicit inexact syntax must appear at the end of an inexact object', + description: descriptions.JS_PARSER.FLOW_INEXACT_MUST_BE_AT_END, }); } @@ -1258,7 +1260,7 @@ function parseFlowObjectTypeProperty( if (variance) { parser.addDiagnostic({ loc: variance.loc, - message: 'Type methods can\'t have variance', + description: descriptions.JS_PARSER.ILLEGAL_VARIANCE, }); } @@ -1655,7 +1657,7 @@ function parseFlowPrimaryType(parser: JSParser): AnyFlowPrimary { } parser.addDiagnostic({ - message: 'Unknown flow primarty type start', + description: descriptions.JS_PARSER.FLOW_UNKNOWN_PRIMARY_START, }); // Fake node @@ -1729,7 +1731,7 @@ function parseFlowIntersectionType(parser: JSParser): AnyFlowPrimary { function eatUnionBitwise(parser: JSParser) { if (parser.match(tt.logicalOR)) { parser.addDiagnostic({ - message: 'Unexpected ||, did you mean just |?', + description: descriptions.JS_PARSER.CONFUSED_OR, }); parser.next(); } else { @@ -1851,7 +1853,7 @@ export function parseAsyncArrowWithFlowTypeParameters( const {returnType, valid, predicate} = parseArrowHead(parser); if (!valid) { parser.addDiagnostic({ - message: 'Invalid async arrow with type parameters', + description: descriptions.JS_PARSER.FLOW_INVALID_ASYNC_ARROW_WITH_TYPE_PARAMS, }); return undefined; } diff --git a/packages/@romejs/js-parser/parser/jsx.ts b/packages/@romejs/js-parser/parser/jsx.ts index 2c38bd44e5d..6863d0db6a0 100644 --- a/packages/@romejs/js-parser/parser/jsx.ts +++ b/packages/@romejs/js-parser/parser/jsx.ts @@ -27,7 +27,7 @@ import { parseTSTypeArguments, parseStringLiteral, } from './index'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {isValidIdentifierName} from '@romejs/js-ast-utils'; // Indicates whether we should create a JSXIdentifier or a JSXReferenceIdentifier @@ -37,7 +37,9 @@ function isHTMLTagName(tagName: string): boolean { } // Transforms JSX element name to string. -function getQualifiedJSXName(node: JSXElement['name'] | JSXIdentifier): string { +function getQualifiedJSXName( + node: undefined | JSXElement['name'] | JSXIdentifier, +): string { if (node === undefined) { return ''; } @@ -67,7 +69,7 @@ function parseJSXIdentifier(parser: JSParser): JSXIdentifier { name = parser.state.tokenType.keyword; } else { parser.addDiagnostic({ - message: 'Unknown JSX identifier token', + description: descriptions.JS_PARSER.JSX_UNKNOWN_IDENTIFIER_TOKEN, }); name = ''; } @@ -141,7 +143,7 @@ function parseJSXAttributeValue( if (node.expression.type === 'JSXEmptyExpression') { parser.addDiagnostic({ loc: node.loc, - message: 'JSX attributes must only be assigned a non-empty expression', + description: descriptions.JS_PARSER.JSX_EMPTY_ATTRIBUTE_VALUE, }); } return node; @@ -155,7 +157,7 @@ function parseJSXAttributeValue( default: { parser.addDiagnostic({ - message: 'JSX value should be either an expression or a quoted JSX text', + description: descriptions.JS_PARSER.JSX_INVALID_ATTRIBUTE_VALUE, }); return parser.finishNode(parser.getPosition(), { type: 'StringLiteral', @@ -278,7 +280,7 @@ function parseJSXOpeningElementAt( if (parser.isRelational('<')) { if (!parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ - message: 'JSX element type arguments are only allowed in TS', + description: descriptions.JS_PARSER.JSX_ELEM_TYPE_ARGUMENTS_OUTSIDE_TS, }); } @@ -295,7 +297,7 @@ function parseJSXOpeningElementAt( const selfClosing = parser.eat(tt.slash); if (!parser.eat(tt.jsxTagEnd)) { parser.addDiagnostic({ - message: 'Unclosed JSX element open', + description: descriptions.JS_PARSER.JSX_UNCLOSED_SELF_CLOSING_TAG, }); } return { @@ -311,13 +313,7 @@ function parseJSXOpeningElementAt( function parseJSXClosingElementAt( parser: JSParser, ): undefined | JSXElement['name'] { - if (parser.match(tt.jsxTagEnd)) { - if (!parser.eat(tt.jsxTagEnd)) { - parser.addDiagnostic({ - message: 'Unclosed JSX fragment close', - }); - } - + if (parser.eat(tt.jsxTagEnd)) { return undefined; } @@ -325,69 +321,13 @@ function parseJSXClosingElementAt( if (!parser.eat(tt.jsxTagEnd)) { parser.addDiagnostic({ - message: 'Unclosed JSX element close', + description: descriptions.JS_PARSER.JSX_UNCLOSED_CLOSING_TAG, }); } return name; } -function getJSXOpenElementAdvice( - parser: JSParser, - def: OpeningElementDef, -): PartialDiagnosticAdvice { - let message = 'Originated from this opening tag'; - - if (def.name !== undefined) { - message = `Originated from opening tag of ${getQualifiedJSXName( - def.name, - )}`; - } - - const {loc} = def; - return [ - { - type: 'log', - category: 'info', - message, - }, - { - type: 'frame', - filename: parser.filename, - start: loc.start, - end: loc.end, - }, - ]; -} - -function getJSXCloseElementAdvice( - parser: JSParser, - name: undefined | JSXElement['name'], - loc: SourceLocation, -): PartialDiagnosticAdvice { - let message; - if (name === undefined) { - message = 'But found a closing fragment instead'; - } else { - message = - `But found a closing tag of ${getQualifiedJSXName(name)} instead`; - } - - return [ - { - type: 'log', - category: 'info', - message, - }, - { - type: 'frame', - filename: parser.filename, - start: loc.start, - end: loc.end, - }, - ]; -} - function recoverFromUnclosedJSX(parser: JSParser) { // jsxOpenTag parser.state.context.pop(); @@ -442,15 +382,19 @@ function parseJSXElementAt( case tt.eof: parser.addDiagnostic({ - message: 'Unclosed JSX element', - advice: getJSXOpenElementAdvice(parser, openingDef), + description: descriptions.JS_PARSER.JSX_UNCLOSED_ELEMENT( + getQualifiedJSXName(openingDef.name), + openingDef.loc, + ), }); break contents; default: parser.addDiagnostic({ - message: 'Unknown JSX children start', - advice: getJSXOpenElementAdvice(parser, openingDef), + description: descriptions.JS_PARSER.JSX_UNKNOWN_CHILD_START( + getQualifiedJSXName(openingDef.name), + openingDef.loc, + ), }); // We don't need to do it for the tt.eof case above because nothing will ever be parsed after @@ -470,8 +414,10 @@ function parseJSXElementAt( if (openingDef.name === undefined && closingName !== undefined) { parser.addDiagnostic({ loc: openingDef.loc, - message: `Expected JSX closing fragment tag`, - advice: getJSXCloseElementAdvice(parser, closingName, closingNameLoc), + description: descriptions.JS_PARSER.JSX_EXPECTED_CLOSING_FRAGMENT_TAG( + getQualifiedJSXName(openingDef.name), + openingDef.loc, + ), }); } @@ -479,10 +425,10 @@ function parseJSXElementAt( if (openingDef.name !== undefined && closingName === undefined) { parser.addDiagnostic({ loc: openingDef.loc, - message: `Expected a corresponding JSX closing tag for ${getQualifiedJSXName( - openingDef.name, - )}`, - advice: getJSXCloseElementAdvice(parser, closingName, closingNameLoc), + description: descriptions.JS_PARSER.JSX_EXPECTED_CLOSING_TAG( + getQualifiedJSXName(openingDef.name), + openingDef.loc, + ), }); } @@ -493,10 +439,10 @@ function parseJSXElementAt( )) { parser.addDiagnostic({ loc: openingDef.loc, - message: `Expected a corresponding JSX closing tag for ${getQualifiedJSXName( - openingDef.name, - )}`, - advice: getJSXCloseElementAdvice(parser, closingName, closingNameLoc), + description: descriptions.JS_PARSER.JSX_EXPECTED_CLOSING_TAG( + getQualifiedJSXName(openingDef.name), + openingDef.loc, + ), }); } } @@ -525,8 +471,7 @@ function parseJSXElementAt( function checkAccidentalFragment(parser: JSParser) { if (parser.match(tt.relational) && parser.state.tokenValue === '<') { parser.addDiagnostic({ - message: `Adjacent JSX elements must be wrapped in an enclosing tag. - Did you want a JSX fragment <>...?`, + description: descriptions.JS_PARSER.UNWRAPPED_ADJACENT_JHX, }); } } @@ -549,35 +494,11 @@ export function parseJSXElement(parser: JSParser): JSXElement | JSXFragment { if (!parser.isSyntaxEnabled('jsx')) { if (parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ - message: 'JSX isn\'t allowed in regular TypeScript files', - advice: [ - { - type: 'log', - category: 'info', - message: 'Change the file extension to .tsx to enable JSX support', - }, - ], + description: descriptions.JS_PARSER.JSX_IN_TS_EXTENSION, }); } else { parser.addDiagnostic({ - message: 'JSX syntax isn\'t enabled', - advice: [ - { - type: 'log', - category: 'info', - message: 'Are you using TypeScript? Change the file extension to .tsx', - }, - { - type: 'log', - category: 'info', - message: 'Are you using Flow? Add a @flow comment annotation to the top of the file', - }, - { - type: 'log', - category: 'info', - message: 'Not using either? Change the file extension to .jsx', - }, - ], + description: descriptions.JS_PARSER.JSX_DISABLED, }); } } diff --git a/packages/@romejs/js-parser/parser/lval.ts b/packages/@romejs/js-parser/parser/lval.ts index 113b15f5978..c58330688f3 100644 --- a/packages/@romejs/js-parser/parser/lval.ts +++ b/packages/@romejs/js-parser/parser/lval.ts @@ -41,7 +41,7 @@ import { parseTSAccessModifier, hasTSModifier, } from './index'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import {get0} from '@romejs/ob1'; import { parseBindingIdentifier, @@ -133,7 +133,7 @@ export function toAssignmentPattern( } else { parser.addDiagnostic({ loc: arg.loc, - message: 'Invalid rest operator\'s argument', + description: descriptions.JS_PARSER.INVALID_OBJECT_REST_ARGUMENT, }); } continue; @@ -169,7 +169,7 @@ export function toAssignmentPattern( if (node.operator !== '=') { parser.addDiagnostic({ loc: parser.getLoc(node.left), - message: 'Only \'=\' operator can be used for specifying default value.', + description: descriptions.JS_PARSER.INVALID_ASSIGNMENT_PATTERN_OPERATOR, }); } @@ -184,11 +184,11 @@ export function toAssignmentPattern( default: { - const message = - `Invalid left-hand side in ${contextDescription} ${node.type}`; parser.addDiagnostic({ loc: node.loc, - message, + description: descriptions.JS_PARSER.INVALID_LEFT_HAND_SIDE( + contextDescription, + ), }); return toAssignmentIdentifier(parser, parser.createUnknownIdentifier( contextDescription, @@ -217,7 +217,7 @@ export function toTargetAssignmentPattern( default: parser.addDiagnostic({ loc: node.loc, - message: 'Not a valid assignment target', + description: descriptions.JS_PARSER.INVALID_ASSIGNMENT_TARGET, }); return { type: 'AssignmentIdentifier', @@ -276,7 +276,7 @@ export function toBindingPattern( if (binding.type === 'MemberExpression') { parser.addDiagnostic({ loc: node.loc, - message: 'Binding member expression', + description: descriptions.JS_PARSER.BINDING_MEMBER_EXPRESSION, }); return { @@ -375,12 +375,9 @@ export function toAssignmentObjectProperty( switch (prop.type) { case 'ObjectMethod': { - const error = prop.kind === 'get' || prop.kind === 'set' - ? 'Object pattern can\'t contain getter or setter' : 'Object pattern can\'t contain methods'; - parser.addDiagnostic({ loc: prop.key.loc, - message: error, + description: descriptions.JS_PARSER.OBJECT_PATTERN_CANNOT_CONTAIN_METHODS, }); const fakeProp: AssignmentObjectPatternProperty = { @@ -419,7 +416,7 @@ export function toAssignmentObjectProperty( default: parser.addDiagnostic({ loc: prop.loc, - message: 'Not a valid assignment object pattern property', + description: descriptions.JS_PARSER.INVALID_OBJECT_PATTERN_PROPERTY, }); return { type: 'AssignmentObjectPatternProperty', @@ -499,7 +496,7 @@ export function toAssignableList( if (expr.type === 'TSAsExpression' || expr.type === 'TSTypeAssertion') { parser.addDiagnostic({ loc: expr.loc, - message: 'Unexpected type cast in parameter position', + description: descriptions.JS_PARSER.TS_UNEXPECTED_CAST_IN_PARAMETER_POSITION, }); } } @@ -629,21 +626,21 @@ export function toReferencedItem( if (parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ loc: expr.loc, - message: 'Flow type cast expressions aren\'t allowed in TypeScript', + description: descriptions.JS_PARSER.FLOW_TYPE_CAST_IN_TS, }); } if (!parser.isParenthesized(expr) && (multiple || !isParenthesizedExpr)) { parser.addDiagnostic({ loc: expr.loc, - message: 'The type cast expression is expected to be wrapped with parentheses', + description: descriptions.JS_PARSER.TYPE_CAST_EXPECTED_PARENS, }); } if (expr.optional) { parser.addDiagnostic({ loc: expr.loc, - message: 'Type cast expressions cannot be optional. Did you mean for this to be a function parameter?', + description: descriptions.JS_PARSER.TYPE_CAST_CANNOT_BE_OPTIONAL, }); } @@ -652,7 +649,7 @@ export function toReferencedItem( if (typeAnnotation === undefined) { parser.addDiagnostic({ loc: expr.loc, - message: 'Type cast expression has no type annotation. Did you mean for this to be a function parameter?', + description: descriptions.JS_PARSER.TYPE_CAST_WITHOUT_ANNOTATION, }); return expression; } @@ -679,14 +676,11 @@ export function filterSpread( for (let i = 0; i < elems.length; i++) { const elem = elems[i]; if (elem.type === 'SpreadElement') { - parser.addDiagnostic({ - message: 'Is this even ever possible?', - loc: elem.loc, - }); - elems[i] = toReferenceIdentifier(parser, parser.createUnknownIdentifier( 'spread substitute', )); + + throw new Error('Is this even ever possible?'); } } // @ts-ignore Technically wrong but we removed all SpreadElement @@ -806,7 +800,9 @@ export function parseBindingList( } else { if (!parser.eat(tt.comma)) { parser.addDiagnostic({ - message: `Expected a comma to separate items in ${openContext.name}`, + description: descriptions.JS_PARSER.EXPECTED_COMMA_SEPARATOR( + openContext.name, + ), }); break; } @@ -873,7 +869,7 @@ export function parseBindingListItem( if (accessibility !== undefined || readonly) { if (!parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ - message: 'Accessibility and readonly syntax found but TS is not enabled', + description: descriptions.JS_PARSER.TS_DISABLED_BUT_ACCESSIBILITY_OR_READONLY, }); } @@ -881,7 +877,7 @@ export function parseBindingListItem( 'BindingAssignmentPattern') { parser.addDiagnostic({ start, - message: 'A parameter property may not be declared using a binding pattern.', + description: descriptions.JS_PARSER.TS_PARAMETER_PROPERTY_BINDING_PATTERN, }); } @@ -910,7 +906,7 @@ export function parseBindingListItemTypes( if (param.type !== 'BindingIdentifier') { parser.addDiagnostic({ loc: param.loc, - message: 'A binding pattern parameter cannot be optional in an implementation signature.', + description: descriptions.JS_PARSER.TYPE_BINDING_PARAMETER_OPTIONAL, }); } @@ -961,7 +957,7 @@ export function parseMaybeDefault( ).start.index) { parser.addDiagnostic({ loc: target.meta.typeAnnotation.loc, - message: 'Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`', + description: descriptions.JS_PARSER.TYPE_ANNOTATION_AFTER_ASSIGNMENT, }); } @@ -994,25 +990,11 @@ export function checkLVal( // Verify that nodes aren't parenthesized if (parser.isParenthesized(expr) && !ALLOWED_PARENTHESIZED_LVAL_TYPES.includes(expr.type)) { - let adviceMsg; - if (expr.type === 'BindingObjectPattern') { - adviceMsg = 'Did you use `({a}) = 0` instead of `({a} = 0)`?'; - } else if (expr.type === 'BindingArrayPattern') { - adviceMsg = 'Did you use `([a]) = 0` instead of `([a] = 0)`?'; - } - - const advice: PartialDiagnosticAdvice = []; - if (adviceMsg !== undefined) { - advice.push({ - type: 'log', - category: 'info', - message: adviceMsg, - }); - } - parser.addDiagnostic({ - message: 'Invalid parenthesized binding', - advice, + description: descriptions.JS_PARSER.INVALID_PARENTEHSIZED_LVAL( + expr.type === 'BindingObjectPattern' ? 'object' : expr.type === + 'BindingArrayPattern' ? 'array' : undefined, + ), loc: expr.loc, }); } @@ -1049,7 +1031,7 @@ export function checkLVal( )) { parser.addDiagnostic({ loc: expr.loc, - message: `${expr.name} is a reserved word`, + description: descriptions.JS_PARSER.RESERVED_WORD(expr.name), }); } @@ -1059,23 +1041,12 @@ export function checkLVal( if (clash === undefined) { checkClashes.set(expr.name, expr); } else { - const loc = parser.getLoc(clash); parser.addDiagnostic({ + description: descriptions.JS_PARSER.ARGUMENT_CLASH_IN_STRICT( + expr.name, + expr.loc, + ), loc: expr.loc, - message: 'Argument name clash in strict mode', - advice: [ - { - type: 'log', - category: 'info', - message: 'Collides with this existing definition', - }, - { - type: 'frame', - filename: parser.filename, - start: loc.start, - end: loc.end, - }, - ], }); } } @@ -1144,7 +1115,7 @@ export function checkToRestConversion( if (VALID_REST_ARGUMENT_TYPES.includes(node.argument.type) === false) { parser.addDiagnostic({ loc: node.argument.loc, - message: 'Invalid rest operator\'s argument', + description: descriptions.JS_PARSER.REST_INVALID_ARGUMENT, }); } } @@ -1166,7 +1137,7 @@ export function raiseRestNotLast( parser.addDiagnostic({ start, loc, - message: `The rest element has to be the last element when destructuring`, + description: descriptions.JS_PARSER.DESTRUCTURING_REST_ELEMENT_NOT_LAST, }); } diff --git a/packages/@romejs/js-parser/parser/modules.ts b/packages/@romejs/js-parser/parser/modules.ts index 6fca93ca8f4..7ea16a582bf 100644 --- a/packages/@romejs/js-parser/parser/modules.ts +++ b/packages/@romejs/js-parser/parser/modules.ts @@ -62,6 +62,7 @@ import { parseExportDefaultFunctionDeclaration, parseExportDefaultClassDeclaration, } from './index'; +import {descriptions} from '@romejs/diagnostics'; export type ParseExportResult = | AnyStatement @@ -157,7 +158,7 @@ export function parseExport(parser: JSParser, start: Position): ParseExportResul parser.addDiagnostic({ start: next.startPos, end: next.endPos, - message: 'Started with `export async` so we expected to receive an async function but no function keyword was found', + description: descriptions.JS_PARSER.EXPORT_ASYNC_NO_FUNCTION_KEYWORD, }); declaration = undefined; specifiers = []; @@ -184,7 +185,7 @@ export function parseExport(parser: JSParser, start: Position): ParseExportResul declaration.type !== 'FlowOpaqueType') { parser.addDiagnostic({ loc: declaration.loc, - message: 'Invalid export declaration', + description: descriptions.JS_PARSER.INVALID_EXPORT_DECLARATION, }); return declaration; } @@ -272,7 +273,7 @@ function parseExportDefaultExpression( if (parser.match(tt._const) || parser.match(tt._var) || isLetStart(parser)) { parser.addDiagnostic({ - message: 'Only expressions, functions or classes are allowed as the `default` export.', + description: descriptions.JS_PARSER.INVALID_EXPORT_DEFAULT, }); } @@ -393,7 +394,7 @@ function parseExportFrom( parser.addDiagnostic({ loc: expr.loc, - message: 'Import from only allows strings', + description: descriptions.JS_PARSER.EXPORT_FROM_NOT_STRING, }); source = { @@ -404,7 +405,7 @@ function parseExportFrom( } } else if (expect) { parser.addDiagnostic({ - message: 'Expected `from` for an export node', + description: descriptions.JS_PARSER.EXPORT_MISSING_FROM, }); source = { @@ -465,7 +466,7 @@ function parseExportNamespace( } { if (exportKind === 'type') { parser.addDiagnostic({ - message: 'Can\'t have a type export namespacer specifier', + description: descriptions.JS_PARSER.EXPORT_TYPE_NAMESPACE, }); } @@ -585,21 +586,7 @@ function checkDuplicateExports( if (existing !== undefined) { parser.addDiagnostic({ loc: node.loc, - message: name === 'default' - ? 'Only one default export allowed per module.' : `\`${name}\` has already been exported. Exported identifiers must be unique.`, - advice: [ - { - type: 'log', - category: 'info', - message: 'First defined here', - }, - { - type: 'frame', - filename: existing.filename, - start: existing.start, - end: existing.end, - }, - ], + description: descriptions.JS_PARSER.DUPLICATE_EXPORT(name, existing), }); } @@ -672,7 +659,7 @@ export function parseImport(parser: JSParser, start: Position): ParseImportResul source = parseStringLiteral(parser); } else { parser.addDiagnostic({ - message: 'import missing a source', + description: descriptions.JS_PARSER.IMPORT_MISSING_SOURCE, }); source = parser.finishNode(start, { @@ -754,7 +741,7 @@ function parseImportSpecifiers( if (importKind === 'type' && lh.tokenType === tt.star) { parser.addDiagnostic({ start: lh.startPos, - message: 'import * is not allowed', + description: descriptions.JS_PARSER.IMPORT_TYPE_STAR, }); } @@ -825,7 +812,7 @@ function parseImportSpecifiers( // Detect an attempt to deep destructure if (parser.eat(tt.colon)) { parser.addDiagnostic({ - message: 'ES2015 named imports do not destructure. Use another statement for destructuring after the import.', + description: descriptions.JS_PARSER.DESTRUCTURING_IN_IMPORT, }); } @@ -896,7 +883,7 @@ function parseImportSpecifier( if (nodeIsTypeImport && specifierIsTypeImport) { parser.addDiagnostic({ start: firstIdentPos, - message: 'The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements', + description: descriptions.JS_PARSER.IMPORT_KIND_SPECIFIER_ON_IMPORT_DECLARATION_WITH_KIND, }); } diff --git a/packages/@romejs/js-parser/parser/statement.ts b/packages/@romejs/js-parser/parser/statement.ts index b869f5c019f..3dc9796a991 100644 --- a/packages/@romejs/js-parser/parser/statement.ts +++ b/packages/@romejs/js-parser/parser/statement.ts @@ -86,6 +86,7 @@ import { keywordRelationalOperator, } from '@romejs/js-parser-utils'; import {number0, get0, add, inc} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; const loopLabel: Label = {kind: 'loop'}; const switchLabel: Label = {kind: 'switch'}; @@ -289,11 +290,11 @@ export function parseStatement( if (context !== undefined) { if (parser.inScope('STRICT')) { parser.addDiagnostic({ - message: 'In strict mode code, functions can only be declared at top level or inside a block', + description: descriptions.JS_PARSER.ILLEGAL_FUNCTION_IN_STRICT, }); } else if (context !== 'if' && context !== 'label') { parser.addDiagnostic({ - message: 'In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement', + description: descriptions.JS_PARSER.ILLEGAL_FUNCTION_IN_NON_STRICT, }); } } @@ -304,7 +305,7 @@ export function parseStatement( if (context !== undefined && result.head.generator === true) { parser.addDiagnostic({ - message: 'Generators can only be declared at the top level or inside a block', + description: descriptions.JS_PARSER.ILLEGAL_GENERATOR_DEFINITION, loc: result.loc, }); } @@ -340,7 +341,7 @@ export function parseStatement( ? assertVarKind(String(parser.state.tokenValue)) : kind; if (context !== undefined && kind !== 'var') { parser.addDiagnostic({ - message: 'Lexical declaration cannot appear in a single-statement context', + description: descriptions.JS_PARSER.LEXICAL_DECLARATION_IN_SINGLE_STATEMENT_CONTEXT, }); } return parseVarStatement(parser, start, kind); @@ -376,7 +377,7 @@ export function parseStatement( if (!topLevel) { parser.addDiagnostic({ - message: '\'import\' and \'export\' may only appear at the top level', + description: descriptions.JS_PARSER.IMPORT_EXPORT_MUST_TOP_LEVEL, }); } @@ -389,7 +390,7 @@ export function parseStatement( if (isAsyncFunctionDeclarationStart(parser)) { if (context !== undefined) { parser.addDiagnostic({ - message: 'Async functions can only be declared at the top level or inside a block', + description: descriptions.JS_PARSER.ILLEGAL_ASYNC_DEFINITION, }); } @@ -462,22 +463,9 @@ export function assertModuleNodeAllowed(parser: JSParser, node: AnyNode): void { if (!parser.inModule) { parser.addDiagnostic({ loc: node.loc, - message: `import and export can only appear in a module`, - advice: [ - // TODO this advice is pointless if you have syntax extensions enabled - - // TODO point to the actual package.json for this file - { - type: 'log', - category: 'info', - message: 'Change the extension to .mjs to turn this file into a module', - }, - { - type: 'log', - category: 'info', - message: `Add "type": "module" to your `, - }, - ], + description: descriptions.JS_PARSER.IMPORT_EXPORT_IN_SCRIPT( + parser.options.manifestPath, + ), }); } } @@ -487,7 +475,6 @@ export function parseBreakContinueStatement( start: Position, isBreak: boolean, ): BreakStatement | ContinueStatement { - const keyword = isBreak ? 'break' : 'continue'; parser.next(); let label; @@ -519,7 +506,7 @@ export function parseBreakContinueStatement( if (i === parser.state.labels.length) { parser.addDiagnostic({ start, - message: `Unsyntactic ${keyword}`, + description: descriptions.JS_PARSER.UNKNOWN_LABEL(label && label.name), }); } @@ -620,7 +607,7 @@ export function parseForStatement( if (awaitAt !== undefined) { parser.addDiagnostic({ start: awaitAt, - message: 'Can\'t have an await on a regular for loop', + description: descriptions.JS_PARSER.REGULAR_FOR_AWAIT, }); } @@ -647,7 +634,7 @@ export function parseForStatement( if (awaitAt !== undefined) { parser.addDiagnostic({ start: awaitAt, - message: 'Can\'t have an await on a regular for loop', + description: descriptions.JS_PARSER.REGULAR_FOR_AWAIT, }); } @@ -683,7 +670,7 @@ export function parseReturnStatement( if (!parser.inScope('FUNCTION') && parser.sourceType !== 'template' && !parser.options.allowReturnOutsideFunction) { parser.addDiagnostic({ - message: '\'return\' outside of function', + description: descriptions.JS_PARSER.RETURN_OUTSIDE_FUNCTION, }); } @@ -765,9 +752,10 @@ export function parseSwitchStatement( test = parseExpression(parser, 'case test'); } else { if (sawDefault) { + // TODO point to other default parser.addDiagnostic({ start: parser.state.lastStartPos, - message: 'Multiple default clauses', + description: descriptions.JS_PARSER.MULTIPLE_DEFAULT_CASE, }); } sawDefault = true; @@ -785,7 +773,7 @@ export function parseSwitchStatement( if (cur === undefined) { parser.addDiagnostic({ loc: stmt.loc, - message: 'Statement outside of a case or default block', + description: descriptions.JS_PARSER.SWITCH_STATEMENT_OUTSIDE_CASE, }); } else { cur.consequent.push(stmt); @@ -817,7 +805,7 @@ export function parseThrowStatement( ))) { parser.addDiagnostic({ start: parser.state.lastEndPos, - message: 'Illegal newline after throw', + description: descriptions.JS_PARSER.NEWLINE_AFTER_THROW, }); } @@ -868,7 +856,7 @@ export function parseTryStatement( if (!handler && !finalizer) { parser.addDiagnostic({ start, - message: 'Missing catch or finally clause', + description: descriptions.JS_PARSER.TRY_MISSING_FINALLY_OR_CATCH, }); } @@ -921,7 +909,7 @@ export function parseWithStatement( if (parser.inScope('STRICT')) { parser.addDiagnostic({ loc: parser.finishLoc(start), - message: '\'with\' in strict mode', + description: descriptions.JS_PARSER.WITH_IN_STRICT, }); } @@ -951,7 +939,7 @@ export function parseLabeledStatement( if (label.name === maybeName) { parser.addDiagnostic({ loc: expr.loc, - message: `Label '${maybeName}' is already declared`, + description: descriptions.JS_PARSER.DUPLICATE_LABEL(maybeName, label.loc), }); } } @@ -976,6 +964,7 @@ export function parseLabeledStatement( parser.state.labels.push({ name: maybeName, kind, + loc: parser.getLoc(expr), statementStart: parser.state.startPos.index, }); @@ -996,7 +985,7 @@ export function parseLabeledStatement( body.head.generator === true || body.head.async === true)) { parser.addDiagnostic({ loc: body.loc, - message: 'Invalid labeled declaration', + description: descriptions.JS_PARSER.INVALID_LABEL_DECLARATION, }); } @@ -1109,7 +1098,7 @@ export function parseBlockOrModuleBlockBody( if (octalPosition !== undefined) { parser.addDiagnostic({ index: octalPosition, - message: 'Octal literal in strict mode', + description: descriptions.JS_PARSER.OCTAL_IN_STRICT, }); } } @@ -1174,7 +1163,7 @@ export function parseForIn( if (isForIn && isAwait) { parser.addDiagnostic({ start: awaitAt, - message: 'Unexpected await for `for-in`', + description: descriptions.JS_PARSER.REGULAR_FOR_AWAIT, }); } @@ -1183,7 +1172,7 @@ export function parseForIn( init.declarations[0].id.type !== 'BindingIdentifier')) { parser.addDiagnostic({ loc: init.loc, - message: `${isForIn ? 'for-in' : 'for-of'} loop variable declaration may not have an initializer`, + description: descriptions.JS_PARSER.FOR_IN_OF_WITH_INITIALIZER, }); } @@ -1245,7 +1234,7 @@ export function parseVar( // It could be a declaration like `const x: number;`. if (!parser.isSyntaxEnabled('ts')) { parser.addDiagnostic({ - message: 'const with no initializer isn\'t allowed', + description: descriptions.JS_PARSER.CONST_WITHOUT_INITIALIZER, loc: id.loc, }); } @@ -1256,7 +1245,7 @@ export function parseVar( (parser.match(tt._in) || parser.isContextual('of')))) { parser.addDiagnostic({ start: parser.state.lastEndPos, - message: 'Complex binding patterns require an initialization value', + description: descriptions.JS_PARSER.COMPLEX_BINDING_WITHOUT_INITIALIZER, }); } } @@ -1286,13 +1275,7 @@ export function parseVarHead( let definite: undefined | boolean; if (id.type === 'BindingIdentifier' && parser.match(tt.bang)) { definite = true; - - if (!parser.isSyntaxEnabled('ts')) { - parser.addDiagnostic({ - message: 'TypeScript syntax isn\'t enabled for definite syntax', - }); - } - + parser.expectSyntaxEnabled('ts'); parser.next(); } @@ -1536,7 +1519,7 @@ export function parseFunctionParams( if (typeParameters !== undefined && (kind === 'get' || kind === 'set')) { parser.addDiagnostic({ loc: typeParameters.loc, - message: 'An accessor cannot have type parameters', + description: descriptions.JS_PARSER.ACCESSOR_WITH_TYPE_PARAMS, }); } } diff --git a/packages/@romejs/js-parser/parser/type-systems.ts b/packages/@romejs/js-parser/parser/type-systems.ts index 6f97acfbca1..3378d40c085 100644 --- a/packages/@romejs/js-parser/parser/type-systems.ts +++ b/packages/@romejs/js-parser/parser/type-systems.ts @@ -54,6 +54,7 @@ import { toTargetAssignmentPattern, } from './index'; import {PatternMeta} from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; export function isTypeSystemEnabled(parser: JSParser): boolean { return parser.isSyntaxEnabled('flow') || parser.isSyntaxEnabled('ts'); @@ -103,7 +104,7 @@ export function parseTypeLiteralAnnotation( if (!parser.match(tt.num)) { parser.addDiagnostic({ - message: `Unexpected token, expected "number"`, + description: descriptions.JS_PARSER.TYPE_NUMERIC_LITERAL_EXPECTED, }); parser.next(); return parser.finishNode(start, { @@ -120,13 +121,13 @@ export function parseTypeLiteralAnnotation( }); } else { parser.addDiagnostic({ - message: 'Numeric literal type annotations cannot stand with a +, omit it instead', + description: descriptions.JS_PARSER.TYPE_NUMERIC_LITERAL_PLUS, }); parser.next(); if (!parser.match(tt.num)) { parser.addDiagnostic({ - message: `Unexpected token, expected "number"`, + description: descriptions.JS_PARSER.TYPE_NUMERIC_LITERAL_EXPECTED, }); parser.next(); return parser.finishNode(start, { @@ -199,19 +200,7 @@ export function addFlowOrTSDiagnostic( parser.addDiagnostic({ start, - message: `A ${label} is only valid inside of a TypeScript or Flow file`, - advice: [ - { - type: 'log', - category: 'info', - message: 'Did you mean TypeScript? Change the file extension to .ts or .tsx', - }, - { - type: 'log', - category: 'info', - message: 'Did you mean Flow? Add a @flow comment annotation to the top of the file', - }, - ], + description: descriptions.JS_PARSER.FLOW_OR_TEST_REQUIRED(label), }); } @@ -226,14 +215,7 @@ export function addFlowDiagnostic( parser.addDiagnostic({ start, - message: `A ${label} is only valid inside of a Flow file`, - advice: [ - { - type: 'log', - category: 'info', - message: 'To enable Flow support, add a @flow comment annotation to the top of the file', - }, - ], + description: descriptions.JS_PARSER.FLOW_REQUIRED(label), }); } @@ -244,14 +226,7 @@ export function addTSDiagnostic(parser: JSParser, label: string, start: Position parser.addDiagnostic({ start, - message: `A ${label} is only valid inside of a TypeScript file`, - advice: [ - { - type: 'log', - category: 'info', - message: 'To enable TypeScript support, the file extension should end in .ts or .tsx', - }, - ], + description: descriptions.JS_PARSER.TS_REQUIRED(label), }); } diff --git a/packages/@romejs/js-parser/parser/typescript.ts b/packages/@romejs/js-parser/parser/typescript.ts index 10aaf2f88e3..9f24b2612c4 100644 --- a/packages/@romejs/js-parser/parser/typescript.ts +++ b/packages/@romejs/js-parser/parser/typescript.ts @@ -91,6 +91,7 @@ import { TemplateLiteralTypeAnnotation, TSOptionalType, } from '@romejs/js-ast'; +import {descriptions} from '@romejs/diagnostics'; type ParsingContext = | 'EnumMembers' @@ -296,7 +297,7 @@ function parseTSImportType(parser: JSParser): TSImportType { if (!parser.match(tt.string)) { parser.addDiagnostic({ - message: 'Argument in a type import must be a string literal', + description: descriptions.JS_PARSER.TS_IMPORT_ARG_NOT_STRING, }); } @@ -473,7 +474,7 @@ export function tsCheckLiteralForConstantContext(parser: JSParser, node: AnyNode default: parser.addDiagnostic({ loc: node.loc, - message: 'Only literal values are allowed in constant contexts', + description: descriptions.JS_PARSER.TS_CONSTANT_NOT_LITERAL, }); } } @@ -534,7 +535,7 @@ function parseTSBindingListForSignature( } else { parser.addDiagnostic({ loc: pattern.loc, - message: `Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got ${pattern.type}`, + description: descriptions.JS_PARSER.TS_INVALID_SIGNATURE_BINDING_NODE, }); } } @@ -828,7 +829,7 @@ function parseTSTupleType(parser: JSParser): TSTupleType { } else if (seenOptionalElement && !isRest) { parser.addDiagnostic({ loc: type.loc, - message: 'A required element cannot follow an optional element.', + description: descriptions.JS_PARSER.TS_REQUIRED_FOLLOWS_OPTIONAL, }); } @@ -949,7 +950,7 @@ function parseTSTemplateLiteralType( if (templateNode.expressions.length > 0) { parser.addDiagnostic({ loc: parser.getLoc(templateNode.expressions[0]), - message: 'Template literal types cannot have any substitution', + description: descriptions.JS_PARSER.TS_TEMPLATE_LITERAL_WITH_SUBSTITUION, }); } @@ -1030,7 +1031,7 @@ function parseTSNonArrayType(parser: JSParser): AnyTSPrimary { } parser.addDiagnostic({ - message: 'Unknown TS non array type start', + description: descriptions.JS_PARSER.TS_UNKNOWN_NON_ARRAY_START, }); parser.next(); @@ -1100,7 +1101,7 @@ function tsCheckTypeAnnotationForReadOnly(parser: JSParser, node: AnyTSPrimary) default: parser.addDiagnostic({ loc: node.loc, - message: '\'readonly\' type modifier is only permitted on array and tuple literal types.', + description: descriptions.JS_PARSER.TS_INVALID_READONLY_MODIFIER, }); break; } @@ -1431,10 +1432,10 @@ export function parseTSHeritageClause( parseTSExpressionWithTypeArguments, ); - if (!delimitedList.length) { + if (delimitedList.length === 0) { parser.addDiagnostic({ start: originalStart, - message: `'${descriptor}' list cannot be empty.`, + description: descriptions.JS_PARSER.TS_EMPTY_LIST(descriptor), }); } @@ -1709,7 +1710,7 @@ function parseTSExternalModuleReference( expression = parseStringLiteral(parser); } else { parser.addDiagnostic({ - message: 'Invalid TS external module reference expression', + description: descriptions.JS_PARSER.TS_EXTERNAL_MODULE_REFERENCE_ARG_NOT_STRING, }); // Skip as much of the next expression as we can @@ -1839,7 +1840,7 @@ export function parseTSDeclare(parser: JSParser, start: Position): TSDeclareNode } parser.addDiagnostic({ - message: 'Unknown typescript declare start', + description: descriptions.JS_PARSER.TS_UNKNOWN_DECLARE_START, }); // Fake node diff --git a/packages/@romejs/js-parser/tokenizer/index.ts b/packages/@romejs/js-parser/tokenizer/index.ts index e792209cc8c..375fd4a4a82 100644 --- a/packages/@romejs/js-parser/tokenizer/index.ts +++ b/packages/@romejs/js-parser/tokenizer/index.ts @@ -32,7 +32,7 @@ import {validateRegexFlags} from '@romejs/js-parser-utils'; import {addComment} from '../parser/index'; import {UNICODE_MISTAKES, ASCII_NAMES} from './unicodeMistakes'; import * as charCodes from '@romejs/string-charcodes'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {descriptions} from '@romejs/diagnostics'; import { coerce0, add, @@ -314,7 +314,7 @@ function pushComment( if (opts.text.includes('@flow') || opts.text.includes('@noflow')) { if (parser.syntax.has('ts')) { parser.addDiagnostic({ - message: 'Cannot have a @flow annotation comment when TypeScript syntax has been enabled', + description: descriptions.JS_PARSER.FLOW_ANNOTATION_WITH_TYPESCRIPT_ENABLED, }); } else { parser.syntax.add('flow'); @@ -353,7 +353,7 @@ function skipBlockComment(parser: JSParser): void { if (endIndex === number0Neg1) { parser.addDiagnostic({ end: parser.getPositionFromIndex(sub(parser.state.index, 2)), - message: 'Unterminated comment', + description: descriptions.JS_PARSER.UNTERMINATED_BLOCK_COMMENT, }); return undefined; } @@ -734,23 +734,11 @@ function readToken_numberSign(parser: JSParser): void { return undefined; } - // Check if there's a ! after this, in that case it's a confused hashbang - let advice: undefined | PartialDiagnosticAdvice; - if (parser.input[getIndex(parser) + 1] === '!') { - advice = - [ - { - type: 'log', - category: 'info', - message: 'Did you want to write a hashbang? A hashbang can only be the first thing in a file.', - }, - ]; - } - // TODO make this a diagnostic, and advance to the next line if suspected hashbang parser.addDiagnostic({ - message: `Unexpected character '#'`, - advice, + description: descriptions.JS_PARSER.UNEXPECTED_HASH(parser.input[getIndex( + parser, + ) + 1] === '!'), }); bumpIndex(parser); nextToken(parser); @@ -944,15 +932,12 @@ function getTokenFromCode(parser: JSParser, code: number): void { } parser.addDiagnostic({ - message: `Unexpected Unicode character '${char}' (${unicodeName})`, - - advice: [ - { - type: 'log', - category: 'info', - message: `Did you mean '${equivalentChar}' (${equivalentName})? Both characters look the same, but are not.`, - }, - ], + description: descriptions.JS_PARSER.UNEXPECTED_UNICODE_CHARACTER( + char, + unicodeName, + equivalentChar, + equivalentName, + ), }); // Read the token as the equivalent character @@ -961,7 +946,9 @@ function getTokenFromCode(parser: JSParser, code: number): void { } parser.addDiagnostic({ - message: `Unexpected character '${codePointToString(code)}'`, + description: descriptions.PARSER_CORE.UNEXPECTED_CHARACTER( + codePointToString(code), + ), }); // Skip unknown characters @@ -985,7 +972,7 @@ export function readRegexp(parser: JSParser): void { if (parser.state.index >= parser.length) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated regular expression', + description: descriptions.JS_PARSER.UNTERMINATED_REGEX, }); break; } @@ -995,7 +982,7 @@ export function readRegexp(parser: JSParser): void { if (lineBreak.test(ch)) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated regular expression', + description: descriptions.JS_PARSER.UNTERMINATED_REGEX, }); break; } @@ -1028,14 +1015,14 @@ export function readRegexp(parser: JSParser): void { if (parser.state.escapePosition !== undefined) { parser.addDiagnostic({ index: parser.state.escapePosition, - message: 'Regular expression flags can\'t contain unicode escapes', + description: descriptions.JS_PARSER.UNICODE_ESCAPE_IN_REGEX_FLAGS, }); } - const mods = validateRegexFlags(rawMods, (msg, index) => { + const mods = validateRegexFlags(rawMods, (metadata, index) => { parser.addDiagnostic({ index: add(start, index), - message: msg, + description: metadata, }); }); @@ -1078,14 +1065,14 @@ function readInt( if (code === charCodes.underscore) { if (allowedSiblings.indexOf(next) === -1) { parser.addDiagnostic({ - message: 'Invalid or unexpected token', + description: descriptions.JS_PARSER.INVALID_INT_TOKEN, }); } if (forbiddenSiblings.indexOf(prev) > -1 || forbiddenSiblings.indexOf(next) > -1 || Number.isNaN(next)) { parser.addDiagnostic({ - message: 'Invalid or unexpected token', + description: descriptions.JS_PARSER.INVALID_INT_TOKEN, }); } @@ -1129,7 +1116,7 @@ function readRadixNumber(parser: JSParser, radix: number): void { if (val === undefined) { parser.addDiagnostic({ index: add(start, 2), - message: `Expected number in radix ${radix}`, + description: descriptions.JS_PARSER.EXPECTED_NUMBER_IN_RADIX(radix), }); } @@ -1141,7 +1128,7 @@ function readRadixNumber(parser: JSParser, radix: number): void { if (isIdentifierStart(fullCharCodeAtPos(parser))) { parser.addDiagnostic({ index: parser.state.index, - message: 'Identifier directly after number', + description: descriptions.JS_PARSER.IDENTIFIER_AFTER_NUMBER, }); } @@ -1166,7 +1153,7 @@ function readNumber(parser: JSParser, startsWithDot: boolean): void { if (!startsWithDot && readInt(parser, 10) === undefined) { parser.addDiagnostic({ index: parser.state.index, - message: 'Invalid number', + description: descriptions.JS_PARSER.INVALID_NUMBER, }); } @@ -1176,7 +1163,7 @@ function readNumber(parser: JSParser, startsWithDot: boolean): void { if (parser.inScope('STRICT')) { parser.addDiagnostic({ index: parser.state.index, - message: 'Legacy octal literals are not allowed in strict mode', + description: descriptions.JS_PARSER.LEGACY_OCTAL_IN_STRICT_MODE, }); } @@ -1204,7 +1191,7 @@ function readNumber(parser: JSParser, startsWithDot: boolean): void { if (readInt(parser, 10) === undefined) { parser.addDiagnostic({ index: parser.state.index, - message: 'Invalid number', + description: descriptions.JS_PARSER.INVALID_NUMBER, }); } @@ -1217,14 +1204,14 @@ function readNumber(parser: JSParser, startsWithDot: boolean): void { if (isFloat) { parser.addDiagnostic({ index: parser.state.index, - message: 'A bigint can\'t have a decimal', + description: descriptions.JS_PARSER.DECIMAL_BIGINT, }); } if (isOctal) { parser.addDiagnostic({ index: parser.state.index, - message: 'A bigint can\'t be an octal', + description: descriptions.JS_PARSER.OCTAL_BIGINT, }); } @@ -1235,7 +1222,7 @@ function readNumber(parser: JSParser, startsWithDot: boolean): void { if (isIdentifierStart(parser.input.codePointAt(getIndex(parser)))) { parser.addDiagnostic({ index: parser.state.index, - message: 'Identifier directly after number', + description: descriptions.JS_PARSER.IDENTIFIER_AFTER_NUMBER, }); } @@ -1275,7 +1262,7 @@ function readCodePoint( if (throwOnInvalid) { parser.addDiagnostic({ index: codePos, - message: 'Code point out of bounds', + description: descriptions.JS_PARSER.OUT_OF_BOUND_CODE_POINT, }); } else { parser.state.invalidTemplateEscapePosition = sub(codePos, 2); @@ -1296,7 +1283,7 @@ function readString(parser: JSParser, quote: number): void { if (parser.state.index >= parser.length) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated string constant', + description: descriptions.JS_PARSER.UNTERMINATED_STRING, }); break; } @@ -1318,7 +1305,7 @@ function readString(parser: JSParser, quote: number): void { if (isNewLine(ch)) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated string constant', + description: descriptions.JS_PARSER.UNTERMINATED_STRING, }); } bumpIndex(parser); @@ -1340,7 +1327,7 @@ export function readTemplateToken(parser: JSParser): void { if (parser.state.index >= parser.length) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated template', + description: descriptions.JS_PARSER.UNTERMINATED_TEMPLATE, }); break; } @@ -1482,7 +1469,7 @@ function readEscapedChar( } else if (parser.inScope('STRICT')) { parser.addDiagnostic({ index: codePos, - message: 'Octal literal in strict mode', + description: descriptions.JS_PARSER.OCTAL_IN_STRICT_MODE, }); } else if (!parser.state.containsOctal) { // These properties are only used to throw an error for an octal which occurs @@ -1514,7 +1501,7 @@ function readHexChar( if (throwOnInvalid) { parser.addDiagnostic({ index: start, - message: 'Bad character escape sequence', + description: descriptions.JS_PARSER.BAD_HEX_ESCAPE, }); return 0; } @@ -1558,7 +1545,7 @@ function readWord1(parser: JSParser): string { charCodes.lowercaseU) { parser.addDiagnostic({ index: parser.state.index, - message: 'Expecting Unicode escape sequence \\uXXXX', + description: descriptions.JS_PARSER.EXPECTED_UNICODE_ESCAPE, }); } @@ -1573,7 +1560,7 @@ function readWord1(parser: JSParser): string { if (isValid(esc) === false) { parser.addDiagnostic({ index: parser.state.index, - message: 'Invalid Unicode escape', + description: descriptions.JS_PARSER.INVALID_UNICODE_ESCAPE, }); } @@ -1601,13 +1588,13 @@ function readWord(parser: JSParser): void { if (type.keyword !== undefined && parser.state.escapePosition !== undefined) { parser.addDiagnostic({ index: parser.state.escapePosition, - message: `Escape sequence in keyword ${word}`, + description: descriptions.JS_PARSER.ESCAPE_SEQUENCE_IN_KEYWORD(word), }); } if (parser.state.isIterator && (!isIterator(word) || !parser.inScope('TYPE'))) { parser.addDiagnostic({ - message: `Invalid identifier ${word}`, + description: descriptions.JS_PARSER.INVALID_IDENTIFIER_NAME(word), }); } @@ -1764,7 +1751,7 @@ function readToken_jsxString(parser: JSParser, quote: number): void { if (parser.state.index >= parser.length) { parser.addDiagnostic({ end: parser.getPositionFromIndex(parser.state.index), - message: 'Unterminated string constant', + description: descriptions.JS_PARSER.UNTERMINATED_JSX_STRING, }); break; } diff --git a/packages/@romejs/js-parser/tokenizer/state.ts b/packages/@romejs/js-parser/tokenizer/state.ts index 2cb1fd1d394..11eef2c4638 100644 --- a/packages/@romejs/js-parser/tokenizer/state.ts +++ b/packages/@romejs/js-parser/tokenizer/state.ts @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics, DiagnosticFilters} from '@romejs/diagnostics'; -import {OpeningContext, ScopeType} from '../parser'; +import {Diagnostics, DiagnosticFilters} from '@romejs/diagnostics'; +import {ScopeType} from '../parser'; import {Position, SourceLocation} from '@romejs/parser-core'; import {types as ct, TokContext} from './context'; import {types as tt, TokenTypes} from './types'; @@ -17,13 +17,12 @@ import {Number1, number1, number0, Number0, number0Neg1} from '@romejs/ob1'; type Scopes = { [K in ScopeType]?: Array }; export type State = { - diagnostics: PartialDiagnostics; + diagnostics: Diagnostics; diagnosticFilters: DiagnosticFilters; isIterator: boolean; tokens: Array; hasHoistedVars: boolean; corrupt: boolean; - possibleIncorrectOpenParens: Array; indentLevel: Number0; lineStart: boolean; @@ -139,6 +138,7 @@ export type LabelKind = undefined | 'loop' | 'switch'; export type Label = { kind: LabelKind; + loc?: SourceLocation; name?: string; statementStart?: Number0; }; @@ -190,7 +190,6 @@ export function createInitialState(): State { octalPosition: undefined, invalidTemplateEscapePosition: undefined, exportedIdentifiers: new Map(), - possibleIncorrectOpenParens: [], lineStart: true, indentLevel: number0, }; diff --git a/packages/@romejs/messages/en.ts b/packages/@romejs/messages/en.ts deleted file mode 100644 index 8b137891791..00000000000 --- a/packages/@romejs/messages/en.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/@romejs/parser-core/index.ts b/packages/@romejs/parser-core/index.ts index 8a9dde092d3..364ab6b8741 100644 --- a/packages/@romejs/parser-core/index.ts +++ b/packages/@romejs/parser-core/index.ts @@ -19,11 +19,11 @@ import { ComplexToken, } from './types'; import { - PartialDiagnosticAdvice, getDiagnosticsFromError, createSingleDiagnosticError, - PartialDiagnostic, + Diagnostic, DiagnosticCategory, + DiagnosticDescription, } from '@romejs/diagnostics'; import { Number1, @@ -38,7 +38,8 @@ import { } from '@romejs/ob1'; import {escapeMarkup} from '@romejs/string-markup'; import {UnknownFilePath, createUnknownFilePath} from '@romejs/path'; -import {Class} from '@romejs/typescript-helpers'; +import {Class, OptionalProps} from '@romejs/typescript-helpers'; +import {createBlessedDiagnosticMessage, descriptions} from '@romejs/diagnostics'; export * from './types'; @@ -54,12 +55,11 @@ export type ParserOptionsWithRequiredPath = & {path: NonNullable}; export type ParserUnexpectedOptions = { - message?: string; + description?: OptionalProps; loc?: SourceLocation; start?: Position; end?: Position; token?: TokenBase; - advice?: PartialDiagnosticAdvice; }; export type TokenValues = @@ -449,9 +449,9 @@ export class ParserCore { return pos; } - createDiagnostic(opts: ParserUnexpectedOptions = {}): PartialDiagnostic { + createDiagnostic(opts: ParserUnexpectedOptions = {}): Diagnostic { const {currentToken} = this; - let {message, start, end, loc, token} = opts; + let {description: metadata, start, end, loc, token} = opts; // Allow passing in a TokenBase if (token !== undefined) { @@ -484,35 +484,41 @@ export class ParserCore { } // Normalize message, we need to be defensive here because it could have been called while tokenizing the first token - if (message === undefined) { + if (metadata === undefined) { + let message; if (currentToken !== undefined && start !== undefined && start.index === currentToken.start) { - message = `Unexpected ${currentToken.type}`; + message = createBlessedDiagnosticMessage( + `Unexpected ${currentToken.type}`, + ); } else { if (this.isEOF(start.index)) { - message = 'Unexpected end of file'; + message = createBlessedDiagnosticMessage('Unexpected end of file'); } else { const char = this.input[get0(start.index)]; - message = - `Unexpected character ${escapeMarkup(char)}`; + message = createBlessedDiagnosticMessage( + `Unexpected character ${escapeMarkup(char)}`, + ); } } + metadata = {message}; } - let errMessage = `${message} (${start.line}:${start.column})`; - if (this.path !== undefined) { - errMessage = `${this.path}: ${errMessage} Input: ${this.input}`; - } + const metadataWithCategory: DiagnosticDescription = { + ...metadata, + category: metadata.category === undefined + ? this.diagnosticCategory : metadata.category, + }; return { - message, - advice: opts.advice, - category: this.diagnosticCategory, - sourceText: this.path === undefined ? this.input : undefined, - mtime: this.mtime, - start, - end, - filename: this.filename, + description: metadataWithCategory, + location: { + sourceText: this.path === undefined ? this.input : undefined, + mtime: this.mtime, + start, + end, + filename: this.filename, + }, }; } @@ -525,7 +531,7 @@ export class ParserCore { assertNoSpace() { if (this.currentToken.start !== this.prevToken.end) { throw this.unexpected({ - message: 'Expected no space between', + description: descriptions.PARSER_CORE.EXPECTED_SPACE, }); } } @@ -554,7 +560,7 @@ export class ParserCore { // Get the current token and assert that it's of the specified type, the token stream will also be advanced expectToken( type: Type, - message?: string, + _metadata?: DiagnosticDescription, ): Tokens[Type] { const token = this.getToken(); if (token.type === type) { @@ -563,8 +569,8 @@ export class ParserCore { return token; } else { throw this.unexpected({ - message: message === undefined - ? `Expected token ${type} but got ${token.type}` : message, + description: _metadata === undefined + ? descriptions.PARSER_CORE.EXPECTED_TOKEN(token.type, (type as string)) : _metadata, }); } } @@ -666,7 +672,7 @@ export class ParserCore { finalize() { if (!this.eatToken('EOF')) { throw this.unexpected({ - message: 'Expected end of file', + description: descriptions.PARSER_CORE.EXPECTED_EOF, }); } } diff --git a/packages/@romejs/path-match/parse.ts b/packages/@romejs/path-match/parse.ts index 8499a37e141..be6b33c1087 100644 --- a/packages/@romejs/path-match/parse.ts +++ b/packages/@romejs/path-match/parse.ts @@ -15,6 +15,7 @@ import { } from './types'; import {ParserOptions, createParser} from '@romejs/parser-core'; import {Number0, add, number0, get0, coerce0} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; type ParseMode = 'path' | 'pattern'; @@ -124,7 +125,7 @@ const createPathMatchParser = createParser((ParserCore) => default: throw this.unexpected({ start: startPos, - message: 'Invalid pattern segment part', + description: descriptions.PATH_MATCH.INVALID_PATTERN_SEGMENT_PART, }); } } @@ -279,7 +280,7 @@ const createPathMatchParser = createParser((ParserCore) => return token.value; } else { throw this.unexpected({ - message: 'Invalid path segment', + description: descriptions.PATH_MATCH.INVALID_PATH_SEGMENT, }); } } diff --git a/packages/@romejs/project/save.ts b/packages/@romejs/project/save.ts index c59560a3a4a..7ebab1afe68 100644 --- a/packages/@romejs/project/save.ts +++ b/packages/@romejs/project/save.ts @@ -65,9 +65,12 @@ export async function modifyProjectConfig( // Set the `code` property on relevant diagnostics since our changes don't exist on disk diagnostics = diagnostics.map((diag) => { - return diag.filename === configPath.join() ? { + return diag.location.filename === configPath.join() ? { ...diag, - sourceText: stringified, + location: { + ...diag.location, + sourceText: stringified, + }, } : diag; }); diff --git a/packages/@romejs/string-escape/index.ts b/packages/@romejs/string-escape/index.ts index 46811975199..7c10a00afe4 100644 --- a/packages/@romejs/string-escape/index.ts +++ b/packages/@romejs/string-escape/index.ts @@ -5,10 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import * as messages from './messages'; - -export {messages}; - export {default as escapeString} from './escapeString'; export {default as unescapeString} from './unescapeString'; export * from './constants'; diff --git a/packages/@romejs/string-escape/messages.ts b/packages/@romejs/string-escape/messages.ts deleted file mode 100644 index 969f6f9cbf0..00000000000 --- a/packages/@romejs/string-escape/messages.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -export const NOT_ENOUGH_CODE_POINTS = 'Not enough code point digits'; -export const INVALID_STRING_CHARACTER = - 'Invalid string character (U+0000 to U+001F)'; -export const INVALID_HEX_DIGIT_FOR_ESCAPE = - 'Invalid hex digit for unicode escape'; diff --git a/packages/@romejs/string-escape/unescapeString.ts b/packages/@romejs/string-escape/unescapeString.ts index e52690f1b65..c896718c6b1 100644 --- a/packages/@romejs/string-escape/unescapeString.ts +++ b/packages/@romejs/string-escape/unescapeString.ts @@ -6,11 +6,7 @@ */ import {isHexDigit} from '@romejs/parser-core'; -import { - INVALID_STRING_CHARACTER, - NOT_ENOUGH_CODE_POINTS, - INVALID_HEX_DIGIT_FOR_ESCAPE, -} from './messages'; +import {DiagnosticDescription, descriptions} from '@romejs/diagnostics'; function unescapeChar(modifier: string): string { switch (modifier) { @@ -37,13 +33,13 @@ function unescapeChar(modifier: string): string { } } -type UnescapeStringUnexpected = (message: string, index: number) => void; +type UnescapeStringUnexpected = (metadata: Omit, index: number) => void; const UNEXPECTED_DEFAULT_THROWER: UnescapeStringUnexpected = ( - message: string, + metadata: Omit, index: number, ) => { - throw new TypeError(`${message} (${String(index)})`); + throw new TypeError(`${metadata.message.value} (${String(index)})`); }; export default function unescapeString( @@ -68,7 +64,10 @@ export default function unescapeString( throw new Error('Already validated that this index exists'); } if (codePoint >= 0 && codePoint <= 31) { - throw unexpected(INVALID_STRING_CHARACTER, index); + throw unexpected( + descriptions.STRING_ESCAPE.INVALID_STRING_CHARACTER, + index, + ); } // Add it verbatim @@ -89,7 +88,10 @@ export default function unescapeString( if (rawCode.length < 4) { // (index of the point start + total point digits) const lastDigitIndex = codeStartIndex + rawCode.length - 1; - throw unexpected(NOT_ENOUGH_CODE_POINTS, lastDigitIndex); + throw unexpected( + descriptions.STRING_ESCAPE.NOT_ENOUGH_CODE_POINTS, + lastDigitIndex, + ); } // Validate that each character is a valid hex digit @@ -100,7 +102,10 @@ export default function unescapeString( // (code start index + digit index) const pos = codeStartIndex + i; - throw unexpected(INVALID_HEX_DIGIT_FOR_ESCAPE, pos); + throw unexpected( + descriptions.STRING_ESCAPE.INVALID_HEX_DIGIT_FOR_ESCAPE, + pos, + ); } } diff --git a/packages/@romejs/string-markup/parse.ts b/packages/@romejs/string-markup/parse.ts index aa22e5a3395..baa7753c2c6 100644 --- a/packages/@romejs/string-markup/parse.ts +++ b/packages/@romejs/string-markup/parse.ts @@ -21,6 +21,7 @@ import { TagName, } from './types'; import {inc, Number0, add, get0} from '@romejs/ob1'; +import {descriptions} from '@romejs/diagnostics'; const globalAttributes: Array = ['emphasis', 'dim']; @@ -147,7 +148,7 @@ const createStringMarkupParser = createParser((ParserCore) => if (unclosed) { throw this.unexpected({ - message: 'Unclosed string', + description: descriptions.STRING_MARKUP.UNCLOSED_STRING, start: this.getPositionFromIndex(stringValueEnd), }); } @@ -202,7 +203,7 @@ const createStringMarkupParser = createParser((ParserCore) => const allowedAttributes = tags.get(rawName); if (allowedAttributes === undefined) { throw this.unexpected({ - message: `Unknown tag name ${rawName}`, + description: descriptions.STRING_MARKUP.UNKNOWN_TAG_NAME(rawName), start: this.getPositionFromIndex(nameToken.start), }); } @@ -223,7 +224,10 @@ const createStringMarkupParser = createParser((ParserCore) => if (!allowedAttributes.includes(key) && !globalAttributes.includes(key)) { throw this.unexpected({ - message: `${key} is not a valid attribute name for <${tagName}>`, + description: descriptions.STRING_MARKUP.INVALID_ATTRIBUTE_NAME_FOR_TAG( + tagName, + key, + ), }); } @@ -250,7 +254,7 @@ const createStringMarkupParser = createParser((ParserCore) => selfClosing = true; } else { throw this.unexpected({ - message: 'Expected attribute name', + description: descriptions.STRING_MARKUP.EXPECTED_ATTRIBUTE_NAME, }); } } @@ -266,7 +270,7 @@ const createStringMarkupParser = createParser((ParserCore) => if (this.matchToken('EOF')) { throw this.unexpected({ - message: `Unclosed ${tagName} tag`, + description: descriptions.STRING_MARKUP.UNCLOSED_TAG(tagName), }); } else { this.expectToken('Less'); @@ -276,14 +280,17 @@ const createStringMarkupParser = createParser((ParserCore) => if (name.type === 'Word') { if (name.value !== tagName) { throw this.unexpected({ - message: `Expected to close ${tagName} but found ${name.value}`, + description: descriptions.STRING_MARKUP.INCORRECT_CLOSING_TAG_NAME( + tagName, + name.value, + ), }); } this.nextToken(); } else { throw this.unexpected({ - message: 'Expected closing tag name', + description: descriptions.STRING_MARKUP.EXPECTED_CLOSING_TAG_NAME, }); } @@ -312,7 +319,7 @@ const createStringMarkupParser = createParser((ParserCore) => return this.parseTag(); } else { throw this.unexpected({ - message: 'Unknown child start', + description: descriptions.STRING_MARKUP.UNKNOWN_START, }); } } diff --git a/packages/@romejs/typescript-helpers/index.ts b/packages/@romejs/typescript-helpers/index.ts index fd703d9e37c..3c0059e3a0b 100644 --- a/packages/@romejs/typescript-helpers/index.ts +++ b/packages/@romejs/typescript-helpers/index.ts @@ -14,6 +14,10 @@ export type RequiredProps = & Omit & { [Key in Keys]-?: NonNullable }; +export type OptionalProps = + & Omit + & { [Key in Keys]?: Obj[Key] }; + // Turn a type that contains interfaces into regular objects export type InterfaceToObject = T extends {} ? { [K in keyof T]: InterfaceToObject } diff --git a/packages/@romejs/v8/errors.ts b/packages/@romejs/v8/errors.ts index 147f5a28978..803016e50dc 100644 --- a/packages/@romejs/v8/errors.ts +++ b/packages/@romejs/v8/errors.ts @@ -6,7 +6,7 @@ */ import {Position, SourceLocation} from '@romejs/parser-core'; -import {PartialDiagnosticAdvice} from '@romejs/diagnostics'; +import {DiagnosticAdvice} from '@romejs/diagnostics'; import {ErrorFrames, ErrorFrame} from './types'; import {isPlainObject} from '@romejs/typescript-helpers'; import {number1, number0, number0Neg1} from '@romejs/ob1'; @@ -22,7 +22,7 @@ export type StructuredError = { message: string; stack: undefined | string; frames: ErrorFrames; - advice: PartialDiagnosticAdvice; + advice: DiagnosticAdvice; framesToPop: number; }; @@ -38,7 +38,7 @@ export class NativeStructuredError extends Error { } [ERROR_FRAMES_PROP]: undefined | ErrorFrames; - [ERROR_ADVICE_PROP]: undefined | PartialDiagnosticAdvice; + [ERROR_ADVICE_PROP]: undefined | DiagnosticAdvice; [ERROR_POP_FRAMES_PROP]: undefined | number; } @@ -51,7 +51,7 @@ export function getErrorStructure(err: unknown): StructuredError { let message = 'Unknown message'; let stack = undefined; let frames: ErrorFrames = []; - let advice: PartialDiagnosticAdvice = []; + let advice: DiagnosticAdvice = []; let framesToPop = 0; let looksLikeValidError = false; diff --git a/packages/rome/error.ts b/packages/rome/error.ts index 14dab90b3b0..7cfce64f05a 100644 --- a/packages/rome/error.ts +++ b/packages/rome/error.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {PartialDiagnostics, getDiagnosticsFromError} from '@romejs/diagnostics'; +import {Diagnostics, getDiagnosticsFromError} from '@romejs/diagnostics'; import {printDiagnosticsToString} from '@romejs/cli-diagnostics'; export class RomeDiagnosticsError extends Error { @@ -23,7 +23,7 @@ export class RomeDiagnosticsError extends Error { } } -export function throwDiagnostics(diagnostics: PartialDiagnostics) { +export function throwDiagnostics(diagnostics: Diagnostics) { if (diagnostics.length === 0) { return; } From 612b8cbd8c01681363567aa874ca978a1e284ab6 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 21 Mar 2020 22:13:12 -0700 Subject: [PATCH 3/7] Update tests --- packages/@romejs/diagnostics/descriptions.ts | 1 + .../api/analyzeDependencies.test.md | 79 +++-- .../@romejs/js-compiler/suppressions.test.md | 74 ++-- .../transforms/lint/getterReturn.test.md | 64 ++-- .../lint/noAsyncPromiseExecutor.test.md | 96 +++--- .../transforms/lint/noCompareNegZero.test.md | 50 +++ .../transforms/lint/noCompareNegZero.test.ts | 25 +- .../transforms/lint/noCondAssign.test.md | 193 ++++++----- ...glingBackslashInRegularExpressions.test.md | 268 ++++++++------- .../transforms/lint/noDebugger.test.md | 34 +- .../transforms/lint/noDeleteVars.test.md | 37 ++ .../transforms/lint/noDeleteVars.test.ts | 14 +- ...cateGroupNamesInRegularExpressions.test.md | 166 ++++----- .../transforms/lint/noDuplicateKeys.test.md | 37 ++ .../transforms/lint/noDuplicateKeys.test.ts | 22 +- .../lint/noEmptyCharacterClass.test.md | 204 ++++++----- .../transforms/lint/noExplicitAny.test.md | 320 ++++++++++-------- ...eSpacesInRegularExpressionLiterals.test.md | 46 +-- .../lint/noTemplateCurlyInString.test.md | 37 ++ .../lint/noTemplateCurlyInString.test.ts | 17 +- .../js-compiler/transforms/lint/noVar.test.md | 32 +- .../js-compiler/transforms/lint/noVar.test.ts | 23 -- .../lint/preferFunctionDeclarations.test.md | 296 +++++++++------- .../transforms/lint/preferTemplate.test.md | 64 ++-- .../transforms/lint/sparseArray.test.md | 34 +- .../lint/undeclaredVariable.test.md | 32 +- .../lint/undeclaredVariable.test.ts | 23 -- .../transforms/lint/unsafeNegation.test.md | 34 +- packages/@romejs/js-parser/parser/lval.ts | 6 +- .../core/uncategorised/321/output.txt | 30 +- .../es2015/uncategorised/196/output.txt | 30 +- .../es2015/uncategorised/307/output.txt | 31 +- .../es2015/uncategorised/308/output.txt | 31 +- .../es2015/uncategorised/309/output.txt | 31 +- .../es2015/uncategorised/310/output.txt | 31 +- .../es2015/uncategorised/393/output.txt | 31 +- .../es2015/uncategorised/394/output.txt | 31 +- .../es2017/async-functions/27/output.txt | 31 +- .../es2017/async-functions/32/output.txt | 31 +- .../object-default-params/output.txt | 31 +- .../object-binding-pattern-01/output.txt | 31 +- .../output.txt | 31 +- .../es2015-class/migrated_0019/output.txt | 30 +- .../nested-cover-grammar/output.txt | 31 +- .../nested-cover-grammar/output.txt | 31 +- .../proto-identifier-shorthand/output.txt | 30 +- .../proto-literal-shorthand/output.txt | 30 +- .../proto-shorthand-identifier/output.txt | 30 +- .../proto-shorthand-literal/output.txt | 30 +- .../proto-shorthands/output.txt | 30 +- .../u-flag-surrogate-pair/output.txt | 30 +- .../u-flag-valid-range/output.txt | 30 +- .../flow/optional-type/4/output.txt | 30 +- .../flow/regression/issue-58/output.txt | 30 +- .../works-in-array-pattern/output.txt | 30 +- .../test-fixtures/jsx/basic/22/output.txt | 47 +-- .../arrow-function/destructuring/output.txt | 31 +- .../typescript/export/declare/output.txt | 31 +- .../typescript/function/declare/output.txt | 31 +- 59 files changed, 1809 insertions(+), 1452 deletions(-) create mode 100644 packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.md create mode 100644 packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.md create mode 100644 packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.md create mode 100644 packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.md diff --git a/packages/@romejs/diagnostics/descriptions.ts b/packages/@romejs/diagnostics/descriptions.ts index ab4e49f0e56..ec1ab0cc232 100644 --- a/packages/@romejs/diagnostics/descriptions.ts +++ b/packages/@romejs/diagnostics/descriptions.ts @@ -928,6 +928,7 @@ export const descriptions = createMessages({ CONST_WITHOUT_INITIALIZER: 'A constant must have an initializer', COMPLEX_BINDING_WITHOUT_INITIALIZER: 'Complex binding patterns require an initialization value', ACCESSOR_WITH_TYPE_PARAMS: 'An accessor cannot have type parameters', + UNEXPECTED_SPREAD: 'Unexpected spread', DUPLICATE_LABEL: (label: string, loc: undefined | SourceLocation) => ({ diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies.test.md b/packages/@romejs/js-compiler/api/analyzeDependencies.test.md index 7328dd2e773..5ee06788229 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies.test.md +++ b/packages/@romejs/js-compiler/api/analyzeDependencies.test.md @@ -33,22 +33,26 @@ Object { ] diagnostics: Array [ Object { - category: 'analyzeDependencies/cjsExportInES' - filename: 'unknown' - language: 'js' - message: 'You cannot use CommonJS exports in an ES module' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'analyzeDependencies'}] - end: Object { - column: 25 - index: 26 - line: 2 + description: Object { + category: 'analyzeDependencies/cjsExportInES' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'You cannot use CommonJS exports in an ES module'} } - start: Object { - column: 6 - index: 7 - line: 2 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 25 + index: 26 + line: 2 + } + start: Object { + column: 6 + index: 7 + line: 2 + } } } ] @@ -149,32 +153,35 @@ Object { syntax: Array [] diagnostics: Array [ Object { - category: 'parse/js' - filename: 'unknown' - message: 'import and export can only appear in a module' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 31 - index: 32 - line: 2 - } - start: Object { - column: 6 - index: 7 - line: 2 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'import and export can only appear in a module'} + advice: Array [ + log { + category: 'info' + message: 'Change the extension to .mjs to turn this file into a module' + } + log { + category: 'info' + message: 'Add "type": "module" to your ' + } + ] } - advice: Array [ - log { - category: 'info' - message: 'Change the extension to .mjs to turn this file into a module' + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 31 + index: 32 + line: 2 } - log { - category: 'info' - message: 'Add "type": "module" to your ' + start: Object { + column: 6 + index: 7 + line: 2 } - ] + } } ] exports: Array [ diff --git a/packages/@romejs/js-compiler/suppressions.test.md b/packages/@romejs/js-compiler/suppressions.test.md index 2485b6247f6..8d4206bdea0 100644 --- a/packages/@romejs/js-compiler/suppressions.test.md +++ b/packages/@romejs/js-compiler/suppressions.test.md @@ -6,27 +6,31 @@ ```javascript Object { - diagnostics: Array [ + suppressions: Array [ Object { - category: 'suppressions/duplicate' - filename: 'unknown' - message: 'Duplicate suppression category foo' - end: Object { - column: 0 - index: 0 - line: 1 - } - start: Object { - column: 0 - index: 0 - line: 1 + category: 'foo' + loc: Object { + filename: 'unknown' + end: Object { + column: 0 + index: 0 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] - suppressions: Array [ + diagnostics: Array [ Object { - category: 'foo' - loc: Object { + description: Object { + category: 'suppressions/duplicate' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Duplicate suppression category foo'} + } + location: Object { filename: 'unknown' end: Object { column: 0 @@ -295,25 +299,29 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'suppressions/incorrectPrefix' - filename: 'unknown' - message: 'Invalid suppression prefix rome-ignore' - end: Object { - column: 0 - index: 0 - line: 1 + description: Object { + category: 'suppressions/incorrectPrefix' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Invalid suppression prefix rome-ignore'} + advice: Array [ + log { + category: 'info' + message: 'Did you mean rome-suppress?' + } + ] } - start: Object { - column: 0 - index: 0 - line: 1 - } - advice: Array [ - log { - category: 'info' - message: 'Did you mean rome-suppress?' + location: Object { + filename: 'unknown' + end: Object { + column: 0 + index: 0 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 } - ] + } } ] } diff --git a/packages/@romejs/js-compiler/transforms/lint/getterReturn.test.md b/packages/@romejs/js-compiler/transforms/lint/getterReturn.test.md index 323a823aeb4..c5c7e321372 100644 --- a/packages/@romejs/js-compiler/transforms/lint/getterReturn.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/getterReturn.test.md @@ -12,22 +12,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/getterReturn' - filename: 'unknown' - language: 'js' - message: 'Expected a \'return\' at end of a getter method but got empty block' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 7 - index: 70 - line: 5 + description: Object { + category: 'lint/getterReturn' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Expected a \'return\' at end of a getter method but got empty block'} } - start: Object { - column: 17 - index: 32 - line: 3 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 7 + index: 70 + line: 5 + } + start: Object { + column: 17 + index: 32 + line: 3 + } } } ] @@ -42,22 +46,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/getterReturn' - filename: 'unknown' - language: 'js' - message: 'Expected a \'return\' at end of a getter method but got empty block' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 7 - index: 77 - line: 6 + description: Object { + category: 'lint/getterReturn' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Expected a \'return\' at end of a getter method but got empty block'} } - start: Object { - column: 17 - index: 39 - line: 4 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 7 + index: 77 + line: 6 + } + start: Object { + column: 17 + index: 39 + line: 4 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.test.md b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.test.md index 80e18de6942..5809b3a8037 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.test.md @@ -12,22 +12,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noAsyncPromiseExecutor' - filename: 'unknown' - language: 'js' - message: 'Promise executor functions should not be async.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 35 - index: 35 - line: 1 + description: Object { + category: 'lint/noAsyncPromiseExecutor' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Promise executor functions should not be async.'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 35 + index: 35 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } ] @@ -42,22 +46,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noAsyncPromiseExecutor' - filename: 'unknown' - language: 'js' - message: 'Promise executor functions should not be async.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 26 - index: 26 - line: 1 + description: Object { + category: 'lint/noAsyncPromiseExecutor' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Promise executor functions should not be async.'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 26 + index: 26 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } ] @@ -72,22 +80,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noAsyncPromiseExecutor' - filename: 'unknown' - language: 'js' - message: 'Promise executor functions should not be async.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 30 - index: 30 - line: 1 + description: Object { + category: 'lint/noAsyncPromiseExecutor' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Promise executor functions should not be async.'} } - start: Object { - column: 16 - index: 16 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 30 + index: 30 + line: 1 + } + start: Object { + column: 16 + index: 16 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.md b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.md new file mode 100644 index 00000000000..5239a935402 --- /dev/null +++ b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.md @@ -0,0 +1,50 @@ +# `noCompareNegZero.test.ts` + +**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.ts --update-snapshots` to update. + +## `disallows comparing negative zero` + +### `0` + +```javascript +Object { + src: '(1 >= -0)' + suppressions: Array [] + diagnostics: Array [ + Object { + origins: Array [Object {category: 'lint'}] + description: Object { + category: 'lint/noCompareNegZero' + fixable: false + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Do not use the \'>=\' operator to compare against -0'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 8 + index: 8 + line: 1 + } + start: Object { + column: 1 + index: 1 + line: 1 + } + } + } + ] +} +``` + +### `1` + +```javascript +Object { + diagnostics: Array [] + src: '(1 >= 0)' + suppressions: Array [] +} +``` diff --git a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.ts b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.ts index 62098f7e1d9..56692a3fe46 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.test.ts @@ -14,29 +14,8 @@ test('disallows comparing negative zero', async (t) => { const sourceTextB = '(1 >= 0)'; const res1 = await testLint(sourceTextA); - t.looksLike(res1.diagnostics, [ - { - category: 'lint/noCompareNegZero', - filename: 'unknown', - fixable: true, - language: 'js', - message: 'Do not use the \'>=\' operator to compare against -0', - mtime: undefined, - sourceType: 'module', - origins: [{category: 'lint'}], - end: { - column: 8, - index: 8, - line: 1, - }, - start: { - column: 1, - index: 1, - line: 1, - }, - }, - ]); + t.snapshot(res1); const res2 = await testLint(sourceTextB); - t.looksLike(res2.diagnostics, []); + t.snapshot(res2); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.test.md b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.test.md index 04ba398b7be..f3ff2835121 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.test.md @@ -12,22 +12,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noCondAssign' - filename: 'unknown' - language: 'js' - message: 'Cannot assign variable in loop condition' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 5 - index: 61 - line: 3 + description: Object { + category: 'lint/noCondAssign' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Cannot assign variable in loop condition'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 5 + index: 61 + line: 3 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] @@ -42,22 +46,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noCondAssign' - filename: 'unknown' - language: 'js' - message: 'Cannot assign variable in loop condition' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 5 - index: 48 - line: 3 + description: Object { + category: 'lint/noCondAssign' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Cannot assign variable in loop condition'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 5 + index: 48 + line: 3 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] @@ -72,59 +80,68 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'parse/js' - filename: 'unknown' - message: 'Unclosed while test' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 6 - index: 6 - line: 1 - } - start: Object { - column: 6 - index: 6 - line: 1 - } - advice: Array [ - log { - category: 'info' - message: 'We expected to find the closing character ) here' + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 6 + index: 6 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 } - frame { - filename: 'unknown' - end: Object { - column: 19 - index: 19 - line: 1 + } + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unclosed while test'} + advice: Array [ + log { + category: 'info' + message: 'We expected to find the closing character ) here' } - start: Object { - column: 19 - index: 19 - line: 1 + frame { + location: Object { + filename: 'unknown' + end: Object { + column: 19 + index: 19 + line: 1 + } + start: Object { + column: 19 + index: 19 + line: 1 + } + } } - } - ] + ] + } } Object { - category: 'lint/noCondAssign' - filename: 'unknown' - language: 'js' - message: 'Cannot assign variable in loop condition' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 5 - index: 51 - line: 3 + description: Object { + category: 'lint/noCondAssign' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Cannot assign variable in loop condition'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 5 + index: 51 + line: 3 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] @@ -139,22 +156,24 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'unknown' - message: 'Unterminated string constant' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 23 - index: 28 - line: 2 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unterminated string constant'} } - start: Object { - column: 23 - index: 28 - line: 2 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 23 + index: 28 + line: 2 + } + start: Object { + column: 23 + index: 28 + line: 2 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.test.md b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.test.md index cdab71e6f66..fe45260b2b1 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.test.md @@ -12,22 +12,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noDanglingBackslash' - filename: 'unknown' - language: 'js' - message: 'Dangling backslash in a regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 12 - index: 13 - line: 1 - } - start: Object { - column: 11 - index: 11 - line: 1 + description: Object { + category: 'lint/noDanglingBackslash' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Dangling backslash in a regular expression'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 12 + index: 13 + line: 1 + } + start: Object { + column: 11 + index: 11 + line: 1 + } } } ] @@ -42,22 +46,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noDanglingBackslash' - filename: 'unknown' - language: 'js' - message: 'Dangling backslash in a regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 14 - index: 15 - line: 1 - } - start: Object { - column: 13 - index: 13 - line: 1 + description: Object { + category: 'lint/noDanglingBackslash' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Dangling backslash in a regular expression'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 14 + index: 15 + line: 1 + } + start: Object { + column: 13 + index: 13 + line: 1 + } } } ] @@ -72,60 +80,70 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'unknown' - message: 'Expecting Unicode escape sequence \\uXXXX' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 17 - index: 17 - line: 1 - } - start: Object { - column: 17 - index: 17 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Expecting Unicode escape sequence \\uXXXX'} + } + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 17 + index: 17 + line: 1 + } + start: Object { + column: 17 + index: 17 + line: 1 + } } } Object { - category: 'lint/noDanglingBackslash' - filename: 'unknown' - language: 'js' - message: 'Dangling backslash in a regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 14 - index: 15 - line: 1 - } - start: Object { - column: 13 - index: 13 - line: 1 + description: Object { + category: 'lint/noDanglingBackslash' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Dangling backslash in a regular expression'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 14 + index: 15 + line: 1 + } + start: Object { + column: 13 + index: 13 + line: 1 + } } } Object { - category: 'lint/undeclaredVariables' - filename: 'unknown' - language: 'js' - message: 'Undeclared variable \0' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 18 - index: 18 - line: 1 - } - start: Object { - column: 16 - index: 16 - line: 1 + description: Object { + category: 'lint/undeclaredVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Undeclared variable \0'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 18 + index: 18 + line: 1 + } + start: Object { + column: 16 + index: 16 + line: 1 + } } } ] @@ -140,60 +158,70 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'unknown' - message: 'Expecting Unicode escape sequence \\uXXXX' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 17 - index: 17 - line: 1 - } - start: Object { - column: 17 - index: 17 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Expecting Unicode escape sequence \\uXXXX'} + } + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 17 + index: 17 + line: 1 + } + start: Object { + column: 17 + index: 17 + line: 1 + } } } Object { - category: 'lint/noDanglingBackslash' - filename: 'unknown' - language: 'js' - message: 'Dangling backslash in a regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 14 - index: 15 - line: 1 - } - start: Object { - column: 13 - index: 13 - line: 1 + description: Object { + category: 'lint/noDanglingBackslash' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Dangling backslash in a regular expression'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 14 + index: 15 + line: 1 + } + start: Object { + column: 13 + index: 13 + line: 1 + } } } Object { - category: 'lint/undeclaredVariables' - filename: 'unknown' - language: 'js' - message: 'Undeclared variable \0' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 18 - index: 18 - line: 1 - } - start: Object { - column: 16 - index: 16 - line: 1 + description: Object { + category: 'lint/undeclaredVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Undeclared variable \0'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 18 + index: 18 + line: 1 + } + start: Object { + column: 16 + index: 16 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noDebugger.test.md b/packages/@romejs/js-compiler/transforms/lint/noDebugger.test.md index 624612a2e0c..e5a18945b1b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDebugger.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noDebugger.test.md @@ -7,23 +7,27 @@ ```javascript Array [ Object { - category: 'lint/noDebugger' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Unexpected \'debugger\' statement' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + category: 'lint/noDebugger' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected \'debugger\' statement'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.md b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.md new file mode 100644 index 00000000000..a3e5d32adbb --- /dev/null +++ b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.md @@ -0,0 +1,37 @@ +# `noDeleteVars.test.ts` + +**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.ts --update-snapshots` to update. + +## `no delete vars` + +```javascript +Object { + src: '\n const foo = "test";\n delete foo;\n ' + suppressions: Array [] + diagnostics: Array [ + Object { + origins: Array [Object {category: 'lint'}] + description: Object { + category: 'lint/noDeleteVars' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Variables should not be deleted.'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'script' + end: Object { + column: 14 + index: 39 + line: 3 + } + start: Object { + column: 4 + index: 29 + line: 3 + } + } + } + ] +} +``` diff --git a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.ts b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.ts index 3c97b49f58d..6f1074cf0c5 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.test.ts @@ -14,17 +14,5 @@ test('no delete vars', async (t) => { delete foo; `, false, 'script'); - t.looksLike(res.diagnostics, [ - { - category: 'lint/noDeleteVars', - message: 'Variables should not be deleted.', - mtime: undefined, - filename: 'unknown', - start: {index: 29, line: 3, column: 4}, - end: {index: 39, line: 3, column: 14}, - language: 'js', - sourceType: 'script', - origins: [{category: 'lint'}], - }, - ]); + t.snapshot(res); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.test.md b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.test.md index 6a98eb6a319..a6acda81744 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.test.md @@ -10,93 +10,107 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noDuplicateGroupNamesInRegularExpressions' - filename: 'unknown' - language: 'js' - message: 'Duplicate group name month in regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 16 - index: 16 - line: 1 - } - start: Object { - column: 1 - index: 1 - line: 1 - } - advice: Array [ - log { - category: 'info' - message: 'Defined again here' + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 16 + index: 16 + line: 1 } - frame { - filename: 'unknown' - end: Object { - column: 47 - index: 47 - line: 1 - } - start: Object { - column: 32 - index: 32 - line: 1 - } + start: Object { + column: 1 + index: 1 + line: 1 } - frame { - filename: 'unknown' - end: Object { - column: 99 - index: 99 - line: 1 + } + description: Object { + category: 'lint/noDuplicateGroupNamesInRegularExpressions' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Duplicate group name month in regular expression'} + advice: Array [ + log { + category: 'info' + message: 'Defined already here' } - start: Object { - column: 85 - index: 85 - line: 1 + frame { + location: Object { + filename: 'unknown' + end: Object { + column: 47 + index: 47 + line: 1 + } + start: Object { + column: 32 + index: 32 + line: 1 + } + } } - } - ] + frame { + location: Object { + filename: 'unknown' + end: Object { + column: 99 + index: 99 + line: 1 + } + start: Object { + column: 85 + index: 85 + line: 1 + } + } + } + ] + } } Object { - category: 'lint/noDuplicateGroupNamesInRegularExpressions' - filename: 'unknown' - language: 'js' - message: 'Duplicate group name year in regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 31 - index: 31 - line: 1 - } - start: Object { - column: 17 - index: 17 - line: 1 - } - advice: Array [ - log { - category: 'info' - message: 'Defined again here' + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 31 + index: 31 + line: 1 + } + start: Object { + column: 17 + index: 17 + line: 1 } - frame { - filename: 'unknown' - end: Object { - column: 62 - index: 62 - line: 1 + } + description: Object { + category: 'lint/noDuplicateGroupNamesInRegularExpressions' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Duplicate group name year in regular expression'} + advice: Array [ + log { + category: 'info' + message: 'Defined already here' } - start: Object { - column: 48 - index: 48 - line: 1 + frame { + location: Object { + filename: 'unknown' + end: Object { + column: 62 + index: 62 + line: 1 + } + start: Object { + column: 48 + index: 48 + line: 1 + } + } } - } - ] + ] + } } ] } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.md b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.md new file mode 100644 index 00000000000..b9916a17074 --- /dev/null +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.md @@ -0,0 +1,37 @@ +# `noDuplicateKeys.test.ts` + +**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.ts --update-snapshots` to update. + +## `no duplicate keys` + +```javascript +Object { + src: '\n const foo = {\n test: true,\n test2: true,\n test: false,\n }\n\n // mark const as used\n console.log(foo);\n ' + suppressions: Array [] + diagnostics: Array [ + Object { + origins: Array [Object {category: 'lint'}] + description: Object { + category: 'lint/noDuplicateKeys' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Duplicate key test'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 17 + index: 73 + line: 5 + } + start: Object { + column: 6 + index: 62 + line: 5 + } + } + } + ] +} +``` diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.ts index caa2767c13b..0bf93ebe37b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.test.ts @@ -20,25 +20,5 @@ test('no duplicate keys', async (t) => { console.log(foo); `); - t.looksLike(res.diagnostics, [ - { - category: 'lint/noDuplicateKeys', - filename: 'unknown', - language: 'js', - message: 'Duplicate key test', - mtime: undefined, - sourceType: 'module', - origins: [{category: 'lint'}], - end: { - column: 17, - index: 73, - line: 5, - }, - start: { - column: 6, - index: 62, - line: 5, - }, - }, - ]); + t.snapshot(res); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.test.md b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.test.md index 7ed7661fb20..2c96e8c2ea2 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.test.md @@ -12,23 +12,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 16 - index: 16 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 15 - index: 15 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 16 + index: 16 + line: 1 + } + start: Object { + column: 15 + index: 15 + line: 1 + } } } ] @@ -43,23 +47,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 16 - index: 16 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 14 - index: 14 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 16 + index: 16 + line: 1 + } + start: Object { + column: 14 + index: 14 + line: 1 + } } } ] @@ -74,23 +82,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 33 - index: 33 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 32 - index: 32 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 33 + index: 33 + line: 1 + } + start: Object { + column: 32 + index: 32 + line: 1 + } } } ] @@ -105,23 +117,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 13 - index: 13 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 11 - index: 11 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 13 + index: 13 + line: 1 + } + start: Object { + column: 11 + index: 11 + line: 1 + } } } ] @@ -136,23 +152,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 14 - index: 14 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 13 - index: 13 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 14 + index: 14 + line: 1 + } + start: Object { + column: 13 + index: 13 + line: 1 + } } } ] @@ -167,23 +187,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noEmptyCharacterClass' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Empty character classes in regular expressions are not allowed' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 21 - index: 21 - line: 1 + description: Object { + category: 'lint/noEmptyCharacterClass' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Empty character classes in regular expressions are not allowed'} } - start: Object { - column: 20 - index: 20 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 21 + index: 21 + line: 1 + } + start: Object { + column: 20 + index: 20 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.test.md b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.test.md index da54d6b0d0b..d165ffc56ba 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.test.md @@ -9,22 +9,26 @@ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 14 - index: 14 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 11 - index: 11 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 14 + index: 14 + line: 1 + } + start: Object { + column: 11 + index: 11 + line: 1 + } } } ] @@ -35,22 +39,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 15 - index: 15 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 15 + index: 15 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } ] @@ -61,22 +69,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 21 - index: 21 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 18 - index: 18 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 21 + index: 21 + line: 1 + } + start: Object { + column: 18 + index: 18 + line: 1 + } } } ] @@ -87,22 +99,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 21 - index: 21 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 18 - index: 18 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 21 + index: 21 + line: 1 + } + start: Object { + column: 18 + index: 18 + line: 1 + } } } ] @@ -113,22 +129,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 21 - index: 21 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 18 - index: 18 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 21 + index: 21 + line: 1 + } + start: Object { + column: 18 + index: 18 + line: 1 + } } } ] @@ -139,22 +159,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 27 - index: 27 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 24 - index: 24 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 27 + index: 27 + line: 1 + } + start: Object { + column: 24 + index: 24 + line: 1 + } } } ] @@ -165,22 +189,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 33 - index: 33 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 30 - index: 30 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 33 + index: 33 + line: 1 + } + start: Object { + column: 30 + index: 30 + line: 1 + } } } ] @@ -191,22 +219,26 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 31 - index: 31 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 28 - index: 28 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 31 + index: 31 + line: 1 + } + start: Object { + column: 28 + index: 28 + line: 1 + } } } ] @@ -217,41 +249,49 @@ Array [ ```javascript Array [ Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 31 - index: 31 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 28 - index: 28 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 31 + index: 31 + line: 1 + } + start: Object { + column: 28 + index: 28 + line: 1 + } } } Object { - category: 'lint/noExplicitAny' - filename: 'unknown' - language: 'js' - message: 'Unexpected any. Specify a different type.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 44 - index: 44 - line: 1 + description: Object { + category: 'lint/noExplicitAny' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected any. Specify a different type.'} } - start: Object { - column: 41 - index: 41 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 44 + index: 44 + line: 1 + } + start: Object { + column: 41 + index: 41 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.test.md b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.test.md index 6c395308d99..f79db154e8f 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.test.md @@ -12,30 +12,34 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noMultipleSpacesInRegularExpressionLiterals' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Unclear multiple spaces in regular expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 5 - index: 5 - line: 1 + description: Object { + category: 'lint/noMultipleSpacesInRegularExpressionLiterals' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unclear multiple spaces in regular expression'} + advice: Array [ + log { + category: 'info' + message: 'It\'s hard to visually count the amount of spaces, it\'s clearer if you use a quantifier instead. eg / {3}/' + } + ] } - start: Object { - column: 4 - index: 4 - line: 1 - } - advice: Array [ - log { - category: 'info' - message: 'It\'s hard to visually count the amount of spaces, it\'s clearer if you use a quantifier instead. eg / {3}/' + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 5 + index: 5 + line: 1 + } + start: Object { + column: 4 + index: 4 + line: 1 } - ] + } } ] } diff --git a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.md b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.md new file mode 100644 index 00000000000..51b0de92ce5 --- /dev/null +++ b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.md @@ -0,0 +1,37 @@ +# `noTemplateCurlyInString.test.ts` + +**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.ts --update-snapshots` to update. + +## `no template curly in string` + +```javascript +Object { + src: '\n const user = "Faustina";\n const helloUser = "Hello, ${user}!";\n\n // mark consts as used\n console.log(user, helloUser)\n ' + suppressions: Array [] + diagnostics: Array [ + Object { + origins: Array [Object {category: 'lint'}] + description: Object { + category: 'lint/noTemplateCurlyInString' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected template string expression.'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 39 + index: 69 + line: 3 + } + start: Object { + column: 22 + index: 52 + line: 3 + } + } + } + ] +} +``` diff --git a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.ts b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.ts index a362df22669..c7142d7af13 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.test.ts @@ -15,19 +15,6 @@ test('no template curly in string', async (t) => { // mark consts as used console.log(user, helloUser) - `); - - t.looksLike(res.diagnostics, [ - { - category: 'lint/noTemplateCurlyInString', - filename: 'unknown', - language: 'js', - message: 'Unexpected template string expression.', - mtime: undefined, - sourceType: 'module', - origins: [{category: 'lint'}], - end: {column: 39, index: 69, line: 3}, - start: {column: 22, index: 52, line: 3}, - }, - ]); + `); + t.snapshot(res); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/noVar.test.md b/packages/@romejs/js-compiler/transforms/lint/noVar.test.md index 9b0a3bc6ae1..39ca696070d 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noVar.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/noVar.test.md @@ -10,22 +10,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/noVar' - filename: 'unknown' - language: 'js' - message: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 11 - index: 11 - line: 1 + description: Object { + category: 'lint/noVar' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 11 + index: 11 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/noVar.test.ts b/packages/@romejs/js-compiler/transforms/lint/noVar.test.ts index 28f743a996b..3c00d4a6619 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noVar.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noVar.test.ts @@ -11,27 +11,4 @@ import {testLint} from '../../api/lint.test'; test('disallow var', async (t) => { const res = await testLint('var foobar;\nfoobar'); t.snapshot(res); - - // Redundant because of the snapshot above, but this is what we actually care about - t.looksLike(res.diagnostics, [ - { - category: 'lint/noVar', - filename: 'unknown', - language: 'js', - message: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.', - mtime: undefined, - sourceType: 'module', - origins: [{category: 'lint'}], - end: { - column: 11, - index: 11, - line: 1, - }, - start: { - column: 0, - index: 0, - line: 1, - }, - }, - ]); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.test.md b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.test.md index 075cc41ece4..d6fa3e7e328 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.test.md @@ -12,42 +12,50 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/preferFunctionDeclarations' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Use a function declaration instead of a const function' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 26 - index: 26 - line: 1 + description: Object { + category: 'lint/preferFunctionDeclarations' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Use a function declaration instead of a const function'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 26 + index: 26 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused variable foo' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable foo'} } - start: Object { - column: 6 - index: 6 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] @@ -62,42 +70,50 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/preferFunctionDeclarations' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Use a function declaration instead of a const function' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 20 - index: 20 - line: 1 + description: Object { + category: 'lint/preferFunctionDeclarations' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Use a function declaration instead of a const function'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 20 + index: 20 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused variable foo' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable foo'} } - start: Object { - column: 6 - index: 6 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] @@ -112,22 +128,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused variable foo' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable foo'} } - start: Object { - column: 6 - index: 6 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] @@ -142,61 +162,73 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused function bar' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 31 - index: 31 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused function bar'} } - start: Object { - column: 28 - index: 28 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 31 + index: 31 + line: 1 + } + start: Object { + column: 28 + index: 28 + line: 1 + } } } Object { - category: 'lint/preferFunctionDeclarations' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Use a function declaration instead of a const function' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 42 - index: 42 - line: 1 + description: Object { + category: 'lint/preferFunctionDeclarations' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Use a function declaration instead of a const function'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 42 + index: 42 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused variable foo' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable foo'} } - start: Object { - column: 6 - index: 6 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] @@ -211,22 +243,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/unusedVariables' - filename: 'unknown' - language: 'js' - message: 'Unused variable foo' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 17 - index: 17 - line: 1 - } - start: Object { - column: 6 - index: 6 - line: 1 + description: Object { + category: 'lint/unusedVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable foo'} + } + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 17 + index: 17 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.test.md b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.test.md index 6df14a7bced..7d8ed6e2ec4 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.test.md @@ -12,22 +12,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/preferTemplate' - filename: 'unknown' - language: 'js' - message: 'You\'re using string concatenation when template literals are preferred' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 42 - index: 42 - line: 1 + description: Object { + category: 'lint/preferTemplate' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'You\'re using string concatenation when template literals are preferred'} } - start: Object { - column: 31 - index: 31 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 42 + index: 42 + line: 1 + } + start: Object { + column: 31 + index: 31 + line: 1 + } } } ] @@ -42,22 +46,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/preferTemplate' - filename: 'unknown' - language: 'js' - message: 'You\'re using string concatenation when template literals are preferred' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 27 - index: 27 - line: 1 + description: Object { + category: 'lint/preferTemplate' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'You\'re using string concatenation when template literals are preferred'} } - start: Object { - column: 12 - index: 12 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 27 + index: 27 + line: 1 + } + start: Object { + column: 12 + index: 12 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/sparseArray.test.md b/packages/@romejs/js-compiler/transforms/lint/sparseArray.test.md index 9f0286ad3e9..d358c8f1a29 100644 --- a/packages/@romejs/js-compiler/transforms/lint/sparseArray.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/sparseArray.test.md @@ -10,23 +10,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/sparseArray' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Your array contains an empty slot' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 6 - index: 6 - line: 1 + description: Object { + category: 'lint/sparseArray' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Your array contains an empty slot'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 6 + index: 6 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.md b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.md index 288d1343228..dd748c9327b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.md @@ -10,22 +10,26 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/undeclaredVariables' - filename: 'unknown' - language: 'js' - message: 'Undeclared variable foobar' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 6 - index: 6 - line: 1 + description: Object { + category: 'lint/undeclaredVariables' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Undeclared variable foobar'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 6 + index: 6 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] diff --git a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.ts b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.ts index 6e81460a0b4..222995db732 100644 --- a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.ts +++ b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariable.test.ts @@ -11,27 +11,4 @@ import {testLint} from '../../api/lint.test'; test('undeclared variable', async (t) => { const res = await testLint('foobar;'); t.snapshot(res); - - // Redundant because of the snapshot above, but this is what we actually care about - t.looksLike(res.diagnostics, [ - { - category: 'lint/undeclaredVariables', - filename: 'unknown', - language: 'js', - message: 'Undeclared variable foobar', - mtime: undefined, - sourceType: 'module', - origins: [{category: 'lint'}], - end: { - column: 6, - index: 6, - line: 1, - }, - start: { - column: 0, - index: 0, - line: 1, - }, - }, - ]); }); diff --git a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.test.md b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.test.md index 2ebb752cde1..06bdae6f3d6 100644 --- a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.test.md +++ b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.test.md @@ -10,23 +10,27 @@ Object { suppressions: Array [] diagnostics: Array [ Object { - category: 'lint/unsafeNegation' - filename: 'unknown' - fixable: true - language: 'js' - message: 'Unsafe usage of negation operator in left side of binary expression' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'lint'}] - end: Object { - column: 11 - index: 11 - line: 1 + description: Object { + category: 'lint/unsafeNegation' + fixable: true + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unsafe usage of negation operator in left side of binary expression'} } - start: Object { - column: 0 - index: 0 - line: 1 + location: Object { + filename: 'unknown' + language: 'js' + mtime: undefined + sourceType: 'module' + end: Object { + column: 11 + index: 11 + line: 1 + } + start: Object { + column: 0 + index: 0 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/parser/lval.ts b/packages/@romejs/js-parser/parser/lval.ts index c58330688f3..a3abb09b6d1 100644 --- a/packages/@romejs/js-parser/parser/lval.ts +++ b/packages/@romejs/js-parser/parser/lval.ts @@ -676,11 +676,13 @@ export function filterSpread( for (let i = 0; i < elems.length; i++) { const elem = elems[i]; if (elem.type === 'SpreadElement') { + parser.addDiagnostic({ + description: descriptions.JS_PARSER.UNEXPECTED_SPREAD, + }); + elems[i] = toReferenceIdentifier(parser, parser.createUnknownIdentifier( 'spread substitute', )); - - throw new Error('Is this even ever possible?'); } } // @ts-ignore Technically wrong but we removed all SpreadElement diff --git a/packages/@romejs/js-parser/test-fixtures/core/uncategorised/321/output.txt b/packages/@romejs/js-parser/test-fixtures/core/uncategorised/321/output.txt index b769bf7ea14..17221de48d3 100644 --- a/packages/@romejs/js-parser/test-fixtures/core/uncategorised/321/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/core/uncategorised/321/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Expected a semicolon or a line terminator' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 1 - index: 1 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Expected a semicolon or a line terminator'} } - start: Object { - column: 0 - index: 2 - line: 2 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 1 + index: 1 + line: 1 + } + start: Object { + column: 0 + index: 2 + line: 2 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/196/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/196/output.txt index b0009a689d6..64507deb625 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/196/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/196/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Range values reversed. Start char code is greater than end char code' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 21 - index: 21 - line: 1 + description: Object { + category: 'parse/regex' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected character u'} } - start: Object { - column: 8 - index: 8 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 33 + index: 33 + line: 1 + } + start: Object { + column: 33 + index: 33 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/307/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/307/output.txt index ff58cbf0b05..6b3b2a2ccea 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/307/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/307/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 5 - index: 5 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 4 - index: 4 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 5 + index: 5 + line: 1 + } + start: Object { + column: 4 + index: 4 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/308/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/308/output.txt index dbf3d32a83a..9124384648e 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/308/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/308/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 5 - index: 5 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 4 - index: 4 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 5 + index: 5 + line: 1 + } + start: Object { + column: 4 + index: 4 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/309/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/309/output.txt index 38c47ebc1dd..679e77a3c22 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/309/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/309/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 12 - index: 12 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 11 - index: 11 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 12 + index: 12 + line: 1 + } + start: Object { + column: 11 + index: 11 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/310/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/310/output.txt index 76b5f764ada..204dce90ff4 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/310/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/310/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 9 - index: 9 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 8 - index: 8 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 9 + index: 9 + line: 1 + } + start: Object { + column: 8 + index: 8 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/393/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/393/output.txt index 16e5768c6d8..e32c7ec51bf 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/393/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/393/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 7 - index: 7 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 6 - index: 6 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 7 + index: 7 + line: 1 + } + start: Object { + column: 6 + index: 6 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/394/output.txt b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/394/output.txt index 53112e0a6fa..2ee20607e04 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/394/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2015/uncategorised/394/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Invalid parenthesized binding' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 2 - index: 9 - line: 2 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Invalid parenthesized binding'} } - start: Object { - column: 1 - index: 8 - line: 2 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 2 + index: 9 + line: 2 + } + start: Object { + column: 1 + index: 8 + line: 2 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/27/output.txt b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/27/output.txt index de494084e75..ba955bdb109 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/27/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/27/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 22 - index: 22 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 21 - index: 21 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 22 + index: 22 + line: 1 + } + start: Object { + column: 21 + index: 21 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/32/output.txt b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/32/output.txt index 506fb1aee77..55eff6d0805 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/32/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/32/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 28 - index: 28 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 27 - index: 27 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 28 + index: 28 + line: 1 + } + start: Object { + column: 27 + index: 27 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/object-default-params/output.txt b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/object-default-params/output.txt index f291c4ad05c..aa285da64e3 100644 --- a/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/object-default-params/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/es2017/async-functions/object-default-params/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 23 - index: 23 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 22 - index: 22 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 23 + index: 23 + line: 1 + } + start: Object { + column: 22 + index: 22 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-01/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-01/output.txt index bee29c2ad7e..094cd7ff583 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-01/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-01/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 6 - index: 6 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 5 - index: 5 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 6 + index: 6 + line: 1 + } + start: Object { + column: 5 + index: 5 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-nested-cover-grammar/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-nested-cover-grammar/output.txt index b4aab38562f..34e495cd433 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-nested-cover-grammar/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-arrow-function/object-binding-pattern-nested-cover-grammar/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 24 - index: 24 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 23 - index: 23 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 24 + index: 24 + line: 1 + } + start: Object { + column: 23 + index: 23 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-class/migrated_0019/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-class/migrated_0019/output.txt index 19a0219413e..dbb437884e2 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-class/migrated_0019/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-class/migrated_0019/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Duplicate constructor in the same class' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 42 - index: 42 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Duplicate constructor in the same class'} } - start: Object { - column: 27 - index: 27 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 42 + index: 42 + line: 1 + } + start: Object { + column: 27 + index: 27 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-array-pattern/nested-cover-grammar/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-array-pattern/nested-cover-grammar/output.txt index cdf805ab92b..c381c14e442 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-array-pattern/nested-cover-grammar/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-array-pattern/nested-cover-grammar/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 4 - index: 4 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 3 - index: 3 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 4 + index: 4 + line: 1 + } + start: Object { + column: 3 + index: 3 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-object-pattern/nested-cover-grammar/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-object-pattern/nested-cover-grammar/output.txt index c4f75bbeb0b..bf2e4a25e4f 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-object-pattern/nested-cover-grammar/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-destructuring-assignment-object-pattern/nested-cover-grammar/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.js' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 23 - index: 23 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 22 - index: 22 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 23 + index: 23 + line: 1 + } + start: Object { + column: 22 + index: 22 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-identifier-shorthand/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-identifier-shorthand/output.txt index 68e6579bf06..e0878f1d45f 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-identifier-shorthand/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-identifier-shorthand/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Redefinition of __proto__ property' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 29 - index: 29 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Redefinition of __proto__ property'} } - start: Object { - column: 20 - index: 20 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 29 + index: 29 + line: 1 + } + start: Object { + column: 20 + index: 20 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-literal-shorthand/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-literal-shorthand/output.txt index d6186a43f88..1f7abf767b9 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-literal-shorthand/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-literal-shorthand/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Redefinition of __proto__ property' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 31 - index: 31 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Redefinition of __proto__ property'} } - start: Object { - column: 22 - index: 22 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 31 + index: 31 + line: 1 + } + start: Object { + column: 22 + index: 22 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-identifier/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-identifier/output.txt index 7d8aef0710e..e52f86b72b0 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-identifier/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-identifier/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Redefinition of __proto__ property' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 23 - index: 23 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Redefinition of __proto__ property'} } - start: Object { - column: 14 - index: 14 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 23 + index: 23 + line: 1 + } + start: Object { + column: 14 + index: 14 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-literal/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-literal/output.txt index 607917bcfbf..e7fcadc4d4e 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-literal/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthand-literal/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Redefinition of __proto__ property' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 25 - index: 25 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Redefinition of __proto__ property'} } - start: Object { - column: 14 - index: 14 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 25 + index: 25 + line: 1 + } + start: Object { + column: 14 + index: 14 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthands/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthands/output.txt index 43c363cdbc2..a4c6f5ead97 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthands/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/es2015-object-initialiser/proto-shorthands/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Redefinition of __proto__ property' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 23 - index: 23 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Redefinition of __proto__ property'} } - start: Object { - column: 14 - index: 14 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 23 + index: 23 + line: 1 + } + start: Object { + column: 14 + index: 14 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-surrogate-pair/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-surrogate-pair/output.txt index 889001a0667..089f268019f 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-surrogate-pair/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-surrogate-pair/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Range values reversed. Start char code is greater than end char code' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 29 - index: 29 - line: 1 + description: Object { + category: 'parse/regex' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected character D'} } - start: Object { - column: 16 - index: 16 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 41 + index: 41 + line: 1 + } + start: Object { + column: 0 + index: 42 + line: 2 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-valid-range/output.txt b/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-valid-range/output.txt index 219f2509b26..51a9cadc64a 100644 --- a/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-valid-range/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/esprima/expression-primary-literal-regular-expression/u-flag-valid-range/output.txt @@ -23,22 +23,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Range values reversed. Start char code is greater than end char code' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 18 - index: 18 - line: 1 + description: Object { + category: 'parse/regex' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected character 6'} } - start: Object { - column: 15 - index: 15 - line: 1 + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 60 + index: 60 + line: 1 + } + start: Object { + column: 60 + index: 60 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/flow/optional-type/4/output.txt b/packages/@romejs/js-parser/test-fixtures/flow/optional-type/4/output.txt index c6a9432f519..7fda7b50b31 100644 --- a/packages/@romejs/js-parser/test-fixtures/flow/optional-type/4/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/flow/optional-type/4/output.txt @@ -26,22 +26,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Unknown start to an conditional consequent' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 16 - index: 16 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unknown start to an conditional consequent'} } - start: Object { - column: 16 - index: 16 - line: 1 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 16 + index: 16 + line: 1 + } + start: Object { + column: 16 + index: 16 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/flow/regression/issue-58/output.txt b/packages/@romejs/js-parser/test-fixtures/flow/regression/issue-58/output.txt index 9604e84547b..8fb6783b2c6 100644 --- a/packages/@romejs/js-parser/test-fixtures/flow/regression/issue-58/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/flow/regression/issue-58/output.txt @@ -25,22 +25,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'Missing conditional expression consequent separator' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 16 - index: 54 - line: 2 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Missing conditional expression consequent separator'} } - start: Object { - column: 16 - index: 54 - line: 2 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 16 + index: 54 + line: 2 + } + start: Object { + column: 16 + index: 54 + line: 2 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/flow/typecasts/works-in-array-pattern/output.txt b/packages/@romejs/js-parser/test-fixtures/flow/typecasts/works-in-array-pattern/output.txt index 61e01cd7f6a..4d4540154a2 100644 --- a/packages/@romejs/js-parser/test-fixtures/flow/typecasts/works-in-array-pattern/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/flow/typecasts/works-in-array-pattern/output.txt @@ -26,22 +26,24 @@ Program { } diagnostics: Array [ Object { - advice: undefined - category: 'parse/js' - filename: 'input.js' - message: 'The type cast expression is expected to be wrapped with parentheses' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 11 - index: 11 - line: 1 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'The type cast expression is expected to be wrapped with parentheses'} } - start: Object { - column: 2 - index: 2 - line: 1 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 11 + index: 11 + line: 1 + } + start: Object { + column: 2 + index: 2 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/jsx/basic/22/output.txt b/packages/@romejs/js-parser/test-fixtures/jsx/basic/22/output.txt index 31bc896a026..fdb7e2e7d81 100644 --- a/packages/@romejs/js-parser/test-fixtures/jsx/basic/22/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/jsx/basic/22/output.txt @@ -43,32 +43,35 @@ Program { ] diagnostics: Array [ Object { - category: 'parse/js' - filename: 'input.mjs' - message: 'import and export can only appear in a module' - mtime: undefined - sourceType: 'script' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 35 - index: 51 - line: 2 - } - start: Object { - column: 0 - index: 16 - line: 2 + description: Object { + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'import and export can only appear in a module'} + advice: Array [ + log { + category: 'info' + message: 'Change the extension to .mjs to turn this file into a module' + } + log { + category: 'info' + message: 'Add "type": "module" to your ' + } + ] } - advice: Array [ - log { - category: 'info' - message: 'Change the extension to .mjs to turn this file into a module' + location: Object { + mtime: undefined + sourceType: 'script' + end: Object { + column: 35 + index: 51 + line: 2 } - log { - category: 'info' - message: 'Add "type": "module" to your ' + start: Object { + column: 0 + index: 16 + line: 2 } - ] + } } ] body: Array [ diff --git a/packages/@romejs/js-parser/test-fixtures/typescript/arrow-function/destructuring/output.txt b/packages/@romejs/js-parser/test-fixtures/typescript/arrow-function/destructuring/output.txt index ea0ba741ecd..ac6f046b7ed 100644 --- a/packages/@romejs/js-parser/test-fixtures/typescript/arrow-function/destructuring/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/typescript/arrow-function/destructuring/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.ts' - message: 'Unexpected token, expected ","' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 6 - index: 6 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ,'} } - start: Object { - column: 5 - index: 5 - line: 1 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 6 + index: 6 + line: 1 + } + start: Object { + column: 5 + index: 5 + line: 1 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/typescript/export/declare/output.txt b/packages/@romejs/js-parser/test-fixtures/typescript/export/declare/output.txt index a95705542c6..14f4cde0c73 100644 --- a/packages/@romejs/js-parser/test-fixtures/typescript/export/declare/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/typescript/export/declare/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.ts' - message: 'Unexpected token, expected "("' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 25 - index: 57 - line: 2 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ('} } - start: Object { - column: 24 - index: 56 - line: 2 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 25 + index: 57 + line: 2 + } + start: Object { + column: 24 + index: 56 + line: 2 + } } } ] diff --git a/packages/@romejs/js-parser/test-fixtures/typescript/function/declare/output.txt b/packages/@romejs/js-parser/test-fixtures/typescript/function/declare/output.txt index 2903d48cbeb..d309c15cbe8 100644 --- a/packages/@romejs/js-parser/test-fixtures/typescript/function/declare/output.txt +++ b/packages/@romejs/js-parser/test-fixtures/typescript/function/declare/output.txt @@ -23,22 +23,25 @@ Program { } diagnostics: Array [ Object { - advice: Array [] - category: 'parse/js' - filename: 'input.ts' - message: 'Unexpected token, expected "("' - mtime: undefined - sourceType: 'module' origins: Array [Object {category: 'js-parser'}] - end: Object { - column: 18 - index: 18 - line: 1 + description: Object { + advice: Array [] + category: 'parse/js' + message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unexpected token, expected ('} } - start: Object { - column: 17 - index: 17 - line: 1 + location: Object { + mtime: undefined + sourceType: 'module' + end: Object { + column: 18 + index: 18 + line: 1 + } + start: Object { + column: 17 + index: 17 + line: 1 + } } } ] From ad319529adb4b942a3eb000bac665db2f72ee0b8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 22 Mar 2020 14:34:18 -0700 Subject: [PATCH 4/7] Rename pointer variables to "location" add description arg to Context.addDiagnostic --- .../cli-diagnostics/DiagnosticsPrinter.ts | 12 ++--- packages/@romejs/consume/Consumer.ts | 44 ++++++++----------- packages/@romejs/core/master/MasterRequest.ts | 28 ++++++------ .../@romejs/core/master/bundler/Bundler.ts | 6 +-- .../core/master/commands/_moduleSignature.ts | 2 +- .../master/commands/analyzeDependencies.ts | 2 +- .../@romejs/core/master/commands/compile.ts | 2 +- .../@romejs/core/master/commands/parse.ts | 2 +- .../@romejs/core/master/commands/resolve.ts | 2 +- .../master/dependencies/DependencyGraph.ts | 2 +- packages/@romejs/core/master/fs/Resolver.ts | 8 ++-- .../@romejs/core/master/fs/resolverSuggest.ts | 12 ++--- .../core/master/project/ProjectManager.ts | 8 ++-- packages/@romejs/core/master/web/index.ts | 4 +- packages/@romejs/diagnostics/derive.ts | 8 ++-- packages/@romejs/diagnostics/descriptions.ts | 4 +- packages/@romejs/diagnostics/helpers.ts | 4 +- packages/@romejs/js-analysis/api/check.ts | 19 ++++---- .../api/analyzeDependencies/index.ts | 7 +-- packages/@romejs/js-compiler/lib/Context.ts | 34 ++++++++------ packages/@romejs/js-compiler/lib/Path.ts | 5 --- .../js-compiler/transforms/compile/jsx.ts | 4 +- .../transforms/compile/transpile/classes.ts | 7 +-- .../lint/defaultExportSameBasename.ts | 7 +-- .../transforms/lint/emptyBlocks.ts | 7 +-- .../transforms/lint/getterReturn.ts | 7 +-- .../transforms/lint/noAsyncPromiseExecutor.ts | 7 +-- .../transforms/lint/noCompareNegZero.ts | 7 +-- .../transforms/lint/noCondAssign.ts | 4 +- ...noDanglingBackslashInRegularExpressions.ts | 7 +-- .../js-compiler/transforms/lint/noDebugger.ts | 5 +-- .../transforms/lint/noDeleteVars.ts | 4 +- .../js-compiler/transforms/lint/noDupeArgs.ts | 7 +-- .../transforms/lint/noDuplicateCase.ts | 7 +-- ...DuplicateGroupNamesInRegularExpressions.ts | 7 +-- .../transforms/lint/noDuplicateKeys.ts | 7 +-- .../transforms/lint/noEmptyCharacterClass.ts | 4 +- .../transforms/lint/noExplicitAny.ts | 4 +- .../transforms/lint/noExtraBooleanCast.ts | 4 +- .../transforms/lint/noFunctionAssign.ts | 4 +- .../transforms/lint/noImportAssign.ts | 4 +- .../js-compiler/transforms/lint/noLabelVar.ts | 4 +- ...ltipleSpacesInRegularExpressionLiterals.ts | 10 ++--- .../lint/noShadowRestrictedNames.ts | 7 +-- .../lint/noTemplateCurlyInString.ts | 7 +-- .../transforms/lint/noUnsafeFinally.ts | 7 +-- .../js-compiler/transforms/lint/noVar.ts | 4 +- .../lint/preferFunctionDeclarations.ts | 7 +-- .../transforms/lint/preferTemplate.ts | 4 +- .../transforms/lint/sparseArray.ts | 4 +- .../transforms/lint/undeclaredVariables.ts | 7 +-- .../transforms/lint/unsafeNegation.ts | 4 +- .../transforms/lint/unusedVariables.ts | 7 +-- 53 files changed, 192 insertions(+), 209 deletions(-) diff --git a/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts b/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts index 1f483c14749..83d84d6c0b1 100644 --- a/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts +++ b/packages/@romejs/cli-diagnostics/DiagnosticsPrinter.ts @@ -300,15 +300,15 @@ export default class DiagnosticsPrinter extends Error { if (advice !== undefined) { for (const item of advice) { if (item.type === 'frame') { - const {location: pointer} = item; - if (pointer.filename !== undefined && pointer.sourceText === + const {location} = item; + if (location.filename !== undefined && location.sourceText === undefined) { deps.push({ type: 'reference', - path: this.createFilePath(pointer.filename), - language: pointer.language, - sourceType: pointer.sourceType, - mtime: pointer.mtime, + path: this.createFilePath(location.filename), + language: location.language, + sourceType: location.sourceType, + mtime: location.mtime, }); } } diff --git a/packages/@romejs/consume/Consumer.ts b/packages/@romejs/consume/Consumer.ts index 561a5443e5e..9f751e86fdf 100644 --- a/packages/@romejs/consume/Consumer.ts +++ b/packages/@romejs/consume/Consumer.ts @@ -189,7 +189,7 @@ export default class Consumer { } } - getDiagnosticPointer( + getDiagnosticLocation( target: ConsumeSourceLocationRequestTarget = 'all', ): DiagnosticLocation { const {getDiagnosticPointer} = this.context; @@ -205,9 +205,9 @@ export default class Consumer { } getLocation(target?: ConsumeSourceLocationRequestTarget): SourceLocation { - const pointer = this.getDiagnosticPointer(target); - if (pointer === undefined || pointer.start === undefined || pointer.end === - undefined) { + const location = this.getDiagnosticLocation(target); + if (location === undefined || location.start === undefined || + location.end === undefined) { return { filename: this.filename, start: UNKNOWN_POSITION, @@ -215,9 +215,9 @@ export default class Consumer { }; } else { return { - filename: pointer.filename, - start: pointer.start, - end: pointer.end, + filename: location.filename, + start: location.start, + end: location.end, }; } } @@ -276,7 +276,7 @@ export default class Consumer { } wasInSource() { - return this.getDiagnosticPointer() !== undefined; + return this.getDiagnosticLocation() !== undefined; } generateUnexpectedMessage(msg: string, opts: UnexpectedConsumerOptions): string { @@ -305,11 +305,10 @@ export default class Consumer { unexpected(msg: string, opts: UnexpectedConsumerOptions = {}): DiagnosticsError { const {target = 'value'} = opts; - let loc: undefined | DiagnosticLocation = opts.loc; const {filename} = this; - let pointer = this.getDiagnosticPointer(target); - const fromSource = pointer !== undefined; + let location = this.getDiagnosticLocation(target); + const fromSource = location !== undefined; msg = this.generateUnexpectedMessage(msg, opts); @@ -328,9 +327,9 @@ export default class Consumer { // Go up the consumer tree and take the position from the first consumer found in the source let consumer: undefined | Consumer = this; do { - const possiblePointer = consumer.getDiagnosticPointer(target); - if (possiblePointer !== undefined) { - pointer = possiblePointer; + const possibleLocation = consumer.getDiagnosticLocation(target); + if (possibleLocation !== undefined) { + location = possibleLocation; break; } consumer = consumer.parent; @@ -355,16 +354,12 @@ export default class Consumer { } } - if (pointer === undefined) { - throw new Error(msg); + if (opts.loc !== undefined) { + location = opts.loc; } - if (loc === undefined) { - loc = { - filename: pointer.filename, - start: pointer.start, - end: pointer.end, - }; + if (location === undefined) { + throw new Error(msg); } const diagnostic: Diagnostic = { @@ -375,11 +370,8 @@ export default class Consumer { advice, }, location: { - ...loc, + ...location, filename: this.filename, - language: pointer.language, - mtime: pointer.mtime, - sourceText: pointer.sourceText, }, }; diff --git a/packages/@romejs/core/master/MasterRequest.ts b/packages/@romejs/core/master/MasterRequest.ts index 5b602158ce4..484beae0822 100644 --- a/packages/@romejs/core/master/MasterRequest.ts +++ b/packages/@romejs/core/master/MasterRequest.ts @@ -124,10 +124,10 @@ export default class MasterRequest { } async assertClientCwdProject(): Promise { - const pointer = this.getDiagnosticPointerForClientCwd(); + const location = this.getDiagnosticPointerForClientCwd(); return this.master.projectManager.assertProject( this.client.flags.cwd, - pointer, + location, ); } @@ -203,7 +203,7 @@ export default class MasterRequest { target: SerializeCLITarget = {type: 'none'}, advice?: DiagnosticAdvice, ) { - const pointer = this.getDiagnosticPointerFromFlags(target); + const location = this.getDiagnosticPointerFromFlags(target); const diag: Diagnostic = { description: { @@ -212,7 +212,7 @@ export default class MasterRequest { ? 'args/invalid' : 'flags/invalid', advice, }, - location: pointer, + location, }; throw new MasterRequestInvalid(message, [diag]); @@ -301,15 +301,15 @@ export default class MasterRequest { const rawArgs = [...this.query.args]; const resolvedArgs: Array<{ path: AbsoluteFilePath; - pointer: DiagnosticLocation; + location: DiagnosticLocation; project: ProjectDefinition; }> = []; if (rawArgs.length === 0) { - const pointer = this.getDiagnosticPointerForClientCwd(); + const location = this.getDiagnosticPointerForClientCwd(); const project = await this.assertClientCwdProject(); resolvedArgs.push({ path: project.folder, - pointer, + location, project, }); projects.add(project); @@ -317,7 +317,7 @@ export default class MasterRequest { for (let i = 0; i < rawArgs.length; i++) { const arg = rawArgs[i]; - const pointer = this.getDiagnosticPointerFromFlags({ + const location = this.getDiagnosticPointerFromFlags({ type: 'arg', key: i, }); @@ -327,7 +327,7 @@ export default class MasterRequest { source: createUnknownFilePath(arg), requestedType: 'folder', }, { - pointer, + location, }); const project = this.master.projectManager.assertProjectExisting( @@ -338,14 +338,14 @@ export default class MasterRequest { resolvedArgs.push({ project, path: resolved.path, - pointer, + location, }); } } // Build up files const paths: AbsoluteFilePathSet = new AbsoluteFilePathSet(); - for (const {path, pointer, project} of resolvedArgs) { + for (const {path, location, project} of resolvedArgs) { const matches = master.memoryFs.glob(path, globOpts); if (matches.size > 0) { @@ -394,7 +394,7 @@ export default class MasterRequest { message: `${explanationPrefix} as it's explicitly disabled in this project config`, }); - const disabledPointer = testSource.value.getDiagnosticPointer( + const disabledPointer = testSource.value.getDiagnosticLocation( 'value', ); advice.push({ @@ -430,7 +430,7 @@ export default class MasterRequest { }); if (ignore.source !== undefined && ignore.source.value !== undefined) { - const ignorePointer = ignore.source.value.getDiagnosticPointer( + const ignorePointer = ignore.source.value.getDiagnosticLocation( 'value', ); @@ -449,7 +449,7 @@ export default class MasterRequest { } throw createSingleDiagnosticError({ - location: pointer, + location, description: { category, message: createBlessedDiagnosticMessage(globOpts.noun === undefined diff --git a/packages/@romejs/core/master/bundler/Bundler.ts b/packages/@romejs/core/master/bundler/Bundler.ts index 60f452e11e6..9ed22e1fe92 100644 --- a/packages/@romejs/core/master/bundler/Bundler.ts +++ b/packages/@romejs/core/master/bundler/Bundler.ts @@ -303,8 +303,8 @@ export default class Bundler { const isBinShorthand = typeof binConsumer.asUnknown() === 'string'; for (const [binName, relative] of manifest.bin) { - const pointer = - (isBinShorthand ? binConsumer : binConsumer.get(binName)).getDiagnosticPointer( + const location = + (isBinShorthand ? binConsumer : binConsumer.get(binName)).getDiagnosticLocation( 'inner-value', ); @@ -313,7 +313,7 @@ export default class Bundler { origin: manifestDef.folder, source: createUnknownFilePath(relative).toExplicitRelative(), }, { - pointer, + location, }); const res = await createBundle(absolute.path, { diff --git a/packages/@romejs/core/master/commands/_moduleSignature.ts b/packages/@romejs/core/master/commands/_moduleSignature.ts index adffc5e1866..9b3ee1f2f46 100644 --- a/packages/@romejs/core/master/commands/_moduleSignature.ts +++ b/packages/@romejs/core/master/commands/_moduleSignature.ts @@ -22,7 +22,7 @@ export default createMasterCommand({ const filename = await master.resolver.resolveEntryAssertPath({ ...req.getResolverOptionsFromFlags(), source: createUnknownFilePath(args[0]), - }, {pointer: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); + }, {location: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); reporter.inspect(await req.requestWorkerModuleSignature(filename)); }, }); diff --git a/packages/@romejs/core/master/commands/analyzeDependencies.ts b/packages/@romejs/core/master/commands/analyzeDependencies.ts index 6fb71183381..b1e739d71e8 100644 --- a/packages/@romejs/core/master/commands/analyzeDependencies.ts +++ b/packages/@romejs/core/master/commands/analyzeDependencies.ts @@ -42,7 +42,7 @@ export default createMasterCommand({ const filename = await master.resolver.resolveEntryAssertPath({ ...req.getResolverOptionsFromFlags(), source: createUnknownFilePath(args[0]), - }, {pointer: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); + }, {location: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); let res = await req.requestWorkerAnalyzeDependencies(filename); diff --git a/packages/@romejs/core/master/commands/compile.ts b/packages/@romejs/core/master/commands/compile.ts index 5aa2be89158..31e25678a8f 100644 --- a/packages/@romejs/core/master/commands/compile.ts +++ b/packages/@romejs/core/master/commands/compile.ts @@ -34,7 +34,7 @@ export default createMasterCommand({ const resolved = await master.resolver.resolveEntryAssert({ ...req.getResolverOptionsFromFlags(), source: createUnknownFilePath(args[0]), - }, {pointer: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); + }, {location: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); let res: WorkerCompileResult; if (commandFlags.bundle) { diff --git a/packages/@romejs/core/master/commands/parse.ts b/packages/@romejs/core/master/commands/parse.ts index 8990b0d53d5..c86c2350756 100644 --- a/packages/@romejs/core/master/commands/parse.ts +++ b/packages/@romejs/core/master/commands/parse.ts @@ -39,7 +39,7 @@ export default createMasterCommand({ const filename = await master.resolver.resolveEntryAssertPath({ ...req.getResolverOptionsFromFlags(), source: createUnknownFilePath(args[0]), - }, {pointer: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); + }, {location: req.getDiagnosticPointerFromFlags({type: 'arg', key: 0})}); const ast = await req.requestWorkerParse(filename, { compact: commandFlags.compact, diff --git a/packages/@romejs/core/master/commands/resolve.ts b/packages/@romejs/core/master/commands/resolve.ts index 5d2b29ef378..e8368a6361e 100644 --- a/packages/@romejs/core/master/commands/resolve.ts +++ b/packages/@romejs/core/master/commands/resolve.ts @@ -41,7 +41,7 @@ export default createMasterCommand({ }; const resolved = await master.resolver.resolveEntryAssert(query, { - pointer: req.getDiagnosticPointerFromFlags({type: 'arg', key}), + location: req.getDiagnosticPointerFromFlags({type: 'arg', key}), }); const filename = resolved.ref.real.join(); reporter.logAll(filename); diff --git a/packages/@romejs/core/master/dependencies/DependencyGraph.ts b/packages/@romejs/core/master/dependencies/DependencyGraph.ts index f2b4029aacf..c8b401fab29 100644 --- a/packages/@romejs/core/master/dependencies/DependencyGraph.ts +++ b/packages/@romejs/core/master/dependencies/DependencyGraph.ts @@ -311,7 +311,7 @@ export default class DependencyGraph { origin, source: createUnknownFilePath(source), }, dep.loc === undefined ? undefined : { - pointer: { + location: { sourceText: undefined, ...dep.loc, language: 'js', diff --git a/packages/@romejs/core/master/fs/Resolver.ts b/packages/@romejs/core/master/fs/Resolver.ts index 46a072ab87d..d80ef005f41 100644 --- a/packages/@romejs/core/master/fs/Resolver.ts +++ b/packages/@romejs/core/master/fs/Resolver.ts @@ -104,7 +104,7 @@ export type ResolverQuerySource = | undefined | { source?: string; - pointer?: DiagnosticLocation; + location?: DiagnosticLocation; }; type ResolverQueryResponseFoundType = @@ -199,12 +199,12 @@ function attachExportAliasIfUnresolved( return res; } - const pointer = alias.key.getDiagnosticPointer('value'); + const location = alias.key.getDiagnosticLocation('value'); return { ...res, - source: pointer === undefined ? undefined : { - pointer, + source: location === undefined ? undefined : { + location, source: alias.value.join(), }, }; diff --git a/packages/@romejs/core/master/fs/resolverSuggest.ts b/packages/@romejs/core/master/fs/resolverSuggest.ts index ec9baab3a9b..a3dcc6db602 100644 --- a/packages/@romejs/core/master/fs/resolverSuggest.ts +++ b/packages/@romejs/core/master/fs/resolverSuggest.ts @@ -49,12 +49,12 @@ export default function resolverSuggest( // Use the querySource returned by the resolution which will be the one that actually triggered this error, otherwise use the query source provided to us const querySource = resolved.source === undefined ? origQuerySource : resolved.source; - if (querySource === undefined || querySource.pointer === undefined) { + if (querySource === undefined || querySource.location === undefined) { // TODO do something about the `advice` on some `resolved` that may contain metadata? throw new Error(errMsg); } - const {pointer} = querySource; + const {location} = querySource; let advice: DiagnosticAdvice = []; @@ -134,7 +134,7 @@ export default function resolverSuggest( // Hint on any indirection if ( - origQuerySource !== undefined && origQuerySource.pointer !== undefined && + origQuerySource !== undefined && origQuerySource.location !== undefined && resolved.source !== undefined ) { advice.push({ @@ -143,7 +143,7 @@ export default function resolverSuggest( message: `Found while resolving ${query.source} from `, }); - const origPointer = origQuerySource.pointer; + const origPointer = origQuerySource.location; advice.push({ type: 'frame', @@ -233,10 +233,10 @@ export default function resolverSuggest( } message += - ` ${source} from `; + ` ${source} from `; throw createSingleDiagnosticError({ - location: pointer, + location, description: { category, message: createBlessedDiagnosticMessage(message), diff --git a/packages/@romejs/core/master/project/ProjectManager.ts b/packages/@romejs/core/master/project/ProjectManager.ts index 167ab41e160..c895472a927 100644 --- a/packages/@romejs/core/master/project/ProjectManager.ts +++ b/packages/@romejs/core/master/project/ProjectManager.ts @@ -591,7 +591,7 @@ export default class ProjectManager { name, existingPackage.path.join(), ), - location: def.consumer.get('name').getDiagnosticPointer('inner-value'), + location: def.consumer.get('name').getDiagnosticLocation('inner-value'), }); return; } @@ -719,7 +719,7 @@ export default class ProjectManager { async assertProject( path: AbsoluteFilePath, - pointer?: DiagnosticLocation, + location?: DiagnosticLocation, ): Promise { // We won't recurse up and check a parent project if we've already visited it const syncProject = this.findProjectExisting(path); @@ -736,14 +736,14 @@ export default class ProjectManager { return project; } - if (pointer === undefined) { + if (location === undefined) { throw new Error( `Couldn't find a project. Checked ${ROME_CONFIG_FILENAMES.join(' or ')} for ${path.join()}`, ); } throw createSingleDiagnosticError({ - location: pointer, + location, description: descriptions.PROJECT_MANAGER.NOT_FOUND, }); } diff --git a/packages/@romejs/core/master/web/index.ts b/packages/@romejs/core/master/web/index.ts index 5fe21e6e359..d0659fcd9cb 100644 --- a/packages/@romejs/core/master/web/index.ts +++ b/packages/@romejs/core/master/web/index.ts @@ -259,11 +259,11 @@ export class WebServer { throw new Error('Pathname is attempting to escalate out of cwd'); } - const pathPointer = url.path.getDiagnosticPointer(); + const pathPointer = url.path.getDiagnosticLocation(); const path = await this.master.resolver.resolveEntryAssertPath({ origin: this.masterRequest.client.flags.cwd, source: absolute, - }, pathPointer === undefined ? undefined : {pointer: pathPointer}); + }, pathPointer === undefined ? undefined : {location: pathPointer}); const platform = url.query.get('platform').asStringSetOrVoid(PLATFORMS); const cacheKey = JSON.stringify({ diff --git a/packages/@romejs/diagnostics/derive.ts b/packages/@romejs/diagnostics/derive.ts index 61c451e518a..534a06ed9d0 100644 --- a/packages/@romejs/diagnostics/derive.ts +++ b/packages/@romejs/diagnostics/derive.ts @@ -90,11 +90,11 @@ export function deriveRootAdviceFromDiagnostic( header: string; } { const advice: DiagnosticAdvice = []; - const {description: metadata, location: pointer} = diag; + const {description: metadata, location} = diag; let header = getDiagnosticHeader({ - start: pointer.start, - filename: pointer.filename, + start: location.start, + filename: location.filename, }); if (diag.label !== undefined) { @@ -132,7 +132,7 @@ export function deriveRootAdviceFromDiagnostic( }); if (opts.skipFrame === false) { - if (pointer.start !== undefined && pointer.end !== undefined) { + if (location.start !== undefined && location.end !== undefined) { advice.push({ type: 'frame', location: diag.location, diff --git a/packages/@romejs/diagnostics/descriptions.ts b/packages/@romejs/diagnostics/descriptions.ts index ec1ab0cc232..26719bea890 100644 --- a/packages/@romejs/diagnostics/descriptions.ts +++ b/packages/@romejs/diagnostics/descriptions.ts @@ -396,12 +396,12 @@ export const descriptions = createMessages({ DUPLICATE_REGEX_GROUP_NAME: ( name: string, - pointers: Array, + locations: Array, ) => ({ category: 'lint/noDuplicateGroupNamesInRegularExpressions', message: `Duplicate group name ${name} in regular expression`, - advice: buildDuplicateLocationAdvice(pointers), + advice: buildDuplicateLocationAdvice(locations), }), DEFAULT_EXPORT_SAME_BASENAME: ( diff --git a/packages/@romejs/diagnostics/helpers.ts b/packages/@romejs/diagnostics/helpers.ts index 376ac242913..884c0064700 100644 --- a/packages/@romejs/diagnostics/helpers.ts +++ b/packages/@romejs/diagnostics/helpers.ts @@ -100,9 +100,9 @@ export function buildSuggestionAdvice( } export function buildDuplicateLocationAdvice( - pointers: Array, + locations: Array, ): DiagnosticAdvice { - const locationAdvice: DiagnosticAdvice = pointers.map((location) => { + const locationAdvice: DiagnosticAdvice = locations.map((location) => { if (location === undefined) { return { type: 'log', diff --git a/packages/@romejs/js-analysis/api/check.ts b/packages/@romejs/js-analysis/api/check.ts index fdaf992a726..590a4dc9f04 100644 --- a/packages/@romejs/js-analysis/api/check.ts +++ b/packages/@romejs/js-analysis/api/check.ts @@ -99,8 +99,7 @@ function resolveGraph(hub: Hub): Diagnostics { advice: [...advice, ...(description.advice || [])], }; - context.addNodeDiagnostic(lowerTarget.originNode, { - description, + context.addNodeDiagnostic(lowerTarget.originNode, description, { marker: lowerTarget && !(lowerTarget instanceof reduced.constructor) ? utils.humanize(lowerTarget) : undefined, }); @@ -122,12 +121,16 @@ function resolveGraph(hub: Hub): Diagnostics { continue; } - context.addNodeDiagnostic(compatibility.lower.originNode, { - description: descriptions.TYPE_CHECK.INCOMPATIBILITY(utils.humanize( - upper, - ), upper.originLoc), - marker: utils.humanize(compatibility.lower), - }); + context.addNodeDiagnostic( + compatibility.lower.originNode, + descriptions.TYPE_CHECK.INCOMPATIBILITY( + utils.humanize(upper), + upper.originLoc, + ), + { + marker: utils.humanize(compatibility.lower), + }, + ); } } } diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts index acdd4bd21d1..c9b1990e34b 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts +++ b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts @@ -231,9 +231,10 @@ export default async function analyzeDependencies( });*/} } else if (record instanceof CJSExportRecord) { if (moduleType === 'es') { - context.addNodeDiagnostic(record.node, { - description: descriptions.ANALYZE_DEPENDENCIES.CJS_EXPORT_IN_ES, - }); + context.addNodeDiagnostic( + record.node, + descriptions.ANALYZE_DEPENDENCIES.CJS_EXPORT_IN_ES, + ); } } } diff --git a/packages/@romejs/js-compiler/lib/Context.ts b/packages/@romejs/js-compiler/lib/Context.ts index 086045b4dba..4c109b98bfa 100644 --- a/packages/@romejs/js-compiler/lib/Context.ts +++ b/packages/@romejs/js-compiler/lib/Context.ts @@ -21,7 +21,7 @@ import { Diagnostic, Diagnostics, DiagnosticOrigin, - DiagnosticLocation, + DiagnosticDescription, } from '@romejs/diagnostics'; import Record from './Record'; import {RootScope} from '../scope/Scope'; @@ -37,9 +37,7 @@ export type ContextArg = { }; // We only want a Context to create diagnostics that belong to itself -type ContextDiagnostic = - & Omit - & {location?: Omit}; +type ContextDiagnostic = Omit; export default class Context { constructor(arg: ContextArg) { @@ -117,7 +115,11 @@ export default class Context { this.diagnostics = [...this.diagnostics, ...diagnostics]; } - addLocDiagnostic(loc: undefined | SourceLocation, diag: ContextDiagnostic) { + addLocDiagnostic( + loc: undefined | SourceLocation, + description: DiagnosticDescription, + diag: ContextDiagnostic = {}, + ) { let origins: Array = []; if (this.origin !== undefined) { origins.push(this.origin); @@ -132,17 +134,14 @@ export default class Context { ); } - const location: DiagnosticLocation = diag.location === undefined - ? {} : diag.location; - this.diagnostics.push({ ...diag, + description, location: { - ...location, mtime: this.mtime, filename: this.filename, - start: loc === undefined ? location.start : loc.start, - end: loc === undefined ? location.end : loc.end, + start: loc === undefined ? undefined : loc.start, + end: loc === undefined ? undefined : loc.end, language: 'js', sourceType: this.sourceType, }, @@ -152,17 +151,24 @@ export default class Context { addNodeDiagnostic( node: undefined | {loc?: SourceLocation}, - diag: ContextDiagnostic, + description: DiagnosticDescription, + diag: ContextDiagnostic = {}, ) { - return this.addLocDiagnostic(node === undefined ? undefined : node.loc, diag); + return this.addLocDiagnostic( + node === undefined ? undefined : node.loc, + description, + diag, + ); } addNodesRangeDiagnostic( nodes: Array<{loc?: SourceLocation}>, - diag: ContextDiagnostic, + description: DiagnosticDescription, + diag: ContextDiagnostic = {}, ) { return this.addLocDiagnostic( extractSourceLocationRangeFromNodes(nodes), + description, diag, ); } diff --git a/packages/@romejs/js-compiler/lib/Path.ts b/packages/@romejs/js-compiler/lib/Path.ts index 9d8601a91a4..68838cf1451 100644 --- a/packages/@romejs/js-compiler/lib/Path.ts +++ b/packages/@romejs/js-compiler/lib/Path.ts @@ -13,7 +13,6 @@ import { AnyHookDescriptor, HookDescriptor, } from '../api/createHook'; -import {Diagnostic} from '@romejs/diagnostics'; import reduce from '../methods/reduce'; import {TransformExitResult} from '../types'; @@ -256,8 +255,4 @@ export default class Path { {...this.getPathOptions(), ...opts}, ); } - - addDiagnostic(opts: Diagnostic) { - return this.context.addNodeDiagnostic(this.node, opts); - } } diff --git a/packages/@romejs/js-compiler/transforms/compile/jsx.ts b/packages/@romejs/js-compiler/transforms/compile/jsx.ts index 58ad7b6cb92..3b7e0cd1a22 100644 --- a/packages/@romejs/js-compiler/transforms/compile/jsx.ts +++ b/packages/@romejs/js-compiler/transforms/compile/jsx.ts @@ -271,9 +271,7 @@ export default { if (jsxNamespacedName.is(node.name)) { // TODO better handle this - context.addNodeDiagnostic(type, { - description: descriptions.COMPILER.JSX_NOT_XML, - }); + context.addNodeDiagnostic(type, descriptions.COMPILER.JSX_NOT_XML); } let attribs: AnyExpression; diff --git a/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts b/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts index a9f339d5232..0f821ac9671 100644 --- a/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts +++ b/packages/@romejs/js-compiler/transforms/compile/transpile/classes.ts @@ -211,9 +211,10 @@ function transformClass( let constructorMethod = undefined; for (const bodyNode of newNode.meta.body) { if (bodyNode.type !== 'ClassMethod') { - context.addNodeDiagnostic(bodyNode, { - description: descriptions.COMPILER.CLASSES_UNSUPPORTED, - }); + context.addNodeDiagnostic( + bodyNode, + descriptions.COMPILER.CLASSES_UNSUPPORTED, + ); continue; } diff --git a/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts b/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts index 40908ec7c36..5dbbc9cffd4 100644 --- a/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts +++ b/packages/@romejs/js-compiler/transforms/lint/defaultExportSameBasename.ts @@ -64,14 +64,15 @@ export default { if (basename !== id.name) { const correctFilename = id.name + context.path.getExtensions(); - context.addNodeDiagnostic(id, { - description: descriptions.LINT.DEFAULT_EXPORT_SAME_BASENAME({ + context.addNodeDiagnostic( + id, + descriptions.LINT.DEFAULT_EXPORT_SAME_BASENAME({ defaultName: id.name, defaultType: type, actualFilename: basename, correctFilename, }), - }); + ); return renameBindings(path, new Map([[id.name, basename]])); } diff --git a/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts b/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts index 8e0e64c474f..75548e30124 100644 --- a/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts +++ b/packages/@romejs/js-compiler/transforms/lint/emptyBlocks.ts @@ -33,9 +33,10 @@ export default { if (node.type === 'IfStatement') { if (isEmpty(node.consequent)) { - context.addNodeDiagnostic(node.consequent, { - description: descriptions.LINT.EMPTY_BLOCKS, - }); + context.addNodeDiagnostic( + node.consequent, + descriptions.LINT.EMPTY_BLOCKS, + ); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts b/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts index 95c33e13c3b..fecaebd60c8 100644 --- a/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts +++ b/packages/@romejs/js-compiler/transforms/lint/getterReturn.ts @@ -19,9 +19,10 @@ export default { node.kind === 'get') { for (const record of getCompletionRecords(node.body)) { if (record.type === 'INVALID') { - path.context.addNodeDiagnostic(record.node, { - description: descriptions.LINT.GETTER_RETURN(record.description), - }); + path.context.addNodeDiagnostic( + record.node, + descriptions.LINT.GETTER_RETURN(record.description), + ); } } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts index 39c8f52f0c3..60cf9259f0e 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noAsyncPromiseExecutor.ts @@ -19,9 +19,10 @@ export default { node.arguments.length > 0 && (node.arguments[0].type === 'ArrowFunctionExpression' || node.arguments[0].type === 'FunctionExpression') && node.arguments[0].head.async) { - context.addNodeDiagnostic(node.arguments[0], { - description: descriptions.LINT.NO_ASYNC_PROMISE_EXECUTOR, - }); + context.addNodeDiagnostic( + node.arguments[0], + descriptions.LINT.NO_ASYNC_PROMISE_EXECUTOR, + ); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts index e8a30e316c7..67957c47b36 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noCompareNegZero.ts @@ -24,9 +24,10 @@ export default { if (node.type === 'BinaryExpression' && OPERATORS_TO_CHECK.includes( node.operator, ) && (isNegZero(node.left) || isNegZero(node.right))) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_COMPARE_NEG_ZERO(node.operator), - }); + path.context.addNodeDiagnostic( + node, + descriptions.LINT.NO_COMPARE_NEG_ZERO(node.operator), + ); if (node.operator === '===') { return template.expression`Object.is(${node.left}, ${node.right})`; } diff --git a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts index c0ffe487617..b9a4a4d933a 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noCondAssign.ts @@ -17,9 +17,7 @@ export default { if ((node.type === 'IfStatement' || node.type === 'ForStatement' || node.type === 'WhileStatement' || node.type === 'DoWhileStatement') && node.test && node.test.type === 'AssignmentExpression') { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_COND_ASSIGN, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.NO_COND_ASSIGN); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts index 07e8efa3797..82e433011ef 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDanglingBackslashInRegularExpressions.ts @@ -19,9 +19,10 @@ export default { if (body) { const last = body[body.length - 1]; if (last && last.type === 'RegExpCharacter' && !last.value) { - context.addNodeDiagnostic(last, { - description: descriptions.LINT.NO_DANGLING_BACKSLASH_IN_REGEX, - }); + context.addNodeDiagnostic( + last, + descriptions.LINT.NO_DANGLING_BACKSLASH_IN_REGEX, + ); } } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts b/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts index 21ccb35551f..45698ebeba5 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDebugger.ts @@ -15,10 +15,7 @@ export default { const {node} = path; if (node.type === 'DebuggerStatement') { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_DEBUGGER, - }); - + path.context.addNodeDiagnostic(node, descriptions.LINT.NO_DEBUGGER); return REDUCE_REMOVE; } diff --git a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts index 53c80f1db6d..7eac05cce96 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDeleteVars.ts @@ -16,9 +16,7 @@ export default { if (node.type === 'UnaryExpression' && node.operator === 'delete' && node.argument.type === 'ReferenceIdentifier') { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_DELETE_VARS, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.NO_DELETE_VARS); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts index fc7aef0d102..2af7cf3de9b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDupeArgs.ts @@ -21,9 +21,10 @@ export default { for (const param of node.params) { for (const {name} of getBindingIdentifiers(param)) { if (uniqueIdentifiers.has(name)) { - context.addNodeDiagnostic(param, { - description: descriptions.LINT.NO_DUPE_ARGS(name), - }); + context.addNodeDiagnostic( + param, + descriptions.LINT.NO_DUPE_ARGS(name), + ); } uniqueIdentifiers.add(name); diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts index b18010574a0..8236d32cb49 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateCase.ts @@ -22,9 +22,10 @@ export default { const {test} = param; if (uniqueSwitchCases.has(test.value)) { - context.addNodeDiagnostic(param, { - description: descriptions.LINT.NO_DUPLICATE_CASE(test.value), - }); + context.addNodeDiagnostic( + param, + descriptions.LINT.NO_DUPLICATE_CASE(test.value), + ); } uniqueSwitchCases.add(test.value); diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts index b510502ff20..78857a33627 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateGroupNamesInRegularExpressions.ts @@ -40,12 +40,13 @@ export default { const firstUsage = usages[0]; - context.addNodeDiagnostic(firstUsage, { - description: descriptions.LINT.DUPLICATE_REGEX_GROUP_NAME( + context.addNodeDiagnostic( + firstUsage, + descriptions.LINT.DUPLICATE_REGEX_GROUP_NAME( name, usages.slice(1).map((node) => node.loc), ), - }); + ); } } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts index ac5ac35201e..d60e6434005 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.ts @@ -44,9 +44,10 @@ export default { if (key !== undefined) { if (previousKeys.has(key)) { - path.context.addNodeDiagnostic(prop, { - description: descriptions.LINT.NO_DUPLICATE_KEYS(key), - }); + path.context.addNodeDiagnostic( + prop, + descriptions.LINT.NO_DUPLICATE_KEYS(key), + ); } previousKeys.add(key); diff --git a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts index 9965e2658ae..71d3724dbcd 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noEmptyCharacterClass.ts @@ -14,9 +14,7 @@ export default { const {context, node} = path; if (node.type === 'RegExpCharSet' && node.body.length === 0 && !node.invert) { - context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_EMPTY_CHAR_SET, - }); + context.addNodeDiagnostic(node, descriptions.LINT.NO_EMPTY_CHAR_SET); return REDUCE_REMOVE; } diff --git a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts index e4d3dc6cba5..c0c2169ff0a 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noExplicitAny.ts @@ -15,9 +15,7 @@ export default { const {context, node} = path; if (node.type === 'AnyKeywordTypeAnnotation') { - context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_EXPLICIT_ANY, - }); + context.addNodeDiagnostic(node, descriptions.LINT.NO_EXPLICIT_ANY); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts index 47a7c07edc1..d1fc5594721 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noExtraBooleanCast.ts @@ -58,9 +58,7 @@ export default { node.argument.type === 'UnaryExpression' && node.argument.operator === '!' || node.type === 'CallExpression' && node.callee.type === 'ReferenceIdentifier' && node.callee.name === 'Boolean') { - context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_EXTRA_BOOLEAN_CAST, - }); + context.addNodeDiagnostic(node, descriptions.LINT.NO_EXTRA_BOOLEAN_CAST); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts index 50db3b19885..a954813fad4 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.ts @@ -17,9 +17,7 @@ export default { if (node.type === 'AssignmentIdentifier' && scope.getBinding(node.name) instanceof FunctionBinding) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_FUNCTION_ASSIGN, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.NO_FUNCTION_ASSIGN); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts index 9d01ea16477..cbf16e0f11c 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noImportAssign.ts @@ -32,9 +32,7 @@ export default { const binding = scope.getBinding(node.name); if (binding !== undefined && binding.kind === 'import') path.context.addNodeDiagnostic( node, - { - description: descriptions.LINT.NO_IMPORT_ASSIGN(node.name), - }, + descriptions.LINT.NO_IMPORT_ASSIGN(node.name), ); } diff --git a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts index b4654aa73d8..29934d9922c 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noLabelVar.ts @@ -22,9 +22,7 @@ export default { ); if (isDefined) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_LABEL_VAR, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.NO_LABEL_VAR); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts index fa9bcd7b813..1d162a7e3a5 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noMultipleSpacesInRegularExpressionLiterals.ts @@ -14,7 +14,6 @@ import { regExpQuantified, } from '@romejs/js-ast'; import {Path, Context} from '@romejs/js-compiler'; -import {extractSourceLocationRangeFromNodes} from '@romejs/parser-core'; import {descriptions} from '@romejs/diagnostics'; function isSpaceChar( @@ -49,11 +48,10 @@ function checkRegex( } } - context.addLocDiagnostic(extractSourceLocationRangeFromNodes(spaceNodes), { - description: descriptions.LINT.NO_MULTIPLE_SPACES_IN_REGEX_LITERAL( - spaceNodes.length, - ), - }); + context.addNodesRangeDiagnostic( + spaceNodes, + descriptions.LINT.NO_MULTIPLE_SPACES_IN_REGEX_LITERAL(spaceNodes.length), + ); const quantifiedSpace: RegExpQuantified = regExpQuantified.create({ min: spaceNodes.length, diff --git a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts index 3e216e99f94..eb3d3dd61a4 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noShadowRestrictedNames.ts @@ -20,9 +20,10 @@ export default { if (scope.node === node) { for (const [name, binding] of scope.getOwnBindings()) { if (restrictedNames.has(name)) { - context.addNodeDiagnostic(binding.node, { - description: descriptions.LINT.NO_SHADOW_RESTRICTED_NAMES(name), - }); + context.addNodeDiagnostic( + binding.node, + descriptions.LINT.NO_SHADOW_RESTRICTED_NAMES(name), + ); } } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts index 90c7f1ce4c2..04ab4cc07e8 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noTemplateCurlyInString.ts @@ -17,9 +17,10 @@ export default { const regex = /\$\{[^}]+\}/u; if (regex.test(node.value)) { - context.addNodeDiagnostic(node, { - description: descriptions.LINT.NO_TEMPLATE_CURLY_IN_STRING, - }); + context.addNodeDiagnostic( + node, + descriptions.LINT.NO_TEMPLATE_CURLY_IN_STRING, + ); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts index edaf7ecf6d1..50f43aee25b 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noUnsafeFinally.ts @@ -22,9 +22,10 @@ export default { if (statement.type === 'ThrowStatement' || statement.type === 'ContinueStatement' || statement.type === 'BreakStatement' || statement.type === 'ReturnStatement') { - context.addNodeDiagnostic(statement, { - description: descriptions.LINT.NO_UNSAFE_FINALLY(statement.type), - }); + context.addNodeDiagnostic( + statement, + descriptions.LINT.NO_UNSAFE_FINALLY(statement.type), + ); } } } diff --git a/packages/@romejs/js-compiler/transforms/lint/noVar.ts b/packages/@romejs/js-compiler/transforms/lint/noVar.ts index 208f49d12fe..b597f270c8f 100644 --- a/packages/@romejs/js-compiler/transforms/lint/noVar.ts +++ b/packages/@romejs/js-compiler/transforms/lint/noVar.ts @@ -15,9 +15,7 @@ export default { const {context, node: declaration} = path; if (declaration.type === 'VariableDeclaration' && declaration.kind === 'var') { - context.addNodeDiagnostic(declaration, { - description: descriptions.LINT.NO_VAR, - }); + context.addNodeDiagnostic(declaration, descriptions.LINT.NO_VAR); } return declaration; diff --git a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts index 0e10e89045d..44c517313e6 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts +++ b/packages/@romejs/js-compiler/transforms/lint/preferFunctionDeclarations.ts @@ -88,9 +88,10 @@ const hook = createHook({ throw new Error('Invalid declarator put into state'); } - path.context.addNodeDiagnostic(init, { - description: descriptions.LINT.PREFER_FUNCTION_DECLARATIONS, - }); + path.context.addNodeDiagnostic( + init, + descriptions.LINT.PREFER_FUNCTION_DECLARATIONS, + ); // Convert arrow function body if necessary const body = init.body.type === 'BlockStatement' diff --git a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts index 71b36be3253..08f57e83221 100644 --- a/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts +++ b/packages/@romejs/js-compiler/transforms/lint/preferTemplate.ts @@ -17,9 +17,7 @@ export default { if (node.type === 'BinaryExpression' && node.operator === '+' && (node.left.type === 'StringLiteral' && !node.left.value.includes('`') || node.right.type === 'StringLiteral' && !node.right.value.includes('`'))) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.PREFER_TEMPLATE, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.PREFER_TEMPLATE); } return node; diff --git a/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts b/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts index 7219bc10688..8d61b71d882 100644 --- a/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts +++ b/packages/@romejs/js-compiler/transforms/lint/sparseArray.ts @@ -16,9 +16,7 @@ export default { const {node} = path; if (node.type === 'ArrayExpression' && node.elements.includes(undefined)) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.SPARSE_ARRAY, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.SPARSE_ARRAY); return arrayExpression.quick(node.elements.map((elem) => elem === undefined diff --git a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts index 55bac1a3470..56006785741 100644 --- a/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts +++ b/packages/@romejs/js-compiler/transforms/lint/undeclaredVariables.ts @@ -54,9 +54,10 @@ export default { NODE_VARIABLES.includes(name); if (!isDefined) { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.UNDECLARED_VARIABLES(name), - }); + path.context.addNodeDiagnostic( + node, + descriptions.LINT.UNDECLARED_VARIABLES(name), + ); } } diff --git a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts index af9d1e14fd0..3864bcf28e1 100644 --- a/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts +++ b/packages/@romejs/js-compiler/transforms/lint/unsafeNegation.ts @@ -17,9 +17,7 @@ export default { if (node.type === 'BinaryExpression' && (node.operator === 'in' || node.operator === 'instanceof') && node.left.type === 'UnaryExpression' && node.left.operator === '!') { - path.context.addNodeDiagnostic(node, { - description: descriptions.LINT.UNSAFE_NEGATION, - }); + path.context.addNodeDiagnostic(node, descriptions.LINT.UNSAFE_NEGATION); return unaryExpression.create({ operator: node.left.operator, diff --git a/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts b/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts index e996b207098..57b9be38af9 100644 --- a/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts +++ b/packages/@romejs/js-compiler/transforms/lint/unusedVariables.ts @@ -64,9 +64,10 @@ const provider = createHook({ const binding = path.scope.getBinding(name); if (used === false && binding !== undefined) { - path.context.addNodeDiagnostic(binding.node, { - description: descriptions.LINT.UNUSED_VARIABLES(binding.kind, name), - }); + path.context.addNodeDiagnostic( + binding.node, + descriptions.LINT.UNUSED_VARIABLES(binding.kind, name), + ); } } From 37ead1e9f29f2fe41be775ccab6811d8aab8b6fb Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 22 Mar 2020 17:25:39 -0700 Subject: [PATCH 5/7] analyzeDependencies: Provide a hint when we can't find an export that exists as a local binding --- .../core/common/types/analyzeDependencies.ts | 7 + .../core/master/bundler/BundleRequest.ts | 15 +- .../master/dependencies/DependencyGraph.ts | 14 +- .../master/dependencies/DependencyNode.ts | 91 ++++-- packages/@romejs/diagnostics/descriptions.ts | 21 ++ .../api/analyzeDependencies.test.md | 264 ++++++++++++++++++ .../api/analyzeDependencies.test.ts | 7 + .../api/analyzeDependencies/index.ts | 9 + 8 files changed, 395 insertions(+), 33 deletions(-) diff --git a/packages/@romejs/core/common/types/analyzeDependencies.ts b/packages/@romejs/core/common/types/analyzeDependencies.ts index af484c9cff1..fbdb78137ba 100644 --- a/packages/@romejs/core/common/types/analyzeDependencies.ts +++ b/packages/@romejs/core/common/types/analyzeDependencies.ts @@ -12,6 +12,7 @@ import { ConstProgramSyntax, } from '@romejs/js-ast'; import {SourceLocation} from '@romejs/parser-core'; +import {Dict} from '@romejs/typescript-helpers'; export type AnalyzeModuleType = 'es' | 'cjs' | 'unknown'; @@ -71,7 +72,12 @@ export type AnalyzeDependencyImportFirstUsage = Array< AnalyzeDependencyImportUsageItem >; +export type AnalyzeDependencyTopLevelLocalBindings = Dict< + | undefined + | SourceLocation>; + export type AnalyzeDependencyResult = { + topLevelLocalBindings: AnalyzeDependencyTopLevelLocalBindings; moduleType: AnalyzeModuleType; syntax: Array; diagnostics: Diagnostics; @@ -82,6 +88,7 @@ export type AnalyzeDependencyResult = { }; export const UNKNOWN_ANALYZE_DEPENDENCIES_RESULT: AnalyzeDependencyResult = { + topLevelLocalBindings: {}, moduleType: 'unknown', syntax: [], diagnostics: [], diff --git a/packages/@romejs/core/master/bundler/BundleRequest.ts b/packages/@romejs/core/master/bundler/BundleRequest.ts index de8c10dc373..ee899edb1b3 100644 --- a/packages/@romejs/core/master/bundler/BundleRequest.ts +++ b/packages/@romejs/core/master/bundler/BundleRequest.ts @@ -101,6 +101,7 @@ export default class BundleRequest { paths: [this.resolvedEntry], diagnosticsProcessor: this.diagnostics, analyzeProgress, + validate: true, }); } finally { analyzeProgress.end(); @@ -142,7 +143,7 @@ export default class BundleRequest { // Build a map of relative module sources to module id const relativeSourcesToModuleId: Dict = {}; for (const [relative, absolute] of mod.relativeToAbsolutePath) { - const moduleId = graph.getNode(absolute).id; + const moduleId = graph.getNode(absolute).uid; relativeSourcesToModuleId[relative] = moduleId; } @@ -168,7 +169,7 @@ export default class BundleRequest { const opts: WorkerBundleCompileOptions = { mode: this.mode, moduleAll: mod.all, - moduleId: mod.id, + moduleId: mod.uid, relativeSourcesToModuleId, resolvedImports, assetPath, @@ -284,7 +285,7 @@ export default class BundleRequest { declaredCJS.add(module); - push(` var ${getPrefixedBundleNamespace(module.id)} = {};`); + push(` var ${getPrefixedBundleNamespace(module.uid)} = {};`); } // Add on files @@ -303,12 +304,12 @@ export default class BundleRequest { // Only do this in modern mode, the module id will already be in the wrapper otherwise if (mode === 'modern') { - push(` // ${module.id}`); + push(` // ${module.uid}`); } declareCJS(module); - addMappings(module.id, compileResult.sourceText, compileResult.mappings); + addMappings(module.uid, compileResult.sourceText, compileResult.mappings); push(compileResult.compiledCode); push(''); } @@ -316,9 +317,9 @@ export default class BundleRequest { // push on initial entry require const entryModule = graph.getNode(resolvedEntry); if (mode === 'modern') { - push(` return ${getPrefixedBundleNamespace(entryModule.id)};`); + push(` return ${getPrefixedBundleNamespace(entryModule.uid)};`); } else { - push(` return Rome.requireNamespace("${entryModule.id}");`); + push(` return Rome.requireNamespace("${entryModule.uid}");`); } // push footer diff --git a/packages/@romejs/core/master/dependencies/DependencyGraph.ts b/packages/@romejs/core/master/dependencies/DependencyGraph.ts index c8b401fab29..7ce5e1b5286 100644 --- a/packages/@romejs/core/master/dependencies/DependencyGraph.ts +++ b/packages/@romejs/core/master/dependencies/DependencyGraph.ts @@ -134,10 +134,10 @@ export default class DependencyGraph { const stats: BundleBuddyStats = []; for (const node of this.nodes.values()) { - const source = node.id; + const source = node.uid; for (const absoluteTarget of node.relativeToAbsolutePath.values()) { - const target = this.getNode(absoluteTarget).id; + const target = this.getNode(absoluteTarget).uid; stats.push({ target, source, @@ -146,7 +146,7 @@ export default class DependencyGraph { } for (const absoluteEntry of entries) { - const source = this.getNode(absoluteEntry).id; + const source = this.getNode(absoluteEntry).uid; stats.push({ source, target: undefined, @@ -157,9 +157,11 @@ export default class DependencyGraph { } addNode(filename: AbsoluteFilePath, res: WorkerAnalyzeDependencyResult) { - const module = new DependencyNode(this, this.master.projectManager.getUid( - filename, - ), filename, res); + const module = new DependencyNode( + this, + this.master.projectManager.getFileReference(filename), + res, + ); this.nodes.set(filename, module); return module; } diff --git a/packages/@romejs/core/master/dependencies/DependencyNode.ts b/packages/@romejs/core/master/dependencies/DependencyNode.ts index 6df196a3acf..81653a274d5 100644 --- a/packages/@romejs/core/master/dependencies/DependencyNode.ts +++ b/packages/@romejs/core/master/dependencies/DependencyNode.ts @@ -9,7 +9,12 @@ import DependencyGraph from './DependencyGraph'; import {BundleCompileResolvedImports} from '@romejs/js-compiler'; import {ConstImportModuleKind} from '@romejs/js-ast'; import {SourceLocation} from '@romejs/parser-core'; -import {Diagnostics, Diagnostic, descriptions} from '@romejs/diagnostics'; +import { + Diagnostics, + Diagnostic, + descriptions, + DiagnosticLocation, +} from '@romejs/diagnostics'; import {ProjectDefinition} from '@romejs/project'; import {DependencyOrder} from './DependencyOrderer'; import DependencyOrderer from './DependencyOrderer'; @@ -22,6 +27,7 @@ import { AnalyzeDependencyName, AnalyzeExportLocal, } from '@romejs/core'; +import {FileReference} from '@romejs/core/common/types/files'; type ResolvedImportFound = { type: 'FOUND'; @@ -69,15 +75,15 @@ type DependencyNodeDependency = { export default class DependencyNode { constructor( graph: DependencyGraph, - id: string, - path: AbsoluteFilePath, + ref: FileReference, res: WorkerAnalyzeDependencyResult, ) { this.graph = graph; - this.project = graph.master.projectManager.assertProjectExisting(path); - this.path = path; - this.id = id; + this.project = graph.master.projectManager.assertProjectExisting(ref.real); + this.uid = ref.uid; + this.path = ref.real; + this.ref = ref; this.type = res.moduleType; this.usedAsync = false; @@ -87,7 +93,7 @@ export default class DependencyNode { this.analyze = res; - const {handler} = getFileHandler(path, this.project.config); + const {handler} = getFileHandler(ref.real, this.project.config); this.handler = handler; } @@ -98,7 +104,8 @@ export default class DependencyNode { type: AnalyzeModuleType; project: ProjectDefinition; path: AbsoluteFilePath; - id: string; + uid: string; + ref: FileReference; all: boolean; usedAsync: boolean; handler: undefined | ExtensionHandler; @@ -196,6 +203,24 @@ export default class DependencyNode { return orderer.order(this.path); } + // Get a list of all DependencyNodes where exports could be resolved. eg. `export *` + getExportedModules(chain: Set = new Set()): Set { + if (chain.has(this)) { + return new Set(); + } else { + chain.add(this); + } + + for (const exp of this.analyze.exports) { + if (exp.type === 'externalAll') { + const node = this.getNodeFromRelativeDependency(exp.source); + node.getExportedModules(chain); + } + } + + return chain; + } + getExportedNames( kind: ConstImportModuleKind, seen: Set = new Set(), @@ -242,10 +267,39 @@ export default class DependencyNode { kind: ConstImportModuleKind, resolved: ResolvedImportNotFound, ): Diagnostic { + const location: DiagnosticLocation = { + ...resolved.loc, + mtime: this.getMtime(), + }; + + const expectedName = resolved.name; + const fromSource = resolved.node.uid; + + // Check if there was a matching local in any of the exported modules + for (const mod of resolved.node.getExportedModules()) { + // We use an object as a hash map so need to check for pollution + if (Object.prototype.hasOwnProperty.call( + mod.analyze.topLevelLocalBindings, + expectedName, + )) { + const localLoc = mod.analyze.topLevelLocalBindings[expectedName]; + if (localLoc !== undefined) { + return { + description: descriptions.BUNDLER.UNKNOWN_EXPORT_POSSIBLE_UNEXPORTED_LOCAL( + expectedName, + fromSource, + localLoc, + ), + location, + }; + } + } + } + return { description: descriptions.BUNDLER.UNKNOWN_EXPORT( - resolved.name, - resolved.node.id, + expectedName, + fromSource, Array.from(resolved.node.getExportedNames(kind)), (name: string) => { const exportInfo = resolved.node.resolveImport(name, undefined); @@ -258,15 +312,12 @@ export default class DependencyNode { return { location: exportInfo.record.loc, - source: exportInfo.node !== resolved.node - ? exportInfo.node.path.join() : undefined, + source: exportInfo.node === resolved.node + ? undefined : exportInfo.node.path.join(), }; }, ), - location: { - ...resolved.loc, - mtime: this.getMtime(), - }, + location, }; } @@ -281,7 +332,7 @@ export default class DependencyNode { return { description: descriptions.BUNDLER.IMPORT_TYPE_MISMATCH( name, - node.id, + node.uid, kind, record.kind, record.loc, @@ -347,9 +398,9 @@ export default class DependencyNode { } // If the resolved target isn't the same as the file then forward it - if (resolved.node.id !== mod.id) { - resolvedImports[`${mod.id}:${name}`] = { - id: resolved.node.id, + if (resolved.node.uid !== mod.uid) { + resolvedImports[`${mod.uid}:${name}`] = { + id: resolved.node.uid, name: resolved.record.name, }; } diff --git a/packages/@romejs/diagnostics/descriptions.ts b/packages/@romejs/diagnostics/descriptions.ts index 26719bea890..e45607a7df1 100644 --- a/packages/@romejs/diagnostics/descriptions.ts +++ b/packages/@romejs/diagnostics/descriptions.ts @@ -739,6 +739,27 @@ export const descriptions = createMessages({ }, }), }), + + UNKNOWN_EXPORT_POSSIBLE_UNEXPORTED_LOCAL: ( + name: string, + source: string, + location: DiagnosticLocation, + ) => + ({ + message: markup`Couldn't find export ${name} in `, + category: 'bundler/unknownExport', + advice: [ + { + type: 'log', + category: 'info', + message: 'However we found a matching local variable in this module. Did you forget to export it?', + }, + { + type: 'frame', + location, + }, + ], + }), }, SPDX: { diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies.test.md b/packages/@romejs/js-compiler/api/analyzeDependencies.test.md index 5ee06788229..1708c3e9c4f 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies.test.md +++ b/packages/@romejs/js-compiler/api/analyzeDependencies.test.md @@ -11,6 +11,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ local { kind: 'value' @@ -69,6 +70,21 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object { + foo: Object { + filename: 'unknown' + end: Object { + column: 22 + index: 23 + line: 2 + } + start: Object { + column: 19 + index: 20 + line: 2 + } + } + } exports: Array [ local { kind: 'value' @@ -102,6 +118,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} dependencies: Array [ es { kind: 'value' @@ -139,6 +156,88 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} +} +``` + +## `defines topLevelLocalBindings` + +```javascript +Object { + diagnostics: Array [] + exports: Array [] + firstTopAwaitLocation: undefined + importFirstUsage: Array [] + moduleType: 'es' + syntax: Array [] + topLevelLocalBindings: Object { + bar: Object { + filename: 'unknown' + end: Object { + column: 15 + index: 16 + line: 2 + } + start: Object { + column: 12 + index: 13 + line: 2 + } + } + foo: Object { + filename: 'unknown' + end: Object { + column: 13 + index: 43 + line: 3 + } + start: Object { + column: 10 + index: 40 + line: 3 + } + } + } + dependencies: Array [ + es { + kind: 'value' + all: false + async: false + optional: false + source: 'foo' + loc: Object { + filename: 'unknown' + end: Object { + column: 27 + index: 28 + line: 2 + } + start: Object { + column: 22 + index: 23 + line: 2 + } + } + names: Array [ + value { + name: 'bar' + loc: Object { + filename: 'unknown' + end: Object { + column: 15 + index: 16 + line: 2 + } + start: Object { + column: 12 + index: 13 + line: 2 + } + } + } + ] + } + ] } ``` @@ -151,6 +250,21 @@ Object { importFirstUsage: Array [] moduleType: 'cjs' syntax: Array [] + topLevelLocalBindings: Object { + foo: Object { + filename: 'unknown' + end: Object { + column: 22 + index: 23 + line: 2 + } + start: Object { + column: 19 + index: 20 + line: 2 + } + } + } diagnostics: Array [ Object { origins: Array [Object {category: 'js-parser'}] @@ -241,6 +355,21 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object { + yes: Object { + filename: 'unknown' + end: Object { + column: 18 + index: 43 + line: 4 + } + start: Object { + column: 15 + index: 40 + line: 4 + } + } + } dependencies: Array [ es { kind: 'value' @@ -298,6 +427,7 @@ Object { importFirstUsage: Array [] moduleType: 'cjs' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ local { kind: 'value' @@ -337,6 +467,7 @@ Object { importFirstUsage: Array [] moduleType: 'cjs' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ local { kind: 'value' @@ -376,6 +507,47 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object { + Bar: Object { + filename: 'unknown' + end: Object { + column: 22 + index: 83 + line: 4 + } + start: Object { + column: 19 + index: 80 + line: 4 + } + } + foo: Object { + filename: 'unknown' + end: Object { + column: 25 + index: 55 + line: 3 + } + start: Object { + column: 22 + index: 52 + line: 3 + } + } + yes: Object { + filename: 'unknown' + end: Object { + column: 22 + index: 23 + line: 2 + } + start: Object { + column: 19 + index: 20 + line: 2 + } + } + } exports: Array [ local { kind: 'value' @@ -445,6 +617,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ local { kind: 'value' @@ -477,6 +650,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ external { kind: 'value' @@ -655,6 +829,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ externalAll { kind: 'value' @@ -710,6 +885,21 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object { + bar: Object { + filename: 'unknown' + end: Object { + column: 16 + index: 17 + line: 2 + } + start: Object { + column: 13 + index: 14 + line: 2 + } + } + } dependencies: Array [ es { kind: 'value' @@ -763,6 +953,60 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object { + bar: Object { + filename: 'unknown' + end: Object { + column: 17 + index: 18 + line: 2 + } + start: Object { + column: 14 + index: 15 + line: 2 + } + } + foo: Object { + filename: 'unknown' + end: Object { + column: 22 + index: 23 + line: 2 + } + start: Object { + column: 19 + index: 20 + line: 2 + } + } + lol: Object { + filename: 'unknown' + end: Object { + column: 38 + index: 39 + line: 2 + } + start: Object { + column: 35 + index: 36 + line: 2 + } + } + to: Object { + filename: 'unknown' + end: Object { + column: 48 + index: 49 + line: 2 + } + start: Object { + column: 46 + index: 47 + line: 2 + } + } + } dependencies: Array [ es { kind: 'value' @@ -864,6 +1108,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} dependencies: Array [ es { kind: 'value' @@ -900,6 +1145,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} exports: Array [ local { kind: 'value' @@ -969,6 +1215,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} dependencies: Array [ es { kind: 'value' @@ -1026,6 +1273,7 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} firstTopAwaitLocation: Object { filename: 'unknown' end: Object { @@ -1060,6 +1308,21 @@ Object { valueType: 'other' } ] + topLevelLocalBindings: Object { + yes: Object { + filename: 'unknown' + end: Object { + column: 18 + index: 90 + line: 7 + } + start: Object { + column: 15 + index: 87 + line: 7 + } + } + } } ``` @@ -1074,5 +1337,6 @@ Object { importFirstUsage: Array [] moduleType: 'es' syntax: Array [] + topLevelLocalBindings: Object {} } ``` diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies.test.ts b/packages/@romejs/js-compiler/api/analyzeDependencies.test.ts index 8548b32e1c5..7ec0daba375 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies.test.ts +++ b/packages/@romejs/js-compiler/api/analyzeDependencies.test.ts @@ -165,3 +165,10 @@ test('disallow mix of es and cjs exports', async (t) => { exports.bar = 'foo'; `, 'script')); }); + +test('defines topLevelLocalBindings', async (t) => { + t.snapshot(await testAnalyzeDeps(` + import {bar} from 'foo'; + const foo = 'bar'; + `, 'module')); +}); diff --git a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts index c9b1990e34b..51ce390a6f0 100644 --- a/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts +++ b/packages/@romejs/js-compiler/api/analyzeDependencies/index.ts @@ -28,6 +28,7 @@ import { AnalyzeDependencyName, AnalyzeDependencyImportFirstUsage, AnalyzeModuleType, + AnalyzeDependencyTopLevelLocalBindings, } from '@romejs/core'; import {descriptions} from '@romejs/diagnostics'; @@ -250,7 +251,15 @@ export default async function analyzeDependencies( }); } + const topLevelLocalBindings: AnalyzeDependencyTopLevelLocalBindings = {}; + + // Get all top level bindings + for (const [name, binding] of context.getRootScope().evaluate(ast).getOwnBindings()) { + topLevelLocalBindings[name] = binding.node.loc; + } + const res: AnalyzeDependencyResult = { + topLevelLocalBindings, moduleType, firstTopAwaitLocation, exports, From 478d231a9bc196ba0c5f63ef7e938953c5cdcba9 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 22 Mar 2020 17:33:20 -0700 Subject: [PATCH 6/7] Actually reference the module it's in alongside the frame --- packages/@romejs/diagnostics/descriptions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@romejs/diagnostics/descriptions.ts b/packages/@romejs/diagnostics/descriptions.ts index e45607a7df1..e2ce6823647 100644 --- a/packages/@romejs/diagnostics/descriptions.ts +++ b/packages/@romejs/diagnostics/descriptions.ts @@ -743,7 +743,7 @@ export const descriptions = createMessages({ UNKNOWN_EXPORT_POSSIBLE_UNEXPORTED_LOCAL: ( name: string, source: string, - location: DiagnosticLocation, + location: SourceLocation, ) => ({ message: markup`Couldn't find export ${name} in `, @@ -752,7 +752,7 @@ export const descriptions = createMessages({ { type: 'log', category: 'info', - message: 'However we found a matching local variable in this module. Did you forget to export it?', + message: markup`However we found a matching local variable in . Did you forget to export it?`, }, { type: 'frame', From b82a6e28bd4567974c970f7de83d7db86646036a Mon Sep 17 00:00:00 2001 From: Nemesis Date: Mon, 23 Mar 2020 04:41:03 +0100 Subject: [PATCH 7/7] feat(website): improve accessibility (#183) * feat: improve get started btn contrast, focus, change p into a h2 * fix: use right css variable --- website/src/css/custom.css | 1 + website/src/pages/index.js | 4 ++-- website/src/pages/styles.module.css | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 5e89359335f..32f9b83b1f2 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -22,6 +22,7 @@ --ifm-color-primary-light: #f8b949; --ifm-color-primary-lighter: #f9be57; --ifm-color-primary-lightest: #facf81; + --ifm-button-color: #000000; --ifm-code-font-size: 95%; } diff --git a/website/src/pages/index.js b/website/src/pages/index.js index 25a6c10d9cd..518bc110cd0 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -36,9 +36,9 @@ function Home() { Rome is an experimental
JavaScript toolchain -

+

A compiler, linter, formatter, bundler, testing framework and more -

+