diff --git a/parser.js b/parser.js index dec3cd6..995c1eb 100644 --- a/parser.js +++ b/parser.js @@ -8,7 +8,7 @@ "use strict"; -const parse = require("typescript-estree").parse; +const parse = require("typescript-estree").parseAndGenerateServices; const astNodeTypes = require("typescript-estree").AST_NODE_TYPES; const traverser = require("eslint/lib/util/traverser"); const analyzeScope = require("./analyze-scope"); @@ -40,7 +40,7 @@ exports.parseForESLint = function parseForESLint(code, options) { options.sourceType = "script"; } - const ast = parse(code, options); + const { ast, services } = parse(code, options); ast.sourceType = options.sourceType; traverser.traverse(ast, { @@ -58,7 +58,7 @@ exports.parseForESLint = function parseForESLint(code, options) { }); const scopeManager = analyzeScope(ast, options); - return { ast, scopeManager, visitorKeys }; + return { ast, services, scopeManager, visitorKeys }; }; exports.parse = function(code, options) { diff --git a/tests/fixtures/services/isolated-file.src.ts b/tests/fixtures/services/isolated-file.src.ts new file mode 100644 index 0000000..ca04667 --- /dev/null +++ b/tests/fixtures/services/isolated-file.src.ts @@ -0,0 +1 @@ +const x = [3, 4, 5]; \ No newline at end of file diff --git a/tests/fixtures/services/tsconfig.json b/tests/fixtures/services/tsconfig.json new file mode 100644 index 0000000..3caa872 --- /dev/null +++ b/tests/fixtures/services/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "strict": true, + "esModuleInterop": true + } +} \ No newline at end of file diff --git a/tests/lib/__snapshots__/services.js.snap b/tests/lib/__snapshots__/services.js.snap new file mode 100644 index 0000000..608c4f7 --- /dev/null +++ b/tests/lib/__snapshots__/services.js.snap @@ -0,0 +1,356 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`services fixtures/isolated-file.src 1`] = ` +Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "elements": Array [ + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 12, + ], + "raw": "3", + "type": "Literal", + "value": 3, + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 14, + "line": 1, + }, + }, + "range": Array [ + 14, + 15, + ], + "raw": "4", + "type": "Literal", + "value": 4, + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "raw": "5", + "type": "Literal", + "value": 5, + }, + ], + "loc": Object { + "end": Object { + "column": 19, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 19, + ], + "type": "ArrayExpression", + }, + "loc": Object { + "end": Object { + "column": 19, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 19, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 20, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 20, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "[", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 12, + ], + "type": "Numeric", + "value": "3", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 1, + }, + "start": Object { + "column": 12, + "line": 1, + }, + }, + "range": Array [ + 12, + 13, + ], + "type": "Punctuator", + "value": ",", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 14, + "line": 1, + }, + }, + "range": Array [ + 14, + 15, + ], + "type": "Numeric", + "value": "4", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": ",", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Numeric", + "value": "5", + }, + Object { + "loc": Object { + "end": Object { + "column": 19, + "line": 1, + }, + "start": Object { + "column": 18, + "line": 1, + }, + }, + "range": Array [ + 18, + 19, + ], + "type": "Punctuator", + "value": "]", + }, + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 19, + "line": 1, + }, + }, + "range": Array [ + 19, + 20, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/tests/lib/services.js b/tests/lib/services.js new file mode 100644 index 0000000..62bef8d --- /dev/null +++ b/tests/lib/services.js @@ -0,0 +1,58 @@ +/** + * @fileoverview Tests for TypeScript-specific constructs + * @author Benjamin Lichtman + * @copyright jQuery Foundation and other contributors, https://jquery.org/ + * MIT License + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const path = require("path"), + shelljs = require("shelljs"), + testUtils = require("../../tools/test-utils"); + +//------------------------------------------------------------------------------ +// Setup +//------------------------------------------------------------------------------ + +const FIXTURES_DIR = "./tests/fixtures/services"; + +const testFiles = shelljs.find(FIXTURES_DIR) + .filter(filename => filename.indexOf(".src.ts") > -1) + // strip off ".src.ts" + .map(filename => filename.substring(FIXTURES_DIR.length - 1, filename.length - 7)); + +/** + * @param {string} filename Full path to file being tested + * @returns {Object} Config object + */ +function createConfig(filename) { + return { + filePath: filename, + generateServices: true, + project: "./tsconfig.json", + tsconfigRootDir: path.resolve(FIXTURES_DIR) + }; +} + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +describe("services", () => { + + testFiles.forEach(filename => { + const fullFileName = `${path.resolve(FIXTURES_DIR, filename)}.src.ts`; + const code = shelljs.cat(fullFileName); + const config = createConfig(fullFileName); + test(`fixtures/${filename}.src`, testUtils.createSnapshotTestBlock(code, config)); + test(`fixtures/${filename}.src services`, () => { + testUtils.testServices(code, config); + }); + }); + +}); diff --git a/tools/test-utils.js b/tools/test-utils.js index f9d2e94..deb4e79 100644 --- a/tools/test-utils.js +++ b/tools/test-utils.js @@ -20,6 +20,16 @@ const parser = require("../parser"); // Private //-------------------------------------------------------------------------------- +const defaultConfig = { + loc: true, + range: true, + raw: true, + tokens: true, + comment: true, + errorOnUnknownASTType: true, + sourceType: "module" +}; + /** * Returns a raw copy of the given AST * @param {Object} ast the AST object @@ -42,15 +52,6 @@ function getRaw(ast) { * @returns {Function} callback for Jest test() block */ function createSnapshotTestBlock(code, config = {}) { - const defaultConfig = { - loc: true, - range: true, - raw: true, - tokens: true, - comment: true, - errorOnUnknownASTType: true, - sourceType: "module" - }; config = Object.assign({}, defaultConfig, config); /** @@ -79,7 +80,23 @@ function createSnapshotTestBlock(code, config = {}) { } +/** + * @param {string} code The code being parsed + * @param {Object} config The configuration object for the parser + * @returns {void} + */ +function testServices(code, config = {}) { + config = Object.assign({}, defaultConfig, config); + + const services = parser.parseForESLint(code, config).services; + expect(services).toBeDefined(); + expect(services.program).toBeDefined(); + expect(services.esTreeNodeToTSNodeMap).toBeDefined(); + expect(services.tsNodeToESTreeNodeMap).toBeDefined(); +} + module.exports = { getRaw, - createSnapshotTestBlock + createSnapshotTestBlock, + testServices };