Skip to content

Commit 81f775e

Browse files
committed
feature: @putout/compare: add plain compare
1 parent d81a9d0 commit 81f775e

File tree

6 files changed

+102
-16
lines changed

6 files changed

+102
-16
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
const {types} = require('@putout/babel');
4+
const {isObject, isArrays} = require('../is');
5+
const {comparePrimitives} = require('./compare-primitives');
6+
7+
const {isIdentifier} = types;
8+
9+
module.exports.comparePlain = (node, template, {add}) => {
10+
if (!node && node === template)
11+
return true;
12+
13+
if (!node)
14+
return false;
15+
16+
if (comparePrimitives(node, template))
17+
return true;
18+
19+
if (isIdentifier(node) && node.name === template.name)
20+
return true;
21+
22+
if (isObject(template) && !Array.isArray(template))
23+
return add(node, template, {
24+
plain: true,
25+
});
26+
27+
if (isArrays(node, template))
28+
return add(node, template, {
29+
plain: true,
30+
});
31+
32+
return false;
33+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
const {is} = require('../is');
4+
5+
const isPrimitive = (a) => typeof a !== 'object' || a === null;
6+
7+
module.exports.comparePrimitives = (node, template) => {
8+
return isPrimitive(template) && !is(template) && template === node;
9+
};

packages/compare/lib/compare.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const {
99
getTemplateValues,
1010
} = require('./vars');
1111

12-
const {runComparators} = require('./comparators');
12+
const {runComparators} = require('./run-comparators');
1313
const {runTopLevelComparators} = require('./top-level-comparators');
1414

1515
const {
@@ -21,14 +21,15 @@ const {
2121
} = require('./is');
2222

2323
const {extractExpression} = template;
24+
const addWaterMark = (a) => a;
2425

2526
const {keys} = Object;
2627
const {isArray} = Array;
2728
const noop = () => {};
2829
const isEmptyArray = (a) => isArray(a) && !a.length;
2930

3031
const compareType = (type) => (path) => path.type === type;
31-
const superPush = (array) => (a, b) => array.push([a, b]);
32+
const superPush = (array) => (a, b, c = {}) => array.push([a, b, c]);
3233
const maybeArray = (a) => isArray(a) ? a : [a];
3334

3435
const findParent = (path, type) => {
@@ -71,7 +72,7 @@ function compare(path, template, options = {}, equal = noop) {
7172
if (!template)
7273
return false;
7374

74-
const node = extractExpression(parseNode(path));
75+
const node = addWaterMark(extractExpression(parseNode(path)));
7576
const templateNode = extractExpression(parseNode(template));
7677

7778
equal(node, templateNode);
@@ -114,7 +115,8 @@ module.exports.compareAll = (path, templateNodes, options) => {
114115
return true;
115116
};
116117

117-
// @babel/template creates empty array directives// extra duplicate value
118+
// @babel/template creates empty array directives
119+
// extra duplicate value
118120
const ignore = [
119121
'loc',
120122
'start',
@@ -141,7 +143,7 @@ function superCompareIterate(node, template) {
141143
const add = superPush(array);
142144

143145
while (item = array.pop()) {
144-
const [node, template] = item;
146+
const [node, template, {plain} = {}] = item;
145147

146148
if (!node || isEmptyArray(node) && !isEmptyArray(template))
147149
return false;
@@ -156,6 +158,7 @@ function superCompareIterate(node, template) {
156158
const is = runComparators(nodeValue, value, {
157159
add,
158160
templateStore,
161+
plain,
159162
});
160163

161164
if (!is)

packages/compare/lib/link.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ module.exports = ({add, value, nodeValue, templateStore}) => {
4040
if (isIdentifier(templateStore[name]) && isTSTypeReference(nodeValue))
4141
return true;
4242

43-
add(templateStore[name], nodeValue);
43+
add(templateStore[name], nodeValue, {
44+
plain: true,
45+
});
4446

4547
return true;
4648
};
Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use strict';
22

3+
const {types} = require('@putout/babel');
4+
35
const log = require('./log');
46
const link = require('./link');
57

68
const {
7-
is,
89
isId,
910
isBool,
1011
isObject,
@@ -29,7 +30,9 @@ const {
2930
isLinkedRegExp,
3031
} = require('./is');
3132

32-
const {types} = require('@putout/babel');
33+
const {comparePlain} = require('./comparators/compare-plain');
34+
const {comparePrimitives} = require('./comparators/compare-primitives');
35+
3336
const {
3437
isClassBody,
3538
isBlock,
@@ -38,15 +41,14 @@ const {
3841
} = types;
3942

4043
const isEmptyBlock = (a) => isBlock(a) && !a.body.length;
41-
const isPrimitive = (a) => typeof a !== 'object' || a === null;
4244

4345
const second = (f) => (a, b) => f(b);
4446

4547
const comparators = [
48+
comparePrimitives,
4649
compareTemplateElements,
4750
compareJSXTexts,
4851
compareAny,
49-
comparePrimitives,
5052
second(isClassBody),
5153
second(isEmptyBlock),
5254
second(isAny),
@@ -70,12 +72,17 @@ const comparators = [
7072
compareArrays,
7173
];
7274

73-
module.exports.runComparators = (node, template, {add, templateStore}) => {
75+
module.exports.runComparators = (node, template, {add, templateStore, plain}) => {
7476
let i = -1;
7577
const n = comparators.length;
7678

7779
log(template, node);
7880

81+
if (plain)
82+
return comparePlain(node, template, {
83+
add,
84+
});
85+
7986
while (++i < n) {
8087
const compare = comparators[i];
8188

@@ -90,10 +97,6 @@ function compareAny(node, template) {
9097
return template === '__';
9198
}
9299

93-
function comparePrimitives(node, template) {
94-
return isPrimitive(template) && !is(template) && template === node;
95-
}
96-
97100
function compareArrays(node, template, {add}) {
98101
const is = isArrays(node, template);
99102

@@ -115,7 +118,7 @@ function compareTemplateElements(node, template) {
115118
}
116119

117120
function linkNodes(node, template, {add, templateStore}) {
118-
if (node && isLinkedNode(template, node) || isLinkedArgs(template) || isLinkedId(node, template) || isLinkedBool(node, template))
121+
if (node && isLinkedNode(template) || isLinkedArgs(template) || isLinkedId(node, template) || isLinkedBool(node, template))
119122
return link({
120123
add,
121124
value: template,

packages/compare/test/compare.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ test('compare: typescript: arrow function type: no args', (t) => {
943943
test('compare: __args__a', (t) => {
944944
const node = '((a) => fn(42))(value)';
945945
const template = '((__args__a) => __c(__args__a))(__args__b)';
946+
946947
const result = compare(node, template);
947948

948949
t.notOk(result);
@@ -1007,6 +1008,41 @@ test('compare: TSMappedType', (t) => {
10071008
t.end();
10081009
});
10091010

1011+
test('compare: different template values', (t) => {
1012+
const result = compare('__b.body.length === 1 && __c.body.length === 1', '__a && __a');
1013+
1014+
t.notOk(result);
1015+
t.end();
1016+
});
1017+
1018+
test('compare: different template values: literals', (t) => {
1019+
const result = compare(`isNameStr('__a') && isNameStr('__b')`, '__a && __a');
1020+
1021+
t.notOk(result);
1022+
t.end();
1023+
});
1024+
1025+
test('compareAny: node is null', (t) => {
1026+
const result = compareAny('a => isIdentifier(a, {\n name: BODY\n})', ['(__args__a) => __a.__b(__args__a)', '(__args__a) => {__a.__b(__args__a)}']);
1027+
1028+
t.notOk(result);
1029+
t.end();
1030+
});
1031+
1032+
test('compare: same member expressions', (t) => {
1033+
const result = compare('hello.world && hello.world && ls && hello.world', '__a && __a && __b && __a');
1034+
1035+
t.ok(result);
1036+
t.end();
1037+
});
1038+
1039+
test('compare: different literals', (t) => {
1040+
const result = compare('/.tsx?$/.test(name) || /{tsx?}$/.test(name)', '__a || __a');
1041+
1042+
t.notOk(result);
1043+
t.end();
1044+
});
1045+
10101046
function getProgramPath(str) {
10111047
let result;
10121048
const ast = parse(str);

0 commit comments

Comments
 (0)