ember-eslint-parser 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/parser/transforms.js +60 -25
package/package.json
CHANGED
package/src/parser/transforms.js
CHANGED
|
@@ -6,6 +6,31 @@ const TypescriptScope = require('@typescript-eslint/scope-manager');
|
|
|
6
6
|
const { Reference, Scope, Variable, Definition } = require('eslint-scope');
|
|
7
7
|
const htmlTags = require('html-tags');
|
|
8
8
|
|
|
9
|
+
const BufferMap = new Map();
|
|
10
|
+
|
|
11
|
+
function getBuffer(str) {
|
|
12
|
+
let buf = BufferMap.get(str);
|
|
13
|
+
if (!buf) {
|
|
14
|
+
buf = Buffer.from(str);
|
|
15
|
+
BufferMap.set(str, buf);
|
|
16
|
+
}
|
|
17
|
+
return buf;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function sliceByteRange(str, a, b) {
|
|
21
|
+
const buf = getBuffer(str);
|
|
22
|
+
return buf.slice(a, b).toString();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function byteToCharIndex(str, byteOffset) {
|
|
26
|
+
const buf = getBuffer(str);
|
|
27
|
+
return buf.slice(0, byteOffset + 1).toString().length - 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function byteLength(str) {
|
|
31
|
+
return getBuffer(str).length;
|
|
32
|
+
}
|
|
33
|
+
|
|
9
34
|
/**
|
|
10
35
|
* finds the nearest node scope
|
|
11
36
|
* @param scopeManager
|
|
@@ -202,17 +227,23 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
202
227
|
const templateInfos = info.templateInfos.map((r) => ({
|
|
203
228
|
range: [r.contentRange.start, r.contentRange.end],
|
|
204
229
|
templateRange: [r.range.start, r.range.end],
|
|
230
|
+
utf16Range: [byteToCharIndex(code, r.range.start), byteToCharIndex(code, r.range.end)],
|
|
205
231
|
}));
|
|
206
232
|
const templateVisitorKeys = {};
|
|
207
233
|
const codeLines = new DocumentLines(code);
|
|
208
234
|
const comments = [];
|
|
209
|
-
const textNodes = [];
|
|
210
235
|
for (const tpl of templateInfos) {
|
|
236
|
+
const currentComments = [];
|
|
237
|
+
const textNodes = [];
|
|
211
238
|
const range = tpl.range;
|
|
212
|
-
const template = code
|
|
239
|
+
const template = sliceByteRange(code, ...range);
|
|
213
240
|
const docLines = new DocumentLines(template);
|
|
214
241
|
const ast = glimmer.preprocess(template, { mode: 'codemod' });
|
|
215
|
-
ast.tokens = tokenize(
|
|
242
|
+
ast.tokens = tokenize(
|
|
243
|
+
sliceByteRange(code, ...tpl.templateRange),
|
|
244
|
+
codeLines,
|
|
245
|
+
tpl.templateRange[0]
|
|
246
|
+
);
|
|
216
247
|
const allNodes = [];
|
|
217
248
|
glimmer.traverse(ast, {
|
|
218
249
|
All(node, path) {
|
|
@@ -221,6 +252,7 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
221
252
|
allNodes.push(node);
|
|
222
253
|
if (node.type === 'CommentStatement' || node.type === 'MustacheCommentStatement') {
|
|
223
254
|
comments.push(node);
|
|
255
|
+
currentComments.push(node);
|
|
224
256
|
}
|
|
225
257
|
if (node.type === 'TextNode') {
|
|
226
258
|
n.value = node.chars;
|
|
@@ -265,17 +297,12 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
265
297
|
n.name = n.tag;
|
|
266
298
|
n.parts = [];
|
|
267
299
|
let start = n.range[0];
|
|
268
|
-
let codeSlice = code
|
|
300
|
+
let codeSlice = sliceByteRange(code, ...n.range);
|
|
269
301
|
for (const part of n.tag.split('.')) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
pattern = `${part}\\b`;
|
|
273
|
-
}
|
|
274
|
-
const regex = new RegExp(pattern);
|
|
275
|
-
const match = codeSlice.match(regex);
|
|
276
|
-
const range = [start + match.index, 0];
|
|
302
|
+
const idx = codeSlice.indexOf(part);
|
|
303
|
+
const range = [start + idx, 0];
|
|
277
304
|
range[1] = range[0] + part.length;
|
|
278
|
-
codeSlice = code
|
|
305
|
+
codeSlice = sliceByteRange(code, range[1], n.range[1]);
|
|
279
306
|
start = range[1];
|
|
280
307
|
n.parts.push({
|
|
281
308
|
type: 'GlimmerElementNodePart',
|
|
@@ -295,8 +322,11 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
295
322
|
n.params = [];
|
|
296
323
|
}
|
|
297
324
|
if ('blockParams' in n && n.parent) {
|
|
298
|
-
|
|
299
|
-
|
|
325
|
+
// for blocks {{x as |b|}} the block range does not contain the block params...
|
|
326
|
+
// for element tag it does <x as b />
|
|
327
|
+
const blockRange = n.type === 'Block' ? n.parent.range : n.range;
|
|
328
|
+
let part = sliceByteRange(code, ...blockRange);
|
|
329
|
+
let start = blockRange[0];
|
|
300
330
|
let idx = part.indexOf('|') + 1;
|
|
301
331
|
start += idx;
|
|
302
332
|
part = part.slice(idx, -1);
|
|
@@ -323,10 +353,12 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
323
353
|
allNodeTypes.add(n.type);
|
|
324
354
|
}
|
|
325
355
|
// ast should not contain comment nodes
|
|
326
|
-
for (const comment of
|
|
356
|
+
for (const comment of currentComments) {
|
|
327
357
|
const parentBody = comment.parent.body || comment.parent.children;
|
|
328
358
|
const idx = parentBody.indexOf(comment);
|
|
329
|
-
|
|
359
|
+
if (idx >= 0) {
|
|
360
|
+
parentBody.splice(idx, 1);
|
|
361
|
+
}
|
|
330
362
|
// comment type can be a block comment or a line comment
|
|
331
363
|
// mark comments as always block comment, this works for eslint in all cases
|
|
332
364
|
comment.type = 'Block';
|
|
@@ -400,8 +432,8 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
400
432
|
|
|
401
433
|
const template = templateInfos.find(
|
|
402
434
|
(t) =>
|
|
403
|
-
t.
|
|
404
|
-
(t.
|
|
435
|
+
t.utf16Range[0] === range[0] &&
|
|
436
|
+
(t.utf16Range[1] === range[1] || t.utf16Range[1] === range[1] + 1)
|
|
405
437
|
);
|
|
406
438
|
if (!template) {
|
|
407
439
|
return null;
|
|
@@ -437,7 +469,9 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
437
469
|
* it's NOT a standard html tag, it should have a referenced variable
|
|
438
470
|
*/
|
|
439
471
|
if (
|
|
472
|
+
n.name !== 'this' &&
|
|
440
473
|
!n.name.startsWith(':') &&
|
|
474
|
+
!n.name.startsWith('@') &&
|
|
441
475
|
scope &&
|
|
442
476
|
(variable ||
|
|
443
477
|
isUpperCase(n.name[0]) ||
|
|
@@ -470,7 +504,7 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
470
504
|
};
|
|
471
505
|
|
|
472
506
|
const replaceRange = function replaceRange(s, start, end, substitute) {
|
|
473
|
-
return s
|
|
507
|
+
return sliceByteRange(s, 0, start) + substitute + sliceByteRange(s, end);
|
|
474
508
|
};
|
|
475
509
|
module.exports.replaceRange = replaceRange;
|
|
476
510
|
|
|
@@ -504,20 +538,21 @@ module.exports.transformForLint = function transformForLint(code) {
|
|
|
504
538
|
*/
|
|
505
539
|
const result = processor.parse(code);
|
|
506
540
|
for (const tplInfo of result.reverse()) {
|
|
507
|
-
const
|
|
508
|
-
(prev, curr) => prev + (
|
|
541
|
+
const backticks = [...tplInfo.contents].reduce(
|
|
542
|
+
(prev, curr) => (prev + (curr.codePointAt(0) === '`') ? 1 : 0),
|
|
509
543
|
0
|
|
510
544
|
);
|
|
545
|
+
const content = tplInfo.contents.replace(/`/g, '\\`');
|
|
511
546
|
if (tplInfo.type === 'class-member') {
|
|
512
547
|
const tplLength = tplInfo.range.end - tplInfo.range.start;
|
|
513
|
-
const spaces = tplLength - 'static{`'.length - '`}'.length -
|
|
514
|
-
const total =
|
|
548
|
+
const spaces = tplLength - byteLength(content) - 'static{`'.length - '`}'.length - backticks;
|
|
549
|
+
const total = content + ' '.repeat(spaces);
|
|
515
550
|
const replacementCode = `static{\`${total}\`}`;
|
|
516
551
|
jsCode = replaceRange(jsCode, tplInfo.range.start, tplInfo.range.end, replacementCode);
|
|
517
552
|
} else {
|
|
518
553
|
const tplLength = tplInfo.range.end - tplInfo.range.start;
|
|
519
|
-
const spaces = tplLength - '""`'.length - '`'.length -
|
|
520
|
-
const total =
|
|
554
|
+
const spaces = tplLength - byteLength(content) - '""`'.length - '`'.length - backticks;
|
|
555
|
+
const total = content + ' '.repeat(spaces);
|
|
521
556
|
const replacementCode = `""\`${total}\``;
|
|
522
557
|
jsCode = replaceRange(jsCode, tplInfo.range.start, tplInfo.range.end, replacementCode);
|
|
523
558
|
}
|