Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/eslint-plugin-import
Path: blob/main/src/rules/no-named-as-default-member.js
829 views
1
/**
2
* @fileoverview Rule to warn about potentially confused use of name exports
3
* @author Desmond Brand
4
* @copyright 2016 Desmond Brand. All rights reserved.
5
* See LICENSE in root directory for full license.
6
*/
7
import Exports from '../ExportMap';
8
import importDeclaration from '../importDeclaration';
9
import docsUrl from '../docsUrl';
10
11
//------------------------------------------------------------------------------
12
// Rule Definition
13
//------------------------------------------------------------------------------
14
15
module.exports = {
16
meta: {
17
type: 'suggestion',
18
docs: {
19
url: docsUrl('no-named-as-default-member'),
20
},
21
schema: [],
22
},
23
24
create(context) {
25
26
const fileImports = new Map();
27
const allPropertyLookups = new Map();
28
29
function handleImportDefault(node) {
30
const declaration = importDeclaration(context);
31
const exportMap = Exports.get(declaration.source.value, context);
32
if (exportMap == null) return;
33
34
if (exportMap.errors.length) {
35
exportMap.reportErrors(context, declaration);
36
return;
37
}
38
39
fileImports.set(node.local.name, {
40
exportMap,
41
sourcePath: declaration.source.value,
42
});
43
}
44
45
function storePropertyLookup(objectName, propName, node) {
46
const lookups = allPropertyLookups.get(objectName) || [];
47
lookups.push({ node, propName });
48
allPropertyLookups.set(objectName, lookups);
49
}
50
51
function handlePropLookup(node) {
52
const objectName = node.object.name;
53
const propName = node.property.name;
54
storePropertyLookup(objectName, propName, node);
55
}
56
57
function handleDestructuringAssignment(node) {
58
const isDestructure = (
59
node.id.type === 'ObjectPattern' &&
60
node.init != null &&
61
node.init.type === 'Identifier'
62
);
63
if (!isDestructure) return;
64
65
const objectName = node.init.name;
66
for (const { key } of node.id.properties) {
67
if (key == null) continue; // true for rest properties
68
storePropertyLookup(objectName, key.name, key);
69
}
70
}
71
72
function handleProgramExit() {
73
allPropertyLookups.forEach((lookups, objectName) => {
74
const fileImport = fileImports.get(objectName);
75
if (fileImport == null) return;
76
77
for (const { propName, node } of lookups) {
78
// the default import can have a "default" property
79
if (propName === 'default') continue;
80
if (!fileImport.exportMap.namespace.has(propName)) continue;
81
82
context.report({
83
node,
84
message: (
85
`Caution: \`${objectName}\` also has a named export ` +
86
`\`${propName}\`. Check if you meant to write ` +
87
`\`import {${propName}} from '${fileImport.sourcePath}'\` ` +
88
'instead.'
89
),
90
});
91
}
92
});
93
}
94
95
return {
96
'ImportDefaultSpecifier': handleImportDefault,
97
'MemberExpression': handlePropLookup,
98
'VariableDeclarator': handleDestructuringAssignment,
99
'Program:exit': handleProgramExit,
100
};
101
},
102
};
103
104