@atlaskit/eslint-plugin-platform 2.3.0 → 2.4.0
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/CHANGELOG.md +13 -0
- package/dist/cjs/rules/compiled/expand-border-shorthand/index.js +4 -4
- package/dist/cjs/rules/ensure-test-runner-arguments/index.js +1 -1
- package/dist/cjs/rules/ensure-test-runner-nested-count/index.js +1 -1
- package/dist/cjs/rules/feature-gating/inline-usage/index.js +7 -4
- package/dist/cjs/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/cjs/rules/feature-gating/no-preconditioning/index.js +4 -4
- package/dist/cjs/rules/feature-gating/use-recommended-utils/index.js +2 -2
- package/dist/cjs/rules/no-duplicate-dependencies/index.js +2 -2
- package/dist/cjs/rules/no-invalid-feature-flag-usage/index.js +6 -6
- package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
- package/dist/cjs/rules/no-pre-post-installs/index.js +1 -1
- package/dist/es2019/rules/feature-gating/inline-usage/index.js +3 -0
- package/dist/esm/rules/compiled/expand-border-shorthand/index.js +4 -4
- package/dist/esm/rules/ensure-test-runner-arguments/index.js +1 -1
- package/dist/esm/rules/ensure-test-runner-nested-count/index.js +1 -1
- package/dist/esm/rules/feature-gating/inline-usage/index.js +7 -4
- package/dist/esm/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/esm/rules/feature-gating/no-preconditioning/index.js +4 -4
- package/dist/esm/rules/feature-gating/use-recommended-utils/index.js +2 -2
- package/dist/esm/rules/no-duplicate-dependencies/index.js +2 -2
- package/dist/esm/rules/no-invalid-feature-flag-usage/index.js +6 -6
- package/dist/esm/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
- package/dist/esm/rules/no-pre-post-installs/index.js +1 -1
- package/package.json +2 -2
- package/src/rules/feature-gating/inline-usage/index.tsx +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 2.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#113173](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/113173)
|
|
8
|
+
[`46aad36c62f2f`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/46aad36c62f2f) -
|
|
9
|
+
Cuts a new changeset to land ESLint v9 changes to NPM fully (shipped internally Feb 5th:
|
|
10
|
+
https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/109855)
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
|
|
3
16
|
## 2.3.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.expandBorderShorthand = exports.default = void 0;
|
|
7
7
|
var EXCLUDED_VALUES = ['0', 'none', 'unset', 'none !important'];
|
|
8
|
-
var
|
|
8
|
+
var _findCallExpression = function findCallExpression(node) {
|
|
9
9
|
var parent = node.parent;
|
|
10
10
|
if (!parent) {
|
|
11
11
|
return null;
|
|
@@ -13,7 +13,7 @@ var findCallExpression = function findCallExpression(node) {
|
|
|
13
13
|
if (parent.type === 'CallExpression') {
|
|
14
14
|
return parent;
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return _findCallExpression(parent);
|
|
17
17
|
};
|
|
18
18
|
var separateBorderProperties = function separateBorderProperties(borderString, property, context) {
|
|
19
19
|
if (EXCLUDED_VALUES.includes(borderString)) {
|
|
@@ -58,11 +58,11 @@ var expandBorderShorthand = exports.expandBorderShorthand = {
|
|
|
58
58
|
create: function create(context) {
|
|
59
59
|
var importDeclaration;
|
|
60
60
|
return {
|
|
61
|
-
'ImportDeclaration[source.value="@compiled/react"], ImportDeclaration[source.value="@atlaskit/css"]': function
|
|
61
|
+
'ImportDeclaration[source.value="@compiled/react"], ImportDeclaration[source.value="@atlaskit/css"]': function ImportDeclarationSourceValueCompiled_react_ImportDeclarationSourceValueAtlaskit_css(node) {
|
|
62
62
|
importDeclaration = node;
|
|
63
63
|
},
|
|
64
64
|
'Property[key.name="border"]': function PropertyKeyNameBorder(node) {
|
|
65
|
-
var callExpression =
|
|
65
|
+
var callExpression = _findCallExpression(node);
|
|
66
66
|
if (!callExpression) {
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
@@ -25,7 +25,7 @@ var rule = {
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
create: function create(context) {
|
|
28
|
-
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/]"), function
|
|
28
|
+
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
29
29
|
if (node.type === 'CallExpression') {
|
|
30
30
|
var _node$parent, _node$parent2;
|
|
31
31
|
var args = node.arguments;
|
|
@@ -49,7 +49,7 @@ var rule = {
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
create: function create(context) {
|
|
52
|
-
return (0, _defineProperty2.default)({}, "Program > * > CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/], CallExpression[callee.name=/describe/] > * > * > * > CallExpression[callee.name=/").concat(TEST_RUNNER_IDENTIFIER, "/]"), function
|
|
52
|
+
return (0, _defineProperty2.default)({}, "Program > * > CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/], CallExpression[callee.name=/describe/] > * > * > * > CallExpression[callee.name=/").concat(TEST_RUNNER_IDENTIFIER, "/]"), function Program____CallExpressionCalleeName___CallExpressionCalleeName_describe_________CallExpressionCalleeName__(node) {
|
|
53
53
|
if (node.type === 'CallExpression') {
|
|
54
54
|
// Calculate the depth of nested test runners, counting from the most outside
|
|
55
55
|
var depth = getDepthOfNestedRunner(node);
|
|
@@ -9,15 +9,15 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
9
9
|
var _utils = require("../utils");
|
|
10
10
|
var FUNCTION_NAMES = new Set(['ff', 'fg', 'expVal', 'expValEquals', 'UNSAFE_noExposureExp']);
|
|
11
11
|
var STATSIG_ONLY_FUNCTION_NAMES = new Set(['fg', 'expVal', 'expValEquals', 'UNSAFE_noExposureExp']);
|
|
12
|
-
var
|
|
13
|
-
return node.type === 'VariableDeclaration' || node.type === 'FunctionDeclaration' ? node :
|
|
12
|
+
var _findDefinitionDeclaration = function findDefinitionDeclaration(node) {
|
|
13
|
+
return node.type === 'VariableDeclaration' || node.type === 'FunctionDeclaration' ? node : _findDefinitionDeclaration(node.parent);
|
|
14
14
|
};
|
|
15
15
|
var validateCallExpression = function validateCallExpression(node, context) {
|
|
16
16
|
var targetedFunctionsSwitch = context.options[0] === 'ssOnly' ? STATSIG_ONLY_FUNCTION_NAMES : FUNCTION_NAMES;
|
|
17
17
|
var callee = node.callee;
|
|
18
18
|
var shouldWarn = callee.type === 'Identifier' && targetedFunctionsSwitch.has(callee.name) && (0, _utils.isAPIimport)(callee.name, context, node);
|
|
19
19
|
if (shouldWarn) {
|
|
20
|
-
var defDeclaration =
|
|
20
|
+
var defDeclaration = _findDefinitionDeclaration(node.parent);
|
|
21
21
|
context.report({
|
|
22
22
|
messageId: 'inlineUsage',
|
|
23
23
|
node: defDeclaration.parent.type === 'ExportNamedDeclaration' ? defDeclaration.parent : defDeclaration
|
|
@@ -74,13 +74,16 @@ var rule = {
|
|
|
74
74
|
description: 'Ensure feature flags/gates and experiments are inlined so that they can be statically analyzable.',
|
|
75
75
|
url: 'https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/browse/platform/packages/platform/eslint-plugin/src/rules/inline-usage/README.md'
|
|
76
76
|
},
|
|
77
|
+
schema: [{
|
|
78
|
+
enum: ['ssOnly']
|
|
79
|
+
}],
|
|
77
80
|
messages: {
|
|
78
81
|
inlineUsage: 'Do not export or wrap feature flags/gates and experiments usages. Inline calls at the callsite to ensure it is statically analyzable.'
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
create: function create(context) {
|
|
82
85
|
return {
|
|
83
|
-
'VariableDeclaration[declarations.length=1] > VariableDeclarator[id.type="Identifier"]:matches([init.type="ArrowFunctionExpression"], [init.type="FunctionExpression"]) > *.init': function
|
|
86
|
+
'VariableDeclaration[declarations.length=1] > VariableDeclarator[id.type="Identifier"]:matches([init.type="ArrowFunctionExpression"], [init.type="FunctionExpression"]) > *.init': function VariableDeclarationDeclarationsLength1__VariableDeclaratorIdTypeIdentifierMatchesInitTypeArrowFunctionExpression_InitTypeFunctionExpression__Init(_ref2) {
|
|
84
87
|
var body = _ref2.body;
|
|
85
88
|
validateFunctionBody(body, context);
|
|
86
89
|
},
|
|
@@ -46,7 +46,7 @@ var rule = {
|
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
},
|
|
49
|
-
'VariableDeclaration[kind="const"] > VariableDeclarator[id.type="Identifier"][init.type="Identifier"]': function
|
|
49
|
+
'VariableDeclaration[kind="const"] > VariableDeclarator[id.type="Identifier"][init.type="Identifier"]': function VariableDeclarationKindConst__VariableDeclaratorIdTypeIdentifierInitTypeIdentifier(node) {
|
|
50
50
|
if (!node.init || node.init.type !== 'Identifier') {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
@@ -11,10 +11,10 @@ var isAndExpression = function isAndExpression(node) {
|
|
|
11
11
|
var isExpUsage = function isExpUsage(calleeName) {
|
|
12
12
|
return calleeName === 'expVal' || calleeName === 'expValEquals';
|
|
13
13
|
};
|
|
14
|
-
var
|
|
14
|
+
var _getGateType = function getGateType(node, context) {
|
|
15
15
|
var type = node.type;
|
|
16
16
|
if (type === 'BinaryExpression') {
|
|
17
|
-
return
|
|
17
|
+
return _getGateType(node.left, context) || _getGateType(node.right, context);
|
|
18
18
|
}
|
|
19
19
|
if (node.type === 'CallExpression') {
|
|
20
20
|
var callee = node.callee;
|
|
@@ -29,9 +29,9 @@ var getPreconditionStatus = function getPreconditionStatus(logicalExpression, co
|
|
|
29
29
|
var _ref = logicalExpression,
|
|
30
30
|
left = _ref.left;
|
|
31
31
|
// If left side is a nested AND expression then the left side node is on the nested's right
|
|
32
|
-
var leftGateType =
|
|
32
|
+
var leftGateType = _getGateType(isAndExpression(left) ? left.right : left, context);
|
|
33
33
|
if (leftGateType) {
|
|
34
|
-
var rightGateType =
|
|
34
|
+
var rightGateType = _getGateType(logicalExpression.right, context);
|
|
35
35
|
// Check this scenario: fg('gate') && isAdmin
|
|
36
36
|
if (!rightGateType) {
|
|
37
37
|
return 'early-exposure';
|
|
@@ -20,7 +20,7 @@ var rule = {
|
|
|
20
20
|
},
|
|
21
21
|
create: function create(context) {
|
|
22
22
|
return {
|
|
23
|
-
'CallExpression > MemberExpression:matches([property.name="checkGate"])': function
|
|
23
|
+
'CallExpression > MemberExpression:matches([property.name="checkGate"])': function CallExpression__MemberExpressionMatchesPropertyNameCheckGate(node) {
|
|
24
24
|
if (node.object.type === 'Identifier' && (0, _utils.isIdentifierImportedFrom)(node.object.name, BANNED_IMPORTS_SET, context, node)) {
|
|
25
25
|
context.report({
|
|
26
26
|
messageId: 'useRecommended',
|
|
@@ -33,7 +33,7 @@ var rule = {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
'CallExpression > MemberExpression:matches([property.name="getExperimentValue"])': function
|
|
36
|
+
'CallExpression > MemberExpression:matches([property.name="getExperimentValue"])': function CallExpression__MemberExpressionMatchesPropertyNameGetExperimentValue(node) {
|
|
37
37
|
if (node.object.type === 'Identifier' && (0, _utils.isIdentifierImportedFrom)(node.object.name, BANNED_IMPORTS_SET, context, node)) {
|
|
38
38
|
context.report({
|
|
39
39
|
messageId: 'notSupported',
|
|
@@ -27,11 +27,11 @@ var rule = {
|
|
|
27
27
|
var dependencies = new Map();
|
|
28
28
|
var devDependencies = new Map();
|
|
29
29
|
return {
|
|
30
|
-
'ObjectExpression Property[key.value=dependencies] Property': function
|
|
30
|
+
'ObjectExpression Property[key.value=dependencies] Property': function ObjectExpression_PropertyKeyValueDependencies_Property(node) {
|
|
31
31
|
// @ts-expect-error
|
|
32
32
|
dependencies.set(node.key.value, node.key);
|
|
33
33
|
},
|
|
34
|
-
'ObjectExpression Property[key.value=devDependencies] Property': function
|
|
34
|
+
'ObjectExpression Property[key.value=devDependencies] Property': function ObjectExpression_PropertyKeyValueDevDependencies_Property(node) {
|
|
35
35
|
// @ts-expect-error
|
|
36
36
|
devDependencies.set(node.key.value, node.key);
|
|
37
37
|
},
|
|
@@ -9,12 +9,12 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
9
9
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
10
10
|
|
|
11
11
|
var FF_GETTER_BOOLEAN_IDENTIFIER = 'getBooleanFF';
|
|
12
|
-
var
|
|
12
|
+
var _isOnlyOneFlagCheckInExpression = function __isOnlyOneFlagCheckInExpression(root, ignoredNode) {
|
|
13
13
|
switch (root.type) {
|
|
14
14
|
case 'IfStatement':
|
|
15
|
-
return
|
|
15
|
+
return _isOnlyOneFlagCheckInExpression(root.test, ignoredNode);
|
|
16
16
|
case 'UnaryExpression':
|
|
17
|
-
return
|
|
17
|
+
return _isOnlyOneFlagCheckInExpression(root.argument, ignoredNode);
|
|
18
18
|
case 'CallExpression':
|
|
19
19
|
if (root === ignoredNode) {
|
|
20
20
|
return true;
|
|
@@ -26,7 +26,7 @@ var __isOnlyOneFlagCheckInExpression = function __isOnlyOneFlagCheckInExpression
|
|
|
26
26
|
return root.name !== FF_GETTER_BOOLEAN_IDENTIFIER;
|
|
27
27
|
case 'BinaryExpression':
|
|
28
28
|
case 'LogicalExpression':
|
|
29
|
-
return
|
|
29
|
+
return _isOnlyOneFlagCheckInExpression(root.left, ignoredNode) && _isOnlyOneFlagCheckInExpression(root.right, ignoredNode);
|
|
30
30
|
default:
|
|
31
31
|
return true;
|
|
32
32
|
}
|
|
@@ -38,7 +38,7 @@ var isOnlyOneFlagCheckInExpression = function isOnlyOneFlagCheckInExpression(nod
|
|
|
38
38
|
while (root.type.endsWith('Expression')) {
|
|
39
39
|
root = root.parent;
|
|
40
40
|
}
|
|
41
|
-
return
|
|
41
|
+
return _isOnlyOneFlagCheckInExpression(root, node);
|
|
42
42
|
};
|
|
43
43
|
var rule = {
|
|
44
44
|
meta: {
|
|
@@ -55,7 +55,7 @@ var rule = {
|
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
create: function create(context) {
|
|
58
|
-
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(FF_GETTER_BOOLEAN_IDENTIFIER, "/]"), function
|
|
58
|
+
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(FF_GETTER_BOOLEAN_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
59
59
|
var _node$parent2;
|
|
60
60
|
// to make typescript happy
|
|
61
61
|
if (node.type === 'CallExpression') {
|
|
@@ -21,7 +21,7 @@ var rule = {
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
create: function create(context) {
|
|
24
|
-
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function
|
|
24
|
+
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
25
25
|
// to make typescript happy
|
|
26
26
|
if (node.type === 'CallExpression') {
|
|
27
27
|
var args = node.arguments;
|
|
@@ -20,7 +20,7 @@ var rule = {
|
|
|
20
20
|
},
|
|
21
21
|
create: function create(context) {
|
|
22
22
|
return {
|
|
23
|
-
'ObjectExpression Property[key.value=scripts] Property[key.value=/^(pre|post)install$/]': function
|
|
23
|
+
'ObjectExpression Property[key.value=scripts] Property[key.value=/^(pre|post)install$/]': function ObjectExpression_PropertyKeyValueScripts_PropertyKeyValue_PrePostInstall$_(node) {
|
|
24
24
|
if (!context.getFilename().endsWith('/package.json')) {
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
@@ -68,6 +68,9 @@ const rule = {
|
|
|
68
68
|
description: 'Ensure feature flags/gates and experiments are inlined so that they can be statically analyzable.',
|
|
69
69
|
url: 'https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/browse/platform/packages/platform/eslint-plugin/src/rules/inline-usage/README.md'
|
|
70
70
|
},
|
|
71
|
+
schema: [{
|
|
72
|
+
enum: ['ssOnly']
|
|
73
|
+
}],
|
|
71
74
|
messages: {
|
|
72
75
|
inlineUsage: 'Do not export or wrap feature flags/gates and experiments usages. Inline calls at the callsite to ensure it is statically analyzable.'
|
|
73
76
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var EXCLUDED_VALUES = ['0', 'none', 'unset', 'none !important'];
|
|
2
|
-
var
|
|
2
|
+
var _findCallExpression = function findCallExpression(node) {
|
|
3
3
|
var parent = node.parent;
|
|
4
4
|
if (!parent) {
|
|
5
5
|
return null;
|
|
@@ -7,7 +7,7 @@ var findCallExpression = function findCallExpression(node) {
|
|
|
7
7
|
if (parent.type === 'CallExpression') {
|
|
8
8
|
return parent;
|
|
9
9
|
}
|
|
10
|
-
return
|
|
10
|
+
return _findCallExpression(parent);
|
|
11
11
|
};
|
|
12
12
|
var separateBorderProperties = function separateBorderProperties(borderString, property, context) {
|
|
13
13
|
if (EXCLUDED_VALUES.includes(borderString)) {
|
|
@@ -52,11 +52,11 @@ export var expandBorderShorthand = {
|
|
|
52
52
|
create: function create(context) {
|
|
53
53
|
var importDeclaration;
|
|
54
54
|
return {
|
|
55
|
-
'ImportDeclaration[source.value="@compiled/react"], ImportDeclaration[source.value="@atlaskit/css"]': function
|
|
55
|
+
'ImportDeclaration[source.value="@compiled/react"], ImportDeclaration[source.value="@atlaskit/css"]': function ImportDeclarationSourceValueCompiled_react_ImportDeclarationSourceValueAtlaskit_css(node) {
|
|
56
56
|
importDeclaration = node;
|
|
57
57
|
},
|
|
58
58
|
'Property[key.name="border"]': function PropertyKeyNameBorder(node) {
|
|
59
|
-
var callExpression =
|
|
59
|
+
var callExpression = _findCallExpression(node);
|
|
60
60
|
if (!callExpression) {
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
@@ -18,7 +18,7 @@ var rule = {
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
create: function create(context) {
|
|
21
|
-
return _defineProperty({}, "CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/]"), function
|
|
21
|
+
return _defineProperty({}, "CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
22
22
|
if (node.type === 'CallExpression') {
|
|
23
23
|
var _node$parent, _node$parent2;
|
|
24
24
|
var args = node.arguments;
|
|
@@ -42,7 +42,7 @@ var rule = {
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
create: function create(context) {
|
|
45
|
-
return _defineProperty({}, "Program > * > CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/], CallExpression[callee.name=/describe/] > * > * > * > CallExpression[callee.name=/").concat(TEST_RUNNER_IDENTIFIER, "/]"), function
|
|
45
|
+
return _defineProperty({}, "Program > * > CallExpression[callee.name=/".concat(TEST_RUNNER_IDENTIFIER, "/], CallExpression[callee.name=/describe/] > * > * > * > CallExpression[callee.name=/").concat(TEST_RUNNER_IDENTIFIER, "/]"), function Program____CallExpressionCalleeName___CallExpressionCalleeName_describe_________CallExpressionCalleeName__(node) {
|
|
46
46
|
if (node.type === 'CallExpression') {
|
|
47
47
|
// Calculate the depth of nested test runners, counting from the most outside
|
|
48
48
|
var depth = getDepthOfNestedRunner(node);
|
|
@@ -2,15 +2,15 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
2
2
|
import { isAPIimport } from '../utils';
|
|
3
3
|
var FUNCTION_NAMES = new Set(['ff', 'fg', 'expVal', 'expValEquals', 'UNSAFE_noExposureExp']);
|
|
4
4
|
var STATSIG_ONLY_FUNCTION_NAMES = new Set(['fg', 'expVal', 'expValEquals', 'UNSAFE_noExposureExp']);
|
|
5
|
-
var
|
|
6
|
-
return node.type === 'VariableDeclaration' || node.type === 'FunctionDeclaration' ? node :
|
|
5
|
+
var _findDefinitionDeclaration = function findDefinitionDeclaration(node) {
|
|
6
|
+
return node.type === 'VariableDeclaration' || node.type === 'FunctionDeclaration' ? node : _findDefinitionDeclaration(node.parent);
|
|
7
7
|
};
|
|
8
8
|
var validateCallExpression = function validateCallExpression(node, context) {
|
|
9
9
|
var targetedFunctionsSwitch = context.options[0] === 'ssOnly' ? STATSIG_ONLY_FUNCTION_NAMES : FUNCTION_NAMES;
|
|
10
10
|
var callee = node.callee;
|
|
11
11
|
var shouldWarn = callee.type === 'Identifier' && targetedFunctionsSwitch.has(callee.name) && isAPIimport(callee.name, context, node);
|
|
12
12
|
if (shouldWarn) {
|
|
13
|
-
var defDeclaration =
|
|
13
|
+
var defDeclaration = _findDefinitionDeclaration(node.parent);
|
|
14
14
|
context.report({
|
|
15
15
|
messageId: 'inlineUsage',
|
|
16
16
|
node: defDeclaration.parent.type === 'ExportNamedDeclaration' ? defDeclaration.parent : defDeclaration
|
|
@@ -67,13 +67,16 @@ var rule = {
|
|
|
67
67
|
description: 'Ensure feature flags/gates and experiments are inlined so that they can be statically analyzable.',
|
|
68
68
|
url: 'https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/browse/platform/packages/platform/eslint-plugin/src/rules/inline-usage/README.md'
|
|
69
69
|
},
|
|
70
|
+
schema: [{
|
|
71
|
+
enum: ['ssOnly']
|
|
72
|
+
}],
|
|
70
73
|
messages: {
|
|
71
74
|
inlineUsage: 'Do not export or wrap feature flags/gates and experiments usages. Inline calls at the callsite to ensure it is statically analyzable.'
|
|
72
75
|
}
|
|
73
76
|
},
|
|
74
77
|
create: function create(context) {
|
|
75
78
|
return {
|
|
76
|
-
'VariableDeclaration[declarations.length=1] > VariableDeclarator[id.type="Identifier"]:matches([init.type="ArrowFunctionExpression"], [init.type="FunctionExpression"]) > *.init': function
|
|
79
|
+
'VariableDeclaration[declarations.length=1] > VariableDeclarator[id.type="Identifier"]:matches([init.type="ArrowFunctionExpression"], [init.type="FunctionExpression"]) > *.init': function VariableDeclarationDeclarationsLength1__VariableDeclaratorIdTypeIdentifierMatchesInitTypeArrowFunctionExpression_InitTypeFunctionExpression__Init(_ref2) {
|
|
77
80
|
var body = _ref2.body;
|
|
78
81
|
validateFunctionBody(body, context);
|
|
79
82
|
},
|
|
@@ -39,7 +39,7 @@ var rule = {
|
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
},
|
|
42
|
-
'VariableDeclaration[kind="const"] > VariableDeclarator[id.type="Identifier"][init.type="Identifier"]': function
|
|
42
|
+
'VariableDeclaration[kind="const"] > VariableDeclarator[id.type="Identifier"][init.type="Identifier"]': function VariableDeclarationKindConst__VariableDeclaratorIdTypeIdentifierInitTypeIdentifier(node) {
|
|
43
43
|
if (!node.init || node.init.type !== 'Identifier') {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
@@ -5,10 +5,10 @@ var isAndExpression = function isAndExpression(node) {
|
|
|
5
5
|
var isExpUsage = function isExpUsage(calleeName) {
|
|
6
6
|
return calleeName === 'expVal' || calleeName === 'expValEquals';
|
|
7
7
|
};
|
|
8
|
-
var
|
|
8
|
+
var _getGateType = function getGateType(node, context) {
|
|
9
9
|
var type = node.type;
|
|
10
10
|
if (type === 'BinaryExpression') {
|
|
11
|
-
return
|
|
11
|
+
return _getGateType(node.left, context) || _getGateType(node.right, context);
|
|
12
12
|
}
|
|
13
13
|
if (node.type === 'CallExpression') {
|
|
14
14
|
var callee = node.callee;
|
|
@@ -23,9 +23,9 @@ var getPreconditionStatus = function getPreconditionStatus(logicalExpression, co
|
|
|
23
23
|
var _ref = logicalExpression,
|
|
24
24
|
left = _ref.left;
|
|
25
25
|
// If left side is a nested AND expression then the left side node is on the nested's right
|
|
26
|
-
var leftGateType =
|
|
26
|
+
var leftGateType = _getGateType(isAndExpression(left) ? left.right : left, context);
|
|
27
27
|
if (leftGateType) {
|
|
28
|
-
var rightGateType =
|
|
28
|
+
var rightGateType = _getGateType(logicalExpression.right, context);
|
|
29
29
|
// Check this scenario: fg('gate') && isAdmin
|
|
30
30
|
if (!rightGateType) {
|
|
31
31
|
return 'early-exposure';
|
|
@@ -14,7 +14,7 @@ var rule = {
|
|
|
14
14
|
},
|
|
15
15
|
create: function create(context) {
|
|
16
16
|
return {
|
|
17
|
-
'CallExpression > MemberExpression:matches([property.name="checkGate"])': function
|
|
17
|
+
'CallExpression > MemberExpression:matches([property.name="checkGate"])': function CallExpression__MemberExpressionMatchesPropertyNameCheckGate(node) {
|
|
18
18
|
if (node.object.type === 'Identifier' && isIdentifierImportedFrom(node.object.name, BANNED_IMPORTS_SET, context, node)) {
|
|
19
19
|
context.report({
|
|
20
20
|
messageId: 'useRecommended',
|
|
@@ -27,7 +27,7 @@ var rule = {
|
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
|
-
'CallExpression > MemberExpression:matches([property.name="getExperimentValue"])': function
|
|
30
|
+
'CallExpression > MemberExpression:matches([property.name="getExperimentValue"])': function CallExpression__MemberExpressionMatchesPropertyNameGetExperimentValue(node) {
|
|
31
31
|
if (node.object.type === 'Identifier' && isIdentifierImportedFrom(node.object.name, BANNED_IMPORTS_SET, context, node)) {
|
|
32
32
|
context.report({
|
|
33
33
|
messageId: 'notSupported',
|
|
@@ -20,11 +20,11 @@ var rule = {
|
|
|
20
20
|
var dependencies = new Map();
|
|
21
21
|
var devDependencies = new Map();
|
|
22
22
|
return {
|
|
23
|
-
'ObjectExpression Property[key.value=dependencies] Property': function
|
|
23
|
+
'ObjectExpression Property[key.value=dependencies] Property': function ObjectExpression_PropertyKeyValueDependencies_Property(node) {
|
|
24
24
|
// @ts-expect-error
|
|
25
25
|
dependencies.set(node.key.value, node.key);
|
|
26
26
|
},
|
|
27
|
-
'ObjectExpression Property[key.value=devDependencies] Property': function
|
|
27
|
+
'ObjectExpression Property[key.value=devDependencies] Property': function ObjectExpression_PropertyKeyValueDevDependencies_Property(node) {
|
|
28
28
|
// @ts-expect-error
|
|
29
29
|
devDependencies.set(node.key.value, node.key);
|
|
30
30
|
},
|
|
@@ -2,12 +2,12 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
3
3
|
|
|
4
4
|
var FF_GETTER_BOOLEAN_IDENTIFIER = 'getBooleanFF';
|
|
5
|
-
var
|
|
5
|
+
var _isOnlyOneFlagCheckInExpression = function __isOnlyOneFlagCheckInExpression(root, ignoredNode) {
|
|
6
6
|
switch (root.type) {
|
|
7
7
|
case 'IfStatement':
|
|
8
|
-
return
|
|
8
|
+
return _isOnlyOneFlagCheckInExpression(root.test, ignoredNode);
|
|
9
9
|
case 'UnaryExpression':
|
|
10
|
-
return
|
|
10
|
+
return _isOnlyOneFlagCheckInExpression(root.argument, ignoredNode);
|
|
11
11
|
case 'CallExpression':
|
|
12
12
|
if (root === ignoredNode) {
|
|
13
13
|
return true;
|
|
@@ -19,7 +19,7 @@ var __isOnlyOneFlagCheckInExpression = function __isOnlyOneFlagCheckInExpression
|
|
|
19
19
|
return root.name !== FF_GETTER_BOOLEAN_IDENTIFIER;
|
|
20
20
|
case 'BinaryExpression':
|
|
21
21
|
case 'LogicalExpression':
|
|
22
|
-
return
|
|
22
|
+
return _isOnlyOneFlagCheckInExpression(root.left, ignoredNode) && _isOnlyOneFlagCheckInExpression(root.right, ignoredNode);
|
|
23
23
|
default:
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
@@ -31,7 +31,7 @@ var isOnlyOneFlagCheckInExpression = function isOnlyOneFlagCheckInExpression(nod
|
|
|
31
31
|
while (root.type.endsWith('Expression')) {
|
|
32
32
|
root = root.parent;
|
|
33
33
|
}
|
|
34
|
-
return
|
|
34
|
+
return _isOnlyOneFlagCheckInExpression(root, node);
|
|
35
35
|
};
|
|
36
36
|
var rule = {
|
|
37
37
|
meta: {
|
|
@@ -48,7 +48,7 @@ var rule = {
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
create: function create(context) {
|
|
51
|
-
return _defineProperty({}, "CallExpression[callee.name=/".concat(FF_GETTER_BOOLEAN_IDENTIFIER, "/]"), function
|
|
51
|
+
return _defineProperty({}, "CallExpression[callee.name=/".concat(FF_GETTER_BOOLEAN_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
52
52
|
var _node$parent2;
|
|
53
53
|
// to make typescript happy
|
|
54
54
|
if (node.type === 'CallExpression') {
|
|
@@ -14,7 +14,7 @@ var rule = {
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
create: function create(context) {
|
|
17
|
-
return _defineProperty({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function
|
|
17
|
+
return _defineProperty({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function CallExpressionCalleeName__(node) {
|
|
18
18
|
// to make typescript happy
|
|
19
19
|
if (node.type === 'CallExpression') {
|
|
20
20
|
var args = node.arguments;
|
|
@@ -14,7 +14,7 @@ var rule = {
|
|
|
14
14
|
},
|
|
15
15
|
create: function create(context) {
|
|
16
16
|
return {
|
|
17
|
-
'ObjectExpression Property[key.value=scripts] Property[key.value=/^(pre|post)install$/]': function
|
|
17
|
+
'ObjectExpression Property[key.value=scripts] Property[key.value=/^(pre|post)install$/]': function ObjectExpression_PropertyKeyValueScripts_PropertyKeyValue_PrePostInstall$_(node) {
|
|
18
18
|
if (!context.getFilename().endsWith('/package.json')) {
|
|
19
19
|
return;
|
|
20
20
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-platform",
|
|
3
3
|
"description": "The essential plugin for use with Atlassian frontend platform tools",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.0",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"atlassian": {
|
|
7
7
|
"team": "Build Infra",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
".": "./src/index.tsx"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@atlaskit/eslint-utils": "^1.
|
|
34
|
+
"@atlaskit/eslint-utils": "^1.10.0",
|
|
35
35
|
"@babel/runtime": "^7.0.0",
|
|
36
36
|
"@compiled/eslint-plugin": "^0.18.2",
|
|
37
37
|
"@manypkg/find-root": "^1.1.0",
|
|
@@ -109,6 +109,11 @@ const rule: Rule.RuleModule = {
|
|
|
109
109
|
'Ensure feature flags/gates and experiments are inlined so that they can be statically analyzable.',
|
|
110
110
|
url: 'https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/browse/platform/packages/platform/eslint-plugin/src/rules/inline-usage/README.md',
|
|
111
111
|
},
|
|
112
|
+
schema: [
|
|
113
|
+
{
|
|
114
|
+
enum: ['ssOnly'],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
112
117
|
messages: {
|
|
113
118
|
inlineUsage:
|
|
114
119
|
'Do not export or wrap feature flags/gates and experiments usages. Inline calls at the callsite to ensure it is statically analyzable.',
|