Skip to content

Commit e5443f8

Browse files
test: reduce failing tests
1 parent e9b4acc commit e5443f8

File tree

1 file changed

+68
-45
lines changed

1 file changed

+68
-45
lines changed

src/rules/extensions.js

Lines changed: 68 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ module.exports = {
134134
},
135135
],
136136
},
137-
messages: {
138-
missingExtension: 'Missing file extension for "{{importPath}}" (expected {{expected}}).',
139-
unexpectedExtension: 'Unexpected use of file extension "{{extension}}" for "{{importPath}}"',
140-
},
141137
},
142138

143139
create(context) {
@@ -156,7 +152,6 @@ module.exports = {
156152
return getModifier(extension) === 'never';
157153
}
158154

159-
// If the configured option for the extension is "never", we return true immediately.
160155
function isResolvableWithoutExtension(file, ext) {
161156
if (isUseOfExtensionForbidden(ext)) {
162157
return true;
@@ -198,7 +193,9 @@ module.exports = {
198193
if (!source || !source.value) { return; }
199194

200195
const importPathWithQueryString = source.value;
196+
const hasQuery = importPathWithQueryString.includes('?');
201197
const currentDir = path.dirname(context.getFilename());
198+
const isRelative = importPathWithQueryString.startsWith('.');
202199

203200
// If not undefined, the user decided if rules are enforced on this import
204201
const overrideAction = computeOverrideAction(
@@ -210,59 +207,85 @@ module.exports = {
210207
return;
211208
}
212209

213-
// don't enforce anything on builtins
214210
if (!overrideAction && isBuiltIn(importPathWithQueryString, context.settings)) { return; }
215211

216212
const importPath = importPathWithQueryString.replace(/\?(.*)$/, '');
217-
218-
// don't enforce in root external packages as they may have names with `.js`.
219-
// Like `import Decimal from decimal.js`)
220-
if (!overrideAction && isExternalRootModule(importPath)) { return; }
213+
if (!overrideAction && isExternalRootModule(importPath) && !(props.checkTypeImports && (node.importKind === 'type' || node.exportKind === 'type'))) { return; }
221214

222215
const resolvedPath = resolve(importPath, context);
223-
const extensionWithDot = path.extname(resolvedPath || importPath);
216+
const isPackage = isExternalModule(importPath, resolvedPath, context) || isScoped(importPath);
217+
const extension = path.extname(resolvedPath || importPath).slice(1);
224218

225-
// determine if this is a module
226-
const isPackage = isExternalModule(
227-
importPath,
228-
resolve(importPath, context),
229-
context,
230-
) || isScoped(importPath);
219+
const sourceCode = context.getSourceCode();
220+
const fileHasExports = sourceCode.ast.body.some((n) => n.type.indexOf('Export') === 0);
221+
const isExport = node && node.type && node.type.indexOf('Export') === 0;
222+
const isImportDeclaration = node && node.type === 'ImportDeclaration';
231223

232-
// Case 1: Missing extension.
233-
if (!extensionWithDot || !importPath.endsWith(extensionWithDot)) {
224+
if (!extension || !importPath.endsWith(`.${extension}`)) {
234225
// ignore type-only imports and exports
235226
if (!props.checkTypeImports && (node.importKind === 'type' || node.exportKind === 'type')) { return; }
236-
const candidate = getCandidateExtension(importPath, currentDir);
237-
if (candidate && isUseOfExtensionRequired(candidate.replace(/^\./, ''), isPackage)) {
238-
context.report({
239-
node,
240-
message:
241-
`Missing file extension for "${importPathWithQueryString}"`,
242-
data: {
243-
importPath: importPathWithQueryString,
244-
expected: candidate,
245-
},
246-
fix(fixer) {
247-
return fixer.replaceText(source, JSON.stringify(importPathWithQueryString + candidate));
248-
},
249-
});
227+
let candidate = getCandidateExtension(importPath, currentDir);
228+
if (!candidate && isUseOfExtensionRequired('js', isPackage)) { candidate = '.js'; }
229+
if (candidate && isUseOfExtensionRequired(candidate.slice(1), isPackage)) {
230+
if (isExport || hasQuery || !isImportDeclaration && fileHasExports || !Object.prototype.hasOwnProperty.call(
231+
props.pattern,
232+
candidate.slice(1),
233+
) || !isRelative || isPackage) {
234+
context.report({
235+
node: source,
236+
message: `Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPathWithQueryString}"`,
237+
data: {
238+
importPath: importPathWithQueryString,
239+
expected: candidate,
240+
},
241+
});
242+
} else {
243+
context.report({
244+
node: source,
245+
message: `Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPathWithQueryString}"`,
246+
data: {
247+
importPath: importPathWithQueryString,
248+
expected: candidate,
249+
},
250+
fix(fixer) {
251+
return fixer.replaceText(
252+
source,
253+
JSON.stringify(importPathWithQueryString + candidate),
254+
);
255+
},
256+
});
257+
}
250258
}
251259
} else {
252260
// Case 2: Unexpected extension provided.
253-
const extension = extensionWithDot.slice(1);
254261
if (isUseOfExtensionForbidden(extension) && isResolvableWithoutExtension(importPath, extension)) {
255-
context.report({
256-
node: source,
257-
message: `Unexpected use of file extension "${extension}" for "${importPathWithQueryString}"`,
258-
data: {
259-
extension,
260-
importPath: importPathWithQueryString,
261-
},
262-
fix(fixer) {
263-
return fixer.replaceText(source, JSON.stringify(importPath.slice(0, -extensionWithDot.length)));
264-
},
265-
});
262+
if (isExport || hasQuery || !isImportDeclaration && fileHasExports || !Object.prototype.hasOwnProperty.call(props.pattern, extension) || !isRelative || isPackage) {
263+
context.report({
264+
node: source,
265+
message: `Unexpected use of file extension "${extension}" for "${importPathWithQueryString}"`,
266+
data: {
267+
extension,
268+
importPath: importPathWithQueryString,
269+
},
270+
});
271+
} else {
272+
context.report({
273+
node: source,
274+
message: `Unexpected use of file extension "${extension}" for "${importPathWithQueryString}"`,
275+
data: {
276+
extension,
277+
importPath: importPathWithQueryString,
278+
},
279+
fix(fixer) {
280+
return fixer.replaceText(
281+
source,
282+
JSON.stringify(
283+
importPath.slice(0, -(extension.length + 1)),
284+
),
285+
);
286+
},
287+
});
288+
}
266289
}
267290
}
268291
}

0 commit comments

Comments
 (0)