diff --git a/packages/ast-spec/src/declaration/ClassDeclaration/fixtures/_error_/export-missing-name/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/ClassDeclaration/fixtures/_error_/export-missing-name/snapshots/1-TSESTree-Error.shot index 871a8fa73bd..428e6049da8 100644 --- a/packages/ast-spec/src/declaration/ClassDeclaration/fixtures/_error_/export-missing-name/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/ClassDeclaration/fixtures/_error_/export-missing-name/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration ClassDeclaration _error_ export-missing-name TSESTree - Error 1`] = ` "TSError > 1 | export class { } - | ^ A class declaration without the 'default' modifier must have a name. + | ^^^^^^^^^^^^^^^^ A class declaration without the 'default' modifier must have a name. 2 |" `; diff --git a/packages/ast-spec/src/declaration/ExportAllDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/ExportAllDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot index 52c5c7981ca..f3e5cca5923 100644 --- a/packages/ast-spec/src/declaration/ExportAllDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/ExportAllDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration ExportAllDeclaration _error_ non-string-source TSESTree - Error 1`] = ` "TSError > 1 | export * from module; - | ^ Module specifier must be a string literal. + | ^^^^^^ Module specifier must be a string literal. 2 |" `; diff --git a/packages/ast-spec/src/declaration/ExportNamedDeclaration/fixtures/_error_/anonymous-class/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/ExportNamedDeclaration/fixtures/_error_/anonymous-class/snapshots/1-TSESTree-Error.shot index 56c490f6432..499868339f5 100644 --- a/packages/ast-spec/src/declaration/ExportNamedDeclaration/fixtures/_error_/anonymous-class/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/ExportNamedDeclaration/fixtures/_error_/anonymous-class/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration ExportNamedDeclaration _error_ anonymous-class TSESTree - Error 1`] = ` "TSError > 1 | export class {} - | ^ A class declaration without the 'default' modifier must have a name. + | ^^^^^^^^^^^^^^^ A class declaration without the 'default' modifier must have a name. 2 |" `; diff --git a/packages/ast-spec/src/declaration/ImportDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/ImportDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot index 93ead06a43f..9c245972b5d 100644 --- a/packages/ast-spec/src/declaration/ImportDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/ImportDeclaration/fixtures/_error_/non-string-source/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration ImportDeclaration _error_ non-string-source TSESTree - Error 1`] = ` "TSError > 1 | import * as x from module; - | ^ Module specifier must be a string literal. + | ^^^^^^ Module specifier must be a string literal. 2 |" `; diff --git a/packages/ast-spec/src/declaration/TSEnumDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/TSEnumDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot index 63b726390f8..7e24abcf6f6 100644 --- a/packages/ast-spec/src/declaration/TSEnumDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/TSEnumDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration TSEnumDeclaration _error_ decorator TSESTree - Error 1`] = ` "TSError > 1 | @decl enum Test {} - | ^ Decorators are not valid here. + | ^^^^^ Decorators are not valid here. 2 |" `; diff --git a/packages/ast-spec/src/declaration/TSInterfaceDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/TSInterfaceDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot index b97c19c1658..de2011df9ce 100644 --- a/packages/ast-spec/src/declaration/TSInterfaceDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/TSInterfaceDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration TSInterfaceDeclaration _error_ decorator TSESTree - Error 1`] = ` "TSError > 1 | @decl interface Test {} - | ^ Decorators are not valid here. + | ^^^^^ Decorators are not valid here. 2 |" `; diff --git a/packages/ast-spec/src/declaration/TSTypeAliasDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/TSTypeAliasDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot index a9881c8490e..1392b9b0742 100644 --- a/packages/ast-spec/src/declaration/TSTypeAliasDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/TSTypeAliasDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration TSTypeAliasDeclaration _error_ decorator TSESTree - Error 1`] = ` "TSError > 1 | @decl type Test = {}; - | ^ Decorators are not valid here. + | ^^^^^ Decorators are not valid here. 2 |" `; diff --git a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot index 7f4b1ed5013..fb0803d0ca0 100644 --- a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/decorator/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration VariableDeclaration _error_ decorator TSESTree - Error 1`] = ` "TSError > 1 | @decl type Test = {}; - | ^ Decorators are not valid here. + | ^^^^^ Decorators are not valid here. 2 |" `; diff --git a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/missing-id-without-value/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/missing-id-without-value/snapshots/1-TSESTree-Error.shot index d3d985a8aac..dedcabc0bbf 100644 --- a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/missing-id-without-value/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/missing-id-without-value/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration VariableDeclaration _error_ missing-id-without-value TSESTree - Error 1`] = ` "TSError > 1 | const; - | ^ A variable declaration list must have at least one variable declarator. + | ^^^^^^ A variable declaration list must have at least one variable declarator. 2 |" `; diff --git a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/no-variables/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/no-variables/snapshots/1-TSESTree-Error.shot index 7f955d4645e..318ceeec614 100644 --- a/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/no-variables/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/declaration/VariableDeclaration/fixtures/_error_/no-variables/snapshots/1-TSESTree-Error.shot @@ -3,6 +3,6 @@ exports[`AST Fixtures declaration VariableDeclaration _error_ no-variables TSESTree - Error 1`] = ` "TSError > 1 | const; - | ^ A variable declaration list must have at least one variable declarator. + | ^^^^^^ A variable declaration list must have at least one variable declarator. 2 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/basics/fixtures/_error_/class-with-export-parameter-properties/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/basics/fixtures/_error_/class-with-export-parameter-properties/snapshots/1-TSESTree-Error.shot index 1cbe0b6996d..c54977ea56f 100644 --- a/packages/ast-spec/src/legacy-fixtures/basics/fixtures/_error_/class-with-export-parameter-properties/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/basics/fixtures/_error_/class-with-export-parameter-properties/snapshots/1-TSESTree-Error.shot @@ -5,7 +5,7 @@ exports[`AST Fixtures legacy-fixtures basics _error_ class-with-export-parameter 2 | 3 | class Foo { > 4 | constructor(export a: string) { - | ^ A parameter cannot have an export modifier. + | ^^^^^^ A parameter cannot have an export modifier. 5 | 6 | } 7 | }" diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-enum-declaration/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-enum-declaration/snapshots/1-TSESTree-Error.shot index 83e4badaaad..3055b0dc449 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-enum-declaration/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-enum-declaration/snapshots/1-TSESTree-Error.shot @@ -2,8 +2,8 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-enum-declaration TSESTree - Error 1`] = ` "TSError -> 1 | // TODO: This fixture might be too large, and if so should be split up. - | ^ Decorators are not valid here. + 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | - 3 | @dec enum E {}" +> 3 | @dec enum E {} + | ^^^^ Decorators are not valid here." `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-interface-declaration/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-interface-declaration/snapshots/1-TSESTree-Error.shot index edd55201765..45ea7f53044 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-interface-declaration/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-interface-declaration/snapshots/1-TSESTree-Error.shot @@ -2,9 +2,9 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-interface-declaration TSESTree - Error 1`] = ` "TSError -> 1 | // TODO: This fixture might be too large, and if so should be split up. - | ^ Decorators are not valid here. + 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | - 3 | @deco() +> 3 | @deco() + | ^^^^^^^ Decorators are not valid here. 4 | interface M {}" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-variable/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-variable/snapshots/1-TSESTree-Error.shot index 1ec303a3706..69123261b06 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-variable/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-variable/snapshots/1-TSESTree-Error.shot @@ -2,9 +2,10 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-variable TSESTree - Error 1`] = ` "TSError -> 1 | // TODO: This fixture might be too large, and if so should be split up. - | ^ Decorators are not valid here. + 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | - 3 | @deco() - 4 | const a = 1" +> 3 | @deco() + | ^^^^^^^ Decorators are not valid here. + 4 | const a = 1 + 5 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-index-signature-export/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-index-signature-export/snapshots/1-TSESTree-Error.shot index 026026fb4c0..699355afeef 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-index-signature-export/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-index-signature-export/snapshots/1-TSESTree-Error.shot @@ -2,11 +2,11 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ interface-index-signature-export TSESTree - Error 1`] = ` "TSError - 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | -> 3 | interface Foo { - | ^ An index signature cannot have an export modifier. - 4 | export [baz: string]: string; + 3 | interface Foo { +> 4 | export [baz: string]: string; + | ^^^^^^ An index signature cannot have an export modifier. 5 | } - 6 |" + 6 | + 7 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-method-export/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-method-export/snapshots/1-TSESTree-Error.shot index 460cd78d0cc..36f8fd7fddd 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-method-export/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-method-export/snapshots/1-TSESTree-Error.shot @@ -2,11 +2,11 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ interface-method-export TSESTree - Error 1`] = ` "TSError - 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | -> 3 | interface Foo { - | ^ A method signature cannot have an export modifier. - 4 | export g(bar: string): void; + 3 | interface Foo { +> 4 | export g(bar: string): void; + | ^^^^^^ A method signature cannot have an export modifier. 5 | } - 6 |" + 6 | + 7 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-export/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-export/snapshots/1-TSESTree-Error.shot index 95024673e53..f21b92669e1 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-export/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-export/snapshots/1-TSESTree-Error.shot @@ -2,11 +2,11 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ interface-property-export TSESTree - Error 1`] = ` "TSError - 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | -> 3 | interface Foo { - | ^ A property signature cannot have an export modifier. - 4 | export a: string; + 3 | interface Foo { +> 4 | export a: string; + | ^^^^^^ A property signature cannot have an export modifier. 5 | } - 6 |" + 6 | + 7 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-with-default-value/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-with-default-value/snapshots/1-TSESTree-Error.shot index 9cc70379ece..9e58d0d1603 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-with-default-value/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-with-default-value/snapshots/1-TSESTree-Error.shot @@ -2,11 +2,10 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ interface-property-with-default-value TSESTree - Error 1`] = ` "TSError - 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | -> 3 | interface Foo { - | ^ A property signature cannot have an initializer. - 4 | bar: string = 'a'; + 3 | interface Foo { +> 4 | bar: string = 'a'; + | ^^^ A property signature cannot have an initializer. 5 | } 6 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-assertion-not-allowed/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-assertion-not-allowed/snapshots/1-TSESTree-Error.shot index 52debdfd81d..4ed8a518fdc 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-assertion-not-allowed/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-assertion-not-allowed/snapshots/1-TSESTree-Error.shot @@ -5,6 +5,6 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ object-assertion-not 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | > 3 | ({a!} = {}) - | ^ A shorthand property assignment cannot have an exclamation token. + | ^ A shorthand property assignment cannot have an exclamation token. 4 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-optional-not-allowed/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-optional-not-allowed/snapshots/1-TSESTree-Error.shot index a12f4a288f5..684488f02c2 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-optional-not-allowed/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/object-optional-not-allowed/snapshots/1-TSESTree-Error.shot @@ -5,6 +5,6 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ object-optional-not- 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | > 3 | ({a?} = {}) - | ^ A shorthand property assignment cannot have a question token. + | ^ A shorthand property assignment cannot have a question token. 4 |" `; diff --git a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/solo-const/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/solo-const/snapshots/1-TSESTree-Error.shot index 6eeef3970c5..c178e7e591b 100644 --- a/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/solo-const/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/legacy-fixtures/errorRecovery/fixtures/_error_/solo-const/snapshots/1-TSESTree-Error.shot @@ -2,8 +2,8 @@ exports[`AST Fixtures legacy-fixtures errorRecovery _error_ solo-const TSESTree - Error 1`] = ` "TSError -> 1 | // TODO: This fixture might be too large, and if so should be split up. - | ^ A variable declaration list must have at least one variable declarator. + 1 | // TODO: This fixture might be too large, and if so should be split up. 2 | - 3 | const" +> 3 | const + | ^^^^^ A variable declaration list must have at least one variable declarator." `; diff --git a/packages/ast-spec/src/statement/ThrowStatement/fixtures/_error_/missing-argument/snapshots/1-TSESTree-Error.shot b/packages/ast-spec/src/statement/ThrowStatement/fixtures/_error_/missing-argument/snapshots/1-TSESTree-Error.shot index 4f6e41ca602..cf149c8bdc2 100644 --- a/packages/ast-spec/src/statement/ThrowStatement/fixtures/_error_/missing-argument/snapshots/1-TSESTree-Error.shot +++ b/packages/ast-spec/src/statement/ThrowStatement/fixtures/_error_/missing-argument/snapshots/1-TSESTree-Error.shot @@ -2,9 +2,9 @@ exports[`AST Fixtures statement ThrowStatement _error_ missing-argument TSESTree - Error 1`] = ` "TSError -> 1 | { - | ^ A throw statement must throw an expression. - 2 | throw + 1 | { +> 2 | throw + | ^^^^^ A throw statement must throw an expression. 3 | } 4 |" `; diff --git a/packages/ast-spec/tests/util/serialize-error.ts b/packages/ast-spec/tests/util/serialize-error.ts index 31e3715f247..ee8597c6148 100644 --- a/packages/ast-spec/tests/util/serialize-error.ts +++ b/packages/ast-spec/tests/util/serialize-error.ts @@ -10,13 +10,21 @@ export function serializeError( return error; } - const { message, lineNumber: line, column, name } = error; + const { + name, + message, + location: { start, end }, + } = error; + return ( name + '\n' + codeFrameColumns( contents, - { start: { line, column: column + 1 } }, + { + start: { line: start.line, column: start.column + 1 }, + end: { line: end.line, column: end.column + 1 }, + }, { highlightCode: false, message }, ) ); diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 96bbaa0fe1b..5d7558dae43 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -13,6 +13,7 @@ import { getLastModifier, getLineAndCharacterFor, getLocFor, + getModifier, getRange, getTextForTokenKind, getTSNodeAccessibility, @@ -52,9 +53,9 @@ export function convertError( error: ts.DiagnosticWithLocation | SemanticOrSyntacticError, ): TSError { return createError( + ('message' in error && error.message) || (error.messageText as string), error.file!, error.start!, - ('message' in error && error.message) || (error.messageText as string), ); } @@ -446,9 +447,8 @@ export class Converter { */ private deeplyCopy(node: TSNode): any { if (node.kind === ts.SyntaxKind.JSDocFunctionType) { - throw createError( - this.ast, - node.pos, + this.#throwError( + node, 'JSDoc types can only be used inside documentation comments.', ); } @@ -591,7 +591,7 @@ export class Converter { if (node.name.kind === SyntaxKind.PrivateIdentifier) { // This is one of the few times where TS explicitly errors, and doesn't even gracefully handle the syntax. // So we shouldn't ever get into this state to begin with. - throw new Error('Non-private identifier expected.'); + this.#throwError(node.name, 'Non-private identifier expected.'); } result = this.createNode(node, { @@ -617,9 +617,10 @@ export class Converter { | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration, ): TSESTree.TSMethodSignature { - if (hasModifier(SyntaxKind.ExportKeyword, node)) { + const exportKeyword = getModifier(SyntaxKind.ExportKeyword, node); + if (exportKeyword) { this.#throwUnlessAllowInvalidAST( - node.pos, + exportKeyword, 'A method signature cannot have an export modifier.', ); } @@ -687,7 +688,7 @@ export class Converter { ): void { if (!allowNull && node.moduleSpecifier == null) { this.#throwUnlessAllowInvalidAST( - node.pos, + node, 'Module specifier must be a string literal.', ); } @@ -697,7 +698,7 @@ export class Converter { node.moduleSpecifier?.kind !== SyntaxKind.StringLiteral ) { this.#throwUnlessAllowInvalidAST( - node.moduleSpecifier.pos, + node.moduleSpecifier, 'Module specifier must be a string literal.', ); } @@ -824,7 +825,7 @@ export class Converter { case SyntaxKind.ThrowStatement: if (node.expression.end === node.expression.pos) { this.#throwUnlessAllowInvalidAST( - node.pos, + node, 'A throw statement must throw an expression.', ); } @@ -960,7 +961,7 @@ export class Converter { if (!result.declarations.length) { this.#throwUnlessAllowInvalidAST( - node.pos, + node, 'A variable declaration list must have at least one variable declarator.', ); } @@ -1034,20 +1035,23 @@ export class Converter { } } - case SyntaxKind.PropertyAssignment: - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.questionToken, - 'A property assignment cannot have a question token.', - ); + case SyntaxKind.PropertyAssignment: { + // eslint-disable-next-line deprecation/deprecation + const { questionToken, exclamationToken } = node; - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.exclamationToken, - 'A property assignment cannot have an exclamation token.', - ); + if (questionToken) { + this.#throwError( + questionToken, + 'A property assignment cannot have a question token.', + ); + } + + if (exclamationToken) { + this.#throwError( + exclamationToken, + 'A property assignment cannot have an exclamation token.', + ); + } return this.createNode(node, { type: AST_NODE_TYPES.Property, @@ -1059,28 +1063,32 @@ export class Converter { shorthand: false, kind: 'init', }); + } case SyntaxKind.ShorthandPropertyAssignment: { - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.modifiers, - 'A shorthand property assignment cannot have modifiers.', - ); + // eslint-disable-next-line deprecation/deprecation + const { modifiers, questionToken, exclamationToken } = node; - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.questionToken, - 'A shorthand property assignment cannot have a question token.', - ); + if (modifiers) { + this.#throwError( + modifiers[0], + 'A shorthand property assignment cannot have modifiers.', + ); + } - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.exclamationToken, - 'A shorthand property assignment cannot have an exclamation token.', - ); + if (questionToken) { + this.#throwError( + questionToken, + 'A shorthand property assignment cannot have a question token.', + ); + } + + if (exclamationToken) { + this.#throwError( + exclamationToken, + 'A shorthand property assignment cannot have an exclamation token.', + ); + } if (node.objectAssignmentInitializer) { return this.createNode(node, { @@ -1627,9 +1635,10 @@ export class Converter { const modifiers = getModifiers(node); if (modifiers) { - if (hasModifier(SyntaxKind.ExportKeyword, node)) { + const exportKeyword = getModifier(SyntaxKind.ExportKeyword, node); + if (exportKeyword) { this.#throwUnlessAllowInvalidAST( - node.pos, + exportKeyword, 'A parameter cannot have an export modifier.', ); } @@ -1656,7 +1665,7 @@ export class Converter { !hasModifier(ts.SyntaxKind.DefaultKeyword, node)) ) { this.#throwUnlessAllowInvalidAST( - node.pos, + node, "A class declaration without the 'default' modifier must have a name.", ); } @@ -1674,7 +1683,7 @@ export class Converter { if (superClass && superClass.types.length > 1) { this.#throwUnlessAllowInvalidAST( - superClass.types[1].pos, + superClass.types[1], 'Classes can only extend a single class.', ); } @@ -1716,7 +1725,7 @@ export class Converter { if (superClass) { if (superClass.types.length > 1) { this.#throwUnlessAllowInvalidAST( - superClass.types[1].pos, + superClass.types[1], 'Classes can only extend a single class.', ); } @@ -2011,7 +2020,7 @@ export class Converter { if (node.expression.kind === SyntaxKind.ImportKeyword) { if (node.arguments.length !== 1 && node.arguments.length !== 2) { this.#throwUnlessAllowInvalidAST( - node.arguments.pos, + node.arguments[0], 'Dynamic import requires exactly one or two arguments.', ); } @@ -2480,16 +2489,19 @@ export class Converter { } case SyntaxKind.PropertySignature: { - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.initializer, - 'A property signature cannot have an initializer.', - ); + // eslint-disable-next-line deprecation/deprecation + const { initializer } = node; + if (initializer) { + this.#throwError( + initializer, + 'A property signature cannot have an initializer.', + ); + } - if (hasModifier(SyntaxKind.ExportKeyword, node)) { + const exportKeyword = getModifier(SyntaxKind.ExportKeyword, node); + if (exportKeyword) { this.#throwUnlessAllowInvalidAST( - node.pos, + exportKeyword, 'A property signature cannot have an export modifier.', ); } @@ -2508,9 +2520,10 @@ export class Converter { } case SyntaxKind.IndexSignature: { - if (hasModifier(SyntaxKind.ExportKeyword, node)) { + const exportKeyword = getModifier(SyntaxKind.ExportKeyword, node); + if (exportKeyword) { this.#throwUnlessAllowInvalidAST( - node.pos, + exportKeyword, 'An index signature cannot have an export modifier.', ); } @@ -2540,13 +2553,16 @@ export class Converter { }); } - case SyntaxKind.FunctionType: - this.#throwErrorIfDeprecatedPropertyExists( - node, - // eslint-disable-next-line deprecation/deprecation - node.modifiers, - 'A function type cannot have modifiers.', - ); + case SyntaxKind.FunctionType: { + // eslint-disable-next-line deprecation/deprecation + const { modifiers } = node; + if (modifiers) { + this.#throwError( + modifiers[0], + 'A function type cannot have modifiers.', + ); + } + } // intentional fallthrough case SyntaxKind.ConstructSignature: case SyntaxKind.CallSignature: { @@ -2732,13 +2748,13 @@ export class Converter { body.type === AST_NODE_TYPES.TSModuleDeclaration ) { this.#throwUnlessAllowInvalidAST( - (node.body ?? node).pos, + node.body ?? node, 'Expected a valid module body', ); } if (id.type !== AST_NODE_TYPES.Identifier) { this.#throwUnlessAllowInvalidAST( - node.name.pos, + node.name, 'global module augmentation must have an Identifier id', ); } @@ -2769,20 +2785,17 @@ export class Converter { // with the innermost node's body as the actual node body. if (node.body == null) { - this.#throwUnlessAllowInvalidAST( - node.pos, - 'Expected a module body', - ); + this.#throwUnlessAllowInvalidAST(node, 'Expected a module body'); } if (node.name.kind !== ts.SyntaxKind.Identifier) { this.#throwUnlessAllowInvalidAST( - node.name.pos, + node.name, '`namespace`s must have an Identifier id', ); } let name: TSESTree.Identifier | TSESTree.TSQualifiedName = - this.createNode(node.name as ts.Identifier, { + this.createNode(node.name, { decorators: [], name: node.name.text, optional: false, @@ -3020,25 +3033,22 @@ export class Converter { #checkIllegalDecorators(node: ts.Node): void { if (nodeHasIllegalDecorators(node)) { this.#throwUnlessAllowInvalidAST( - node.pos, + node.illegalDecorators[0], 'Decorators are not valid here.', ); } } - #throwUnlessAllowInvalidAST(pos: number, message: string): void { + #throwUnlessAllowInvalidAST( + node: ts.Node, + message: string, + ): asserts node is never { if (!this.options.allowInvalidAST) { - throw createError(this.ast, pos, message); + this.#throwError(node, message); } } - #throwErrorIfDeprecatedPropertyExists( - node: Node, - property: unknown, - message: string, - ): void { - if (property) { - throw createError(this.ast, node.pos, message); - } + #throwError(node: ts.Node, message: string): asserts node is never { + throw createError(message, this.ast, node.getStart(), node.getEnd()); } } diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index db2cc2c4cb2..9386a76a2a8 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -87,6 +87,21 @@ export function hasModifier( return modifiers?.some(modifier => modifier.kind === modifierKind) === true; } +/** + * Get a modifier from a ts.Node + * @param modifierKind TypeScript SyntaxKind modifier + * @param node TypeScript AST node + * @returns matched modifier if present or null + */ +export function getModifier( + modifierKind: ts.KeywordSyntaxKind, + node: ts.Node, +): ts.Modifier | null { + return ( + getModifiers(node)?.find(modifier => modifier.kind === modifierKind) ?? null + ); +} + /** * Get last last modifier in ast * @param node TypeScript AST node @@ -600,9 +615,18 @@ export class TSError extends Error { constructor( message: string, public readonly fileName: string, - public readonly index: number, - public readonly lineNumber: number, - public readonly column: number, + public readonly location: { + start: { + line: number; + column: number; + offset: number; + }; + end: { + line: number; + column: number; + offset: number; + }; + }, ) { super(message); Object.defineProperty(this, 'name', { @@ -611,24 +635,47 @@ export class TSError extends Error { configurable: true, }); } + + // For old version of ESLint https://github.com/typescript-eslint/typescript-eslint/pull/6556#discussion_r1123237311 + get index(): number { + return this.location.start.offset; + } + + // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L853 + get lineNumber(): number { + return this.location.start.line; + } + + // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L854 + get column(): number { + return this.location.start.column; + } } /** - * @param ast the AST object - * @param start the index at which the error starts * @param message the error message + * @param ast the AST object + * @param startIndex the index at which the error starts + * @param endIndex the index at which the error ends * @returns converted error object */ export function createError( - ast: ts.SourceFile, - start: number, message: string, + ast: ts.SourceFile, + startIndex: number, + endIndex: number = startIndex, ): TSError { - const loc = ast.getLineAndCharacterOfPosition(start); - return new TSError(message, ast.fileName, start, loc.line + 1, loc.character); + const [start, end] = [startIndex, endIndex].map(offset => { + const { line, character: column } = + ast.getLineAndCharacterOfPosition(offset); + return { line: line + 1, column, offset }; + }); + return new TSError(message, ast.fileName, { start, end }); } -export function nodeHasIllegalDecorators(node: ts.Node): boolean { +export function nodeHasIllegalDecorators( + node: ts.Node, +): node is ts.Node & { illegalDecorators: ts.Node[] } { return !!( 'illegalDecorators' in node && (node.illegalDecorators as unknown[] | undefined)?.length