Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"resolvers/*/test",
"scripts",
"memo-parser",
"lib"
"lib",
"examples"
]
}
1 change: 1 addition & 0 deletions examples/flat/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default [
'import/no-dynamic-require': 'warn',
'import/no-nodejs-modules': 'warn',
'import/no-unused-modules': ['warn', { unusedExports: true }],
'import/no-cycle': 'warn',
},
},
];
3 changes: 3 additions & 0 deletions examples/flat/src/depth-zero.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { foo } from "./es6/depth-one-dynamic";

foo();
3 changes: 3 additions & 0 deletions examples/flat/src/es6/depth-one-dynamic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function foo() {}

export const bar = () => import("../depth-zero").then(({foo}) => foo);
1 change: 1 addition & 0 deletions examples/legacy/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ module.exports = {
'import/no-dynamic-require': 'warn',
'import/no-nodejs-modules': 'warn',
'import/no-unused-modules': ['warn', { unusedExports: true }],
'import/no-cycle': 'warn',
},
};
3 changes: 3 additions & 0 deletions examples/legacy/src/depth-zero.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { foo } from "./es6/depth-one-dynamic";

foo();
3 changes: 3 additions & 0 deletions examples/legacy/src/es6/depth-one-dynamic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function foo() {}

export const bar = () => import("../depth-zero").then(({ foo }) => foo);
14 changes: 14 additions & 0 deletions tests/src/core/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,18 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
parseStubParser.parse = parseSpy;
expect(parse.bind(null, path, content, { settings: {}, parserPath: 'espree', languageOptions: { parserOptions: { sourceType: 'module', ecmaVersion: 2015, ecmaFeatures: { jsx: true } } }, parserOptions: { sourceType: 'script' } })).not.to.throw(Error);
});

it('passes ecmaVersion and sourceType from languageOptions to parser', () => {
const parseSpy = sinon.spy();
const languageOptions = { ecmaVersion: 'latest', sourceType: 'module', parserOptions: { ecmaFeatures: { jsx: true } } };
parseStubParser.parse = parseSpy;
parse(path, content, { settings: {}, parserPath: parseStubParserPath, languageOptions });
expect(parseSpy.args[0][1], 'custom parser to clone the parserOptions object').to.not.equal(languageOptions);
expect(parseSpy.args[0][1], 'custom parser to get ecmaFeatures in parserOptions which is a clone of ecmaFeatures passed in')
.to.have.property('ecmaFeatures')
.that.is.eql(languageOptions.parserOptions.ecmaFeatures)
.and.is.not.equal(languageOptions.parserOptions.ecmaFeatures);
expect(parseSpy.args[0][1], 'custom parser to get ecmaVersion in parserOptions from languageOptions').to.have.property('ecmaVersion', languageOptions.ecmaVersion);
expect(parseSpy.args[0][1], 'custom parser to get sourceType in parserOptions from languageOptions').to.have.property('sourceType', languageOptions.sourceType);
});
});
3 changes: 3 additions & 0 deletions utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange

### Fixed
- `parse`: remove unneeded extra backticks ([#3057], thanks [@G-Rath])
- `parse`: espree parser isn't working with flat config ([#3061], thanks [@michaelfaith])
- `parse`: add `ecmaVersion` and `sourceType` to `parserOptions` ([#3061], thanks [@michaelfaith])

## v2.11.0 - 2024-09-05

Expand Down Expand Up @@ -168,6 +170,7 @@ Yanked due to critical issue with cache key resulting from #839.
### Fixed
- `unambiguous.test()` regex is now properly in multiline mode

[#3061]: https://github.com/import-js/eslint-plugin-import/pull/3061
[#3057]: https://github.com/import-js/eslint-plugin-import/pull/3057
[#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
[#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
Expand Down
26 changes: 22 additions & 4 deletions utils/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
if (parsedResult && parsedResult.visitorKeys) {
return parsedResult.visitorKeys;
}
if (typeof parserPath === 'string' && (/.*espree.*/).test(parserPath)) {
return parserInstance.VisitorKeys;
}
// The old babel parser doesn't have a `parseForESLint` eslint function, so we don't end
// up with a `parsedResult` here. It also doesn't expose the visitor keys on the parser itself,
// so we have to try and infer the visitor-keys module from the parserPath.
// This is NOT supported in flat config!
if (typeof parserPath === 'string' && (/.*babel-eslint.*/).test(parserPath)) {
return getBabelEslintVisitorKeys(parserPath);
}
// The espree parser doesn't have the `parseForESLint` function, so we don't end up with a
// `parsedResult` here, but it does expose the visitor keys on the parser instance that we can use.
if (parserInstance && parserInstance.VisitorKeys) {
return parserInstance.VisitorKeys;
}
return null;
}

Expand Down Expand Up @@ -107,7 +113,8 @@ exports.default = function parse(path, content, context) {
if (context == null) { throw new Error('need context to parse properly'); }

// ESLint in "flat" mode only sets context.languageOptions.parserOptions
let parserOptions = context.languageOptions && context.languageOptions.parserOptions || context.parserOptions;
const languageOptions = context.languageOptions;
let parserOptions = languageOptions && languageOptions.parserOptions || context.parserOptions;
const parserOrPath = getParser(path, context);

if (!parserOrPath) { throw new Error('parserPath or languageOptions.parser is required!'); }
Expand Down Expand Up @@ -138,6 +145,17 @@ exports.default = function parse(path, content, context) {
delete parserOptions.project;
delete parserOptions.projects;

// If this is a flat config, we need to add ecmaVersion and sourceType (if present) from languageOptions
if (languageOptions && languageOptions.ecmaVersion) {
parserOptions.ecmaVersion = languageOptions.ecmaVersion;
}
if (languageOptions && languageOptions.sourceType) {
// @ts-expect-error languageOptions is from the flatConfig Linter type in 8.57 while parserOptions is not.
// Non-flat config parserOptions.sourceType doesn't have "commonjs" in the type. Once upgraded to v9 types,
// they'll be the same and this expect-error should be removed.
parserOptions.sourceType = languageOptions.sourceType;
}

// require the parser relative to the main module (i.e., ESLint)
const parser = typeof parserOrPath === 'string' ? moduleRequire(parserOrPath) : parserOrPath;

Expand Down