Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/eslint-plugin-import
Path: blob/main/src/rules/first.js
829 views
1
import docsUrl from '../docsUrl';
2
3
function getImportValue(node) {
4
return node.type === 'ImportDeclaration'
5
? node.source.value
6
: node.moduleReference.expression.value;
7
}
8
9
module.exports = {
10
meta: {
11
type: 'suggestion',
12
docs: {
13
url: docsUrl('first'),
14
},
15
fixable: 'code',
16
schema: [
17
{
18
type: 'string',
19
enum: ['absolute-first', 'disable-absolute-first'],
20
},
21
],
22
},
23
24
create(context) {
25
function isPossibleDirective(node) {
26
return node.type === 'ExpressionStatement' &&
27
node.expression.type === 'Literal' &&
28
typeof node.expression.value === 'string';
29
}
30
31
return {
32
'Program': function (n) {
33
const body = n.body;
34
if (!body) {
35
return;
36
}
37
const absoluteFirst = context.options[0] === 'absolute-first';
38
const message = 'Import in body of module; reorder to top.';
39
const sourceCode = context.getSourceCode();
40
const originSourceCode = sourceCode.getText();
41
let nonImportCount = 0;
42
let anyExpressions = false;
43
let anyRelative = false;
44
let lastLegalImp = null;
45
const errorInfos = [];
46
let shouldSort = true;
47
let lastSortNodesIndex = 0;
48
body.forEach(function (node, index) {
49
if (!anyExpressions && isPossibleDirective(node)) {
50
return;
51
}
52
53
anyExpressions = true;
54
55
if (node.type === 'ImportDeclaration' || node.type === 'TSImportEqualsDeclaration') {
56
if (absoluteFirst) {
57
if (/^\./.test(getImportValue(node))) {
58
anyRelative = true;
59
} else if (anyRelative) {
60
context.report({
61
node: node.type === 'ImportDeclaration' ? node.source : node.moduleReference,
62
message: 'Absolute imports should come before relative imports.',
63
});
64
}
65
}
66
if (nonImportCount > 0) {
67
for (const variable of context.getDeclaredVariables(node)) {
68
if (!shouldSort) break;
69
const references = variable.references;
70
if (references.length) {
71
for (const reference of references) {
72
if (reference.identifier.range[0] < node.range[1]) {
73
shouldSort = false;
74
break;
75
}
76
}
77
}
78
}
79
shouldSort && (lastSortNodesIndex = errorInfos.length);
80
errorInfos.push({
81
node,
82
range: [body[index - 1].range[1], node.range[1]],
83
});
84
} else {
85
lastLegalImp = node;
86
}
87
} else {
88
nonImportCount++;
89
}
90
});
91
if (!errorInfos.length) return;
92
errorInfos.forEach(function (errorInfo, index) {
93
const node = errorInfo.node;
94
const infos = {
95
node,
96
message,
97
};
98
if (index < lastSortNodesIndex) {
99
infos.fix = function (fixer) {
100
return fixer.insertTextAfter(node, '');
101
};
102
} else if (index === lastSortNodesIndex) {
103
const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1);
104
infos.fix = function (fixer) {
105
const removeFixers = sortNodes.map(function (_errorInfo) {
106
return fixer.removeRange(_errorInfo.range);
107
});
108
const range = [0, removeFixers[removeFixers.length - 1].range[1]];
109
let insertSourceCode = sortNodes.map(function (_errorInfo) {
110
const nodeSourceCode = String.prototype.slice.apply(
111
originSourceCode, _errorInfo.range,
112
);
113
if (/\S/.test(nodeSourceCode[0])) {
114
return '\n' + nodeSourceCode;
115
}
116
return nodeSourceCode;
117
}).join('');
118
let insertFixer = null;
119
let replaceSourceCode = '';
120
if (!lastLegalImp) {
121
insertSourceCode =
122
insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
123
}
124
insertFixer = lastLegalImp ?
125
fixer.insertTextAfter(lastLegalImp, insertSourceCode) :
126
fixer.insertTextBefore(body[0], insertSourceCode);
127
const fixers = [insertFixer].concat(removeFixers);
128
fixers.forEach(function (computedFixer, i) {
129
replaceSourceCode += (originSourceCode.slice(
130
fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0],
131
) + computedFixer.text);
132
});
133
return fixer.replaceTextRange(range, replaceSourceCode);
134
};
135
}
136
context.report(infos);
137
});
138
},
139
};
140
},
141
};
142
143