diff --git a/docs/architecture/TypeScript_ESTree.mdx b/docs/architecture/TypeScript_ESTree.mdx index 1df714085953..2b7fadedd8f4 100644 --- a/docs/architecture/TypeScript_ESTree.mdx +++ b/docs/architecture/TypeScript_ESTree.mdx @@ -290,39 +290,6 @@ const { ast, services } = parseAndGenerateServices(code, { }); ``` -#### `parseWithNodeMaps(code, options)` - -Parses the given string of code with the options provided and returns both the ESTree-compatible AST as well as the node maps. -This allows you to work with both ASTs without the overhead of types that may come with `parseAndGenerateServices`. - -```ts -interface ParseWithNodeMapsResult { - ast: TSESTree.Program; - esTreeNodeToTSNodeMap: ParserServices['esTreeNodeToTSNodeMap']; - tsNodeToESTreeNodeMap: ParserServices['tsNodeToESTreeNodeMap']; -} - -declare function parseWithNodeMaps( - code: string, - options: ParseOptions = PARSE_DEFAULT_OPTIONS, -): ParseWithNodeMapsResult; -``` - -Example usage: - -```js -import { parseWithNodeMaps } from '@typescript-eslint/typescript-estree'; - -const code = `const hello: string = 'world';`; -const { ast, esTreeNodeToTSNodeMap, tsNodeToESTreeNodeMap } = parseWithNodeMaps( - code, - { - loc: true, - range: true, - }, -); -``` - ### `TSESTree`, `AST_NODE_TYPES` and `AST_TOKEN_TYPES` Types for the AST produced by the parse functions. diff --git a/packages/typescript-estree/src/index.ts b/packages/typescript-estree/src/index.ts index 07dd20bb0605..c86262b7cd9d 100644 --- a/packages/typescript-estree/src/index.ts +++ b/packages/typescript-estree/src/index.ts @@ -2,9 +2,7 @@ export { AST, parse, parseAndGenerateServices, - parseWithNodeMaps, ParseAndGenerateServicesResult, - ParseWithNodeMapsResult, } from './parser'; export { ParserServices, diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 4a3e55e038d2..f5b869c0efc1 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -142,13 +142,6 @@ function parseWithNodeMapsInternal( }; } -function parseWithNodeMaps( - code: string, - options?: T, -): ParseWithNodeMapsResult { - return parseWithNodeMapsInternal(code, options, true); -} - let parseAndGenerateServicesCalls: { [fileName: string]: number } = {}; // Privately exported utility intended for use in typescript-eslint unit tests only function clearParseAndGenerateServicesCalls(): void { @@ -278,9 +271,7 @@ export { AST, parse, parseAndGenerateServices, - parseWithNodeMaps, ParseAndGenerateServicesResult, - ParseWithNodeMapsResult, clearProgramCache, clearParseAndGenerateServicesCalls, }; diff --git a/packages/typescript-estree/tests/lib/__snapshots__/parse.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/parse.test.ts.snap index 8c2e78614356..0f777af2df28 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/parse.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/parse.test.ts.snap @@ -4199,492 +4199,3 @@ exports[`parseAndGenerateServices isolated parsing should parse .vue file - with }, } `; - -exports[`parseWithNodeMaps() general output should not contain loc 1`] = ` -{ - "body": [ - { - "declarations": [ - { - "definite": false, - "id": { - "decorators": [], - "name": "foo", - "optional": false, - "range": [ - 4, - 7, - ], - "type": "Identifier", - }, - "init": { - "decorators": [], - "name": "bar", - "optional": false, - "range": [ - 10, - 13, - ], - "type": "Identifier", - }, - "range": [ - 4, - 13, - ], - "type": "VariableDeclarator", - }, - ], - "declare": false, - "kind": "let", - "range": [ - 0, - 14, - ], - "type": "VariableDeclaration", - }, - ], - "range": [ - 0, - 14, - ], - "sourceType": "script", - "type": "Program", -} -`; - -exports[`parseWithNodeMaps() general output should not contain range 1`] = ` -{ - "body": [ - { - "declarations": [ - { - "definite": false, - "id": { - "decorators": [], - "loc": { - "end": { - "column": 7, - "line": 1, - }, - "start": { - "column": 4, - "line": 1, - }, - }, - "name": "foo", - "optional": false, - "type": "Identifier", - }, - "init": { - "decorators": [], - "loc": { - "end": { - "column": 13, - "line": 1, - }, - "start": { - "column": 10, - "line": 1, - }, - }, - "name": "bar", - "optional": false, - "type": "Identifier", - }, - "loc": { - "end": { - "column": 13, - "line": 1, - }, - "start": { - "column": 4, - "line": 1, - }, - }, - "type": "VariableDeclarator", - }, - ], - "declare": false, - "kind": "let", - "loc": { - "end": { - "column": 14, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "type": "VariableDeclaration", - }, - ], - "loc": { - "end": { - "column": 14, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "sourceType": "script", - "type": "Program", -} -`; - -exports[`parseWithNodeMaps() general output tokens, comments, locs, and ranges when called with those options 1`] = ` -{ - "body": [ - { - "declarations": [ - { - "definite": false, - "id": { - "decorators": [], - "loc": { - "end": { - "column": 7, - "line": 1, - }, - "start": { - "column": 4, - "line": 1, - }, - }, - "name": "foo", - "optional": false, - "range": [ - 4, - 7, - ], - "type": "Identifier", - }, - "init": { - "decorators": [], - "loc": { - "end": { - "column": 13, - "line": 1, - }, - "start": { - "column": 10, - "line": 1, - }, - }, - "name": "bar", - "optional": false, - "range": [ - 10, - 13, - ], - "type": "Identifier", - }, - "loc": { - "end": { - "column": 13, - "line": 1, - }, - "start": { - "column": 4, - "line": 1, - }, - }, - "range": [ - 4, - 13, - ], - "type": "VariableDeclarator", - }, - ], - "declare": false, - "kind": "let", - "loc": { - "end": { - "column": 14, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 14, - ], - "type": "VariableDeclaration", - }, - ], - "comments": [], - "loc": { - "end": { - "column": 14, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 14, - ], - "sourceType": "script", - "tokens": [ - { - "loc": { - "end": { - "column": 3, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 3, - ], - "type": "Keyword", - "value": "let", - }, - { - "loc": { - "end": { - "column": 7, - "line": 1, - }, - "start": { - "column": 4, - "line": 1, - }, - }, - "range": [ - 4, - 7, - ], - "type": "Identifier", - "value": "foo", - }, - { - "loc": { - "end": { - "column": 9, - "line": 1, - }, - "start": { - "column": 8, - "line": 1, - }, - }, - "range": [ - 8, - 9, - ], - "type": "Punctuator", - "value": "=", - }, - { - "loc": { - "end": { - "column": 13, - "line": 1, - }, - "start": { - "column": 10, - "line": 1, - }, - }, - "range": [ - 10, - 13, - ], - "type": "Identifier", - "value": "bar", - }, - { - "loc": { - "end": { - "column": 14, - "line": 1, - }, - "start": { - "column": 13, - "line": 1, - }, - }, - "range": [ - 13, - 14, - ], - "type": "Punctuator", - "value": ";", - }, - ], - "type": "Program", -} -`; - -exports[`parseWithNodeMaps() non string code should correctly convert code to a string for parse() 1`] = ` -{ - "body": [ - { - "expression": { - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "raw": "12345", - "type": "Literal", - "value": 12345, - }, - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "type": "ExpressionStatement", - }, - ], - "comments": [], - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "sourceType": "script", - "tokens": [ - { - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "type": "Numeric", - "value": "12345", - }, - ], - "type": "Program", -} -`; - -exports[`parseWithNodeMaps() non string code should correctly convert code to a string for parseAndGenerateServices() 1`] = ` -{ - "body": [ - { - "expression": { - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "raw": "12345", - "type": "Literal", - "value": 12345, - }, - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "type": "ExpressionStatement", - }, - ], - "comments": [], - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "sourceType": "script", - "tokens": [ - { - "loc": { - "end": { - "column": 5, - "line": 1, - }, - "start": { - "column": 0, - "line": 1, - }, - }, - "range": [ - 0, - 5, - ], - "type": "Numeric", - "value": "12345", - }, - ], - "type": "Program", -} -`; diff --git a/packages/typescript-estree/tests/lib/parse.test.ts b/packages/typescript-estree/tests/lib/parse.test.ts index 6e2adac8f870..7b4503513345 100644 --- a/packages/typescript-estree/tests/lib/parse.test.ts +++ b/packages/typescript-estree/tests/lib/parse.test.ts @@ -5,26 +5,12 @@ import { join, resolve } from 'path'; import type * as typescriptModule from 'typescript'; import * as parser from '../../src'; -import * as astConverterModule from '../../src/ast-converter'; import * as sharedParserUtilsModule from '../../src/create-program/shared'; import type { TSESTreeOptions } from '../../src/parser-options'; import { clearGlobResolutionCache } from '../../src/parseSettings/resolveProjectList'; -import { createSnapshotTestBlock } from '../../tools/test-utils'; const FIXTURES_DIR = join(__dirname, '../fixtures/simpleProject'); -// we can't spy on the exports of an ES module - so we instead have to mock the entire module -jest.mock('../../src/ast-converter', () => { - const astConverterActual = jest.requireActual( - '../../src/ast-converter', - ); - - return { - ...astConverterActual, - __esModule: true, - astConverter: jest.fn(astConverterActual.astConverter), - }; -}); jest.mock('../../src/create-program/shared', () => { const sharedActual = jest.requireActual( '../../src/create-program/shared', @@ -62,7 +48,6 @@ jest.mock('globby', () => { const hrtimeSpy = jest.spyOn(process, 'hrtime'); -const astConverterMock = jest.mocked(astConverterModule.astConverter); const createDefaultCompilerOptionsFromExtra = jest.mocked( sharedParserUtilsModule.createDefaultCompilerOptionsFromExtra, ); @@ -81,139 +66,6 @@ beforeEach(() => { clearGlobResolutionCache(); }); -describe('parseWithNodeMaps()', () => { - describe('basic functionality', () => { - it('should parse an empty string', () => { - expect(parser.parseWithNodeMaps('').ast.body).toEqual([]); - expect(parser.parseWithNodeMaps('', {}).ast.body).toEqual([]); - }); - - it('parse() should be the same as parseWithNodeMaps().ast', () => { - const code = 'const x: number = 1;'; - expect(parser.parseWithNodeMaps(code).ast).toMatchObject( - parser.parse(code), - ); - }); - - it('should simple code', () => { - const result = parser.parseWithNodeMaps('1;'); - expect(result.ast).toMatchInlineSnapshot(` - { - "body": [ - { - "directive": undefined, - "expression": { - "raw": "1", - "type": "Literal", - "value": 1, - }, - "type": "ExpressionStatement", - }, - ], - "comments": undefined, - "sourceType": "script", - "tokens": undefined, - "type": "Program", - } - `); - const tsNode = result.esTreeNodeToTSNodeMap.get(result.ast.body[0]); - expect(tsNode).toBeDefined(); - expect(result.tsNodeToESTreeNodeMap.get(tsNode)).toBeDefined(); - }); - }); - - describe('modules', () => { - it('should have correct column number when strict mode error occurs', () => { - try { - parser.parseWithNodeMaps('function fn(a, a) {\n}'); - } catch ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - err: any - ) { - expect(err.column).toBe(16); - } - }); - }); - - describe('general', () => { - const code = 'let foo = bar;'; - const config: TSESTreeOptions = { - comment: true, - tokens: true, - range: true, - loc: true, - }; - - it( - 'output tokens, comments, locs, and ranges when called with those options', - createSnapshotTestBlock(code, config), - ); - - it( - 'output should not contain loc', - createSnapshotTestBlock(code, { - range: true, - loc: false, - }), - ); - - it( - 'output should not contain range', - createSnapshotTestBlock(code, { - range: false, - loc: true, - }), - ); - }); - - describe('non string code', () => { - // testing a non string code.. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const code = 12345 as any as string; - const config: TSESTreeOptions = { - comment: true, - tokens: true, - range: true, - loc: true, - }; - - it( - 'should correctly convert code to a string for parse()', - createSnapshotTestBlock(code, config), - ); - - it( - 'should correctly convert code to a string for parseAndGenerateServices()', - createSnapshotTestBlock(code, config, true), - ); - }); - - describe('loggerFn should be propagated to ast-converter', () => { - it('output tokens, comments, locs, and ranges when called with those options', () => { - const loggerFn = jest.fn(() => {}); - - parser.parseWithNodeMaps('let foo = bar;', { - loggerFn, - comment: true, - tokens: true, - range: true, - loc: true, - }); - - expect(astConverterMock).toHaveBeenCalled(); - expect(astConverterMock.mock.calls[0][1]).toMatchObject({ - code: 'let foo = bar;', - comment: true, - comments: [], - loc: true, - log: loggerFn, - range: true, - tokens: expect.any(Array), - }); - }); - }); -}); - describe('parseAndGenerateServices', () => { describe('preserveNodeMaps', () => { const code = 'var a = true'; @@ -252,31 +104,6 @@ describe('parseAndGenerateServices', () => { ); }); - it('should not impact the use of parseWithNodeMaps()', () => { - const resultWithNoOptionSet = parser.parseWithNodeMaps(code, baseConfig); - const resultWithOptionSetToTrue = parser.parseWithNodeMaps(code, { - ...baseConfig, - preserveNodeMaps: true, - }); - const resultWithOptionSetToFalse = parser.parseWithNodeMaps(code, { - ...baseConfig, - preserveNodeMaps: false, - }); - const resultWithOptionSetExplicitlyToUndefined = parser.parseWithNodeMaps( - code, - { - ...baseConfig, - preserveNodeMaps: undefined, - }, - ); - - expect(resultWithNoOptionSet).toMatchObject(resultWithOptionSetToTrue); - expect(resultWithNoOptionSet).toMatchObject(resultWithOptionSetToFalse); - expect(resultWithNoOptionSet).toMatchObject( - resultWithOptionSetExplicitlyToUndefined, - ); - }); - it('should preserve node maps by default for parseAndGenerateServices()', () => { const noOptionSet = parser.parseAndGenerateServices(code, baseConfig);