@thethracian/oxlint-config 0.2.1 → 0.3.1
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/README.md +124 -18
- package/dist/codemod-fix/cli.d.ts +3 -0
- package/dist/codemod-fix/cli.d.ts.map +1 -0
- package/dist/codemod-fix/cli.js +22 -0
- package/dist/codemod-fix/cli.js.map +1 -0
- package/dist/codemod-fix/index.d.ts +44 -0
- package/dist/codemod-fix/index.d.ts.map +1 -0
- package/dist/codemod-fix/index.js +110 -0
- package/dist/codemod-fix/index.js.map +1 -0
- package/dist/codemods/arrow-body-style.d.ts +7 -0
- package/dist/codemods/arrow-body-style.d.ts.map +1 -0
- package/dist/codemods/arrow-body-style.js +106 -0
- package/dist/codemods/arrow-body-style.js.map +1 -0
- package/dist/codemods/comment-format.d.ts +24 -0
- package/dist/codemods/comment-format.d.ts.map +1 -0
- package/dist/codemods/comment-format.js +100 -0
- package/dist/codemods/comment-format.js.map +1 -0
- package/dist/codemods/explicit-return-types.d.ts +7 -0
- package/dist/codemods/explicit-return-types.d.ts.map +1 -0
- package/dist/codemods/explicit-return-types.js +350 -0
- package/dist/codemods/explicit-return-types.js.map +1 -0
- package/dist/codemods/format-file-header.d.ts +7 -0
- package/dist/codemods/format-file-header.d.ts.map +1 -0
- package/dist/codemods/format-file-header.js +163 -0
- package/dist/codemods/format-file-header.js.map +1 -0
- package/dist/codemods/format-jsdoc-comments.d.ts +7 -0
- package/dist/codemods/format-jsdoc-comments.d.ts.map +1 -0
- package/dist/codemods/format-jsdoc-comments.js +129 -0
- package/dist/codemods/format-jsdoc-comments.js.map +1 -0
- package/dist/codemods/function-declarations.d.ts +7 -0
- package/dist/codemods/function-declarations.d.ts.map +1 -0
- package/dist/codemods/function-declarations.js +202 -0
- package/dist/codemods/function-declarations.js.map +1 -0
- package/dist/codemods/inline-export-lists.d.ts +7 -0
- package/dist/codemods/inline-export-lists.d.ts.map +1 -0
- package/dist/codemods/inline-export-lists.js +168 -0
- package/dist/codemods/inline-export-lists.js.map +1 -0
- package/dist/codemods/internal-export-docs.d.ts +7 -0
- package/dist/codemods/internal-export-docs.d.ts.map +1 -0
- package/dist/codemods/internal-export-docs.js +93 -0
- package/dist/codemods/internal-export-docs.js.map +1 -0
- package/dist/codemods/no-ternary-branch-initializers.d.ts +14 -0
- package/dist/codemods/no-ternary-branch-initializers.d.ts.map +1 -0
- package/dist/codemods/no-ternary-branch-initializers.js +240 -0
- package/dist/codemods/no-ternary-branch-initializers.js.map +1 -0
- package/dist/codemods/no-ternary-variable-initializers.d.ts +14 -0
- package/dist/codemods/no-ternary-variable-initializers.d.ts.map +1 -0
- package/dist/codemods/no-ternary-variable-initializers.js +235 -0
- package/dist/codemods/no-ternary-variable-initializers.js.map +1 -0
- package/dist/codemods/no-ternary.d.ts +7 -0
- package/dist/codemods/no-ternary.d.ts.map +1 -0
- package/dist/codemods/no-ternary.js +215 -0
- package/dist/codemods/no-ternary.js.map +1 -0
- package/dist/codemods/rename-acronyms.d.ts +8 -0
- package/dist/codemods/rename-acronyms.d.ts.map +1 -0
- package/dist/codemods/rename-acronyms.js +193 -0
- package/dist/codemods/rename-acronyms.js.map +1 -0
- package/dist/codemods/run.d.ts +2 -0
- package/dist/codemods/run.d.ts.map +1 -0
- package/dist/codemods/run.js +14 -0
- package/dist/codemods/run.js.map +1 -0
- package/dist/codemods/sort-imports.d.ts +7 -0
- package/dist/codemods/sort-imports.d.ts.map +1 -0
- package/dist/codemods/sort-imports.js +235 -0
- package/dist/codemods/sort-imports.js.map +1 -0
- package/dist/index.d.ts +30 -96
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +156 -94
- package/dist/index.js.map +1 -1
- package/dist/rules/acronym-case.d.ts +7 -3
- package/dist/rules/acronym-case.d.ts.map +1 -1
- package/dist/rules/acronym-case.js +129 -118
- package/dist/rules/acronym-case.js.map +1 -1
- package/dist/rules/acronyms-1.d.ts +3 -0
- package/dist/rules/acronyms-1.d.ts.map +1 -0
- package/dist/rules/acronyms-1.js +407 -0
- package/dist/rules/acronyms-1.js.map +1 -0
- package/dist/rules/acronyms-2.d.ts +3 -0
- package/dist/rules/acronyms-2.d.ts.map +1 -0
- package/dist/rules/acronyms-2.js +407 -0
- package/dist/rules/acronyms-2.js.map +1 -0
- package/dist/rules/acronyms-3.d.ts +3 -0
- package/dist/rules/acronyms-3.d.ts.map +1 -0
- package/dist/rules/acronyms-3.js +407 -0
- package/dist/rules/acronyms-3.js.map +1 -0
- package/dist/rules/acronyms-4.d.ts +3 -0
- package/dist/rules/acronyms-4.d.ts.map +1 -0
- package/dist/rules/acronyms-4.js +377 -0
- package/dist/rules/acronyms-4.js.map +1 -0
- package/dist/rules/acronyms.d.ts +1 -8
- package/dist/rules/acronyms.d.ts.map +1 -1
- package/dist/rules/acronyms.js +14 -1578
- package/dist/rules/acronyms.js.map +1 -1
- package/dist/rules/boolean-prefix.d.ts +11 -2
- package/dist/rules/boolean-prefix.d.ts.map +1 -1
- package/dist/rules/boolean-prefix.js +95 -59
- package/dist/rules/boolean-prefix.js.map +1 -1
- package/dist/rules/camel-case-identifiers.d.ts +3 -4
- package/dist/rules/camel-case-identifiers.d.ts.map +1 -1
- package/dist/rules/camel-case-identifiers.js +59 -40
- package/dist/rules/camel-case-identifiers.js.map +1 -1
- package/dist/rules/char-class.d.ts +26 -13
- package/dist/rules/char-class.d.ts.map +1 -1
- package/dist/rules/char-class.js +56 -24
- package/dist/rules/char-class.js.map +1 -1
- package/dist/rules/diagnostic-guidance.d.ts +91 -0
- package/dist/rules/diagnostic-guidance.d.ts.map +1 -0
- package/dist/rules/diagnostic-guidance.js +243 -0
- package/dist/rules/diagnostic-guidance.js.map +1 -0
- package/dist/rules/effect-default-ast.d.ts +89 -0
- package/dist/rules/effect-default-ast.d.ts.map +1 -0
- package/dist/rules/effect-default-ast.js +208 -0
- package/dist/rules/effect-default-ast.js.map +1 -0
- package/dist/rules/effect-default-compat-rules.d.ts +76 -0
- package/dist/rules/effect-default-compat-rules.d.ts.map +1 -0
- package/dist/rules/effect-default-compat-rules.js +270 -0
- package/dist/rules/effect-default-compat-rules.js.map +1 -0
- package/dist/rules/effect-default-env-rules.d.ts +60 -0
- package/dist/rules/effect-default-env-rules.d.ts.map +1 -0
- package/dist/rules/effect-default-env-rules.js +259 -0
- package/dist/rules/effect-default-env-rules.js.map +1 -0
- package/dist/rules/effect-default-fiber-helpers.d.ts +13 -0
- package/dist/rules/effect-default-fiber-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-fiber-helpers.js +76 -0
- package/dist/rules/effect-default-fiber-helpers.js.map +1 -0
- package/dist/rules/effect-default-floating-helpers.d.ts +7 -0
- package/dist/rules/effect-default-floating-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-floating-helpers.js +113 -0
- package/dist/rules/effect-default-floating-helpers.js.map +1 -0
- package/dist/rules/effect-default-helpers.d.ts +8 -32
- package/dist/rules/effect-default-helpers.d.ts.map +1 -1
- package/dist/rules/effect-default-helpers.js +11 -535
- package/dist/rules/effect-default-helpers.js.map +1 -1
- package/dist/rules/effect-default-resource-helpers.d.ts +18 -4
- package/dist/rules/effect-default-resource-helpers.d.ts.map +1 -1
- package/dist/rules/effect-default-resource-helpers.js +30 -13
- package/dist/rules/effect-default-resource-helpers.js.map +1 -1
- package/dist/rules/effect-default-safety-helpers.d.ts +43 -0
- package/dist/rules/effect-default-safety-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-safety-helpers.js +126 -0
- package/dist/rules/effect-default-safety-helpers.js.map +1 -0
- package/dist/rules/effect-default-scan-helpers.d.ts +43 -0
- package/dist/rules/effect-default-scan-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-scan-helpers.js +141 -0
- package/dist/rules/effect-default-scan-helpers.js.map +1 -0
- package/dist/rules/effect-default-schema-helpers.d.ts +37 -0
- package/dist/rules/effect-default-schema-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-schema-helpers.js +104 -0
- package/dist/rules/effect-default-schema-helpers.js.map +1 -0
- package/dist/rules/effect-default-test-helpers.d.ts +18 -4
- package/dist/rules/effect-default-test-helpers.d.ts.map +1 -1
- package/dist/rules/effect-default-test-helpers.js +41 -20
- package/dist/rules/effect-default-test-helpers.js.map +1 -1
- package/dist/rules/effect-default-workflow-helpers.d.ts +91 -0
- package/dist/rules/effect-default-workflow-helpers.d.ts.map +1 -0
- package/dist/rules/effect-default-workflow-helpers.js +247 -0
- package/dist/rules/effect-default-workflow-helpers.js.map +1 -0
- package/dist/rules/effect-default.d.ts +1 -1
- package/dist/rules/effect-default.d.ts.map +1 -1
- package/dist/rules/effect-default.js +105 -680
- package/dist/rules/effect-default.js.map +1 -1
- package/dist/rules/effect-exported-declarations.d.ts +19 -0
- package/dist/rules/effect-exported-declarations.d.ts.map +1 -0
- package/dist/rules/effect-exported-declarations.js +237 -0
- package/dist/rules/effect-exported-declarations.js.map +1 -0
- package/dist/rules/effect-path-options.d.ts +49 -11
- package/dist/rules/effect-path-options.d.ts.map +1 -1
- package/dist/rules/effect-path-options.js +85 -52
- package/dist/rules/effect-path-options.js.map +1 -1
- package/dist/rules/effect-rule-aliases.d.ts +55 -0
- package/dist/rules/effect-rule-aliases.d.ts.map +1 -0
- package/dist/rules/effect-rule-aliases.js +278 -0
- package/dist/rules/effect-rule-aliases.js.map +1 -0
- package/dist/rules/effect-rule-core.d.ts +38 -24
- package/dist/rules/effect-rule-core.d.ts.map +1 -1
- package/dist/rules/effect-rule-core.js +157 -344
- package/dist/rules/effect-rule-core.js.map +1 -1
- package/dist/rules/effect-rule-names.d.ts +12 -3
- package/dist/rules/effect-rule-names.d.ts.map +1 -1
- package/dist/rules/effect-rule-names.js +15 -3
- package/dist/rules/effect-rule-names.js.map +1 -1
- package/dist/rules/effect-source-comments.d.ts +7 -0
- package/dist/rules/effect-source-comments.d.ts.map +1 -0
- package/dist/rules/effect-source-comments.js +227 -0
- package/dist/rules/effect-source-comments.js.map +1 -0
- package/dist/rules/effect-source-helpers.d.ts +4 -9
- package/dist/rules/effect-source-helpers.d.ts.map +1 -1
- package/dist/rules/effect-source-helpers.js +7 -358
- package/dist/rules/effect-source-helpers.js.map +1 -1
- package/dist/rules/effect-source-navigation.d.ts +25 -0
- package/dist/rules/effect-source-navigation.d.ts.map +1 -0
- package/dist/rules/effect-source-navigation.js +244 -0
- package/dist/rules/effect-source-navigation.js.map +1 -0
- package/dist/rules/effect-source-scan.d.ts +30 -7
- package/dist/rules/effect-source-scan.d.ts.map +1 -1
- package/dist/rules/effect-source-scan.js +372 -300
- package/dist/rules/effect-source-scan.js.map +1 -1
- package/dist/rules/effect-strict-ast-specs.d.ts +8 -0
- package/dist/rules/effect-strict-ast-specs.d.ts.map +1 -0
- package/dist/rules/effect-strict-ast-specs.js +166 -0
- package/dist/rules/effect-strict-ast-specs.js.map +1 -0
- package/dist/rules/effect-strict-boundary-helpers.d.ts +25 -0
- package/dist/rules/effect-strict-boundary-helpers.d.ts.map +1 -0
- package/dist/rules/effect-strict-boundary-helpers.js +127 -0
- package/dist/rules/effect-strict-boundary-helpers.js.map +1 -0
- package/dist/rules/effect-strict-core-specs.d.ts +8 -0
- package/dist/rules/effect-strict-core-specs.d.ts.map +1 -0
- package/dist/rules/effect-strict-core-specs.js +334 -0
- package/dist/rules/effect-strict-core-specs.js.map +1 -0
- package/dist/rules/effect-strict-external-helpers.d.ts +25 -0
- package/dist/rules/effect-strict-external-helpers.d.ts.map +1 -0
- package/dist/rules/effect-strict-external-helpers.js +87 -0
- package/dist/rules/effect-strict-external-helpers.js.map +1 -0
- package/dist/rules/effect-strict-helpers.d.ts +75 -33
- package/dist/rules/effect-strict-helpers.d.ts.map +1 -1
- package/dist/rules/effect-strict-helpers.js +93 -384
- package/dist/rules/effect-strict-helpers.js.map +1 -1
- package/dist/rules/effect-strict-internals.d.ts +198 -0
- package/dist/rules/effect-strict-internals.d.ts.map +1 -0
- package/dist/rules/effect-strict-internals.js +477 -0
- package/dist/rules/effect-strict-internals.js.map +1 -0
- package/dist/rules/effect-strict-segment-helpers.d.ts +79 -0
- package/dist/rules/effect-strict-segment-helpers.d.ts.map +1 -0
- package/dist/rules/effect-strict-segment-helpers.js +308 -0
- package/dist/rules/effect-strict-segment-helpers.js.map +1 -0
- package/dist/rules/effect-strict.d.ts +1 -1
- package/dist/rules/effect-strict.d.ts.map +1 -1
- package/dist/rules/effect-strict.js +10 -725
- package/dist/rules/effect-strict.js.map +1 -1
- package/dist/rules/max-import-depth.d.ts +2 -2
- package/dist/rules/max-import-depth.d.ts.map +1 -1
- package/dist/rules/max-import-depth.js +52 -17
- package/dist/rules/max-import-depth.js.map +1 -1
- package/dist/rules/max-line-length.d.ts +9 -2
- package/dist/rules/max-line-length.d.ts.map +1 -1
- package/dist/rules/max-line-length.js +52 -15
- package/dist/rules/max-line-length.js.map +1 -1
- package/dist/rules/no-commented-out-code.d.ts +3 -7
- package/dist/rules/no-commented-out-code.d.ts.map +1 -1
- package/dist/rules/no-commented-out-code.js +157 -102
- package/dist/rules/no-commented-out-code.js.map +1 -1
- package/dist/rules/pascal-case-types.d.ts +1 -1
- package/dist/rules/pascal-case-types.d.ts.map +1 -1
- package/dist/rules/pascal-case-types.js +65 -46
- package/dist/rules/pascal-case-types.js.map +1 -1
- package/dist/rules/plugin-commented-out-code-rule.d.ts +32 -0
- package/dist/rules/plugin-commented-out-code-rule.d.ts.map +1 -0
- package/dist/rules/plugin-commented-out-code-rule.js +135 -0
- package/dist/rules/plugin-commented-out-code-rule.js.map +1 -0
- package/dist/rules/plugin.d.ts +5 -0
- package/dist/rules/plugin.d.ts.map +1 -1
- package/dist/rules/plugin.js +168 -154
- package/dist/rules/plugin.js.map +1 -1
- package/dist/rules/private-underscore.d.ts +1 -1
- package/dist/rules/private-underscore.d.ts.map +1 -1
- package/dist/rules/private-underscore.js +11 -4
- package/dist/rules/private-underscore.js.map +1 -1
- package/dist/rules/require-file-doc.d.ts +5 -6
- package/dist/rules/require-file-doc.d.ts.map +1 -1
- package/dist/rules/require-file-doc.js +127 -78
- package/dist/rules/require-file-doc.js.map +1 -1
- package/dist/rules/require-function-doc-ignored-text.d.ts +7 -0
- package/dist/rules/require-function-doc-ignored-text.d.ts.map +1 -0
- package/dist/rules/require-function-doc-ignored-text.js +67 -0
- package/dist/rules/require-function-doc-ignored-text.js.map +1 -0
- package/dist/rules/require-function-doc-local-exports.d.ts +7 -0
- package/dist/rules/require-function-doc-local-exports.d.ts.map +1 -0
- package/dist/rules/require-function-doc-local-exports.js +114 -0
- package/dist/rules/require-function-doc-local-exports.js.map +1 -0
- package/dist/rules/require-function-doc.d.ts +3 -18
- package/dist/rules/require-function-doc.d.ts.map +1 -1
- package/dist/rules/require-function-doc.js +396 -221
- package/dist/rules/require-function-doc.js.map +1 -1
- package/dist/rules/source-cache.d.ts +13 -5
- package/dist/rules/source-cache.d.ts.map +1 -1
- package/dist/rules/source-cache.js +35 -22
- package/dist/rules/source-cache.js.map +1 -1
- package/package.json +10 -2
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/* -------------------------------------------------------------------------- */
|
|
2
|
+
/* Core runtime for source-backed and AST-backed Effect lint rules. */
|
|
3
|
+
/* -------------------------------------------------------------------------- */
|
|
4
|
+
import { canonicalizeEffectAPIAliases } from './effect-rule-aliases.js';
|
|
5
|
+
import { effectDiagnosticMessage } from './diagnostic-guidance.js';
|
|
2
6
|
import { readCachedSource } from './source-cache.js';
|
|
7
|
+
import { stripCommentsAndStrings } from './effect-source-helpers.js';
|
|
3
8
|
const LINE_START_CACHE_MAX = 256;
|
|
4
9
|
const TOKEN_GATE_CACHE_MAX = 512;
|
|
10
|
+
const CHAR_CODE_NEWLINE = 10;
|
|
5
11
|
const lineStartCache = new Map();
|
|
6
12
|
const globalPatternCache = new WeakMap();
|
|
7
13
|
const tokenGateCache = new WeakMap();
|
|
8
14
|
const sourceTokenPresenceCache = new Map();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function isCodeAt(strippedSource, index) {
|
|
13
|
-
return strippedSource[index]?.trim() !== '';
|
|
14
|
-
}
|
|
15
|
-
function hasPattern(source, patterns) {
|
|
15
|
+
const readSource = (context) => readCachedSource(context);
|
|
16
|
+
const isCodeAt = (strippedSource, index) => strippedSource[index]?.trim() !== '';
|
|
17
|
+
const hasPattern = (source, patterns) => {
|
|
16
18
|
let strippedSource = undefined;
|
|
17
19
|
return patterns.some((pattern) => {
|
|
18
20
|
for (const match of source.matchAll(toGlobalRegExp(pattern))) {
|
|
@@ -23,41 +25,50 @@ function hasPattern(source, patterns) {
|
|
|
23
25
|
}
|
|
24
26
|
return false;
|
|
25
27
|
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
+
};
|
|
29
|
+
const toGlobalRegExp = (pattern) => {
|
|
28
30
|
const cachedPattern = globalPatternCache.get(pattern);
|
|
29
31
|
if (cachedPattern !== undefined) {
|
|
30
32
|
return cachedPattern;
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
let { flags } = pattern;
|
|
35
|
+
if (!flags.includes('g')) {
|
|
36
|
+
flags = `${flags}g`;
|
|
37
|
+
}
|
|
38
|
+
const globalPattern = new RegExp(pattern.source, flags);
|
|
33
39
|
globalPatternCache.set(pattern, globalPattern);
|
|
34
40
|
return globalPattern;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
};
|
|
42
|
+
const cachedLineStarts = (source) => lineStartCache.get(source);
|
|
43
|
+
const evictFirstLineStart = () => {
|
|
44
|
+
if (lineStartCache.size < LINE_START_CACHE_MAX) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const firstKey = lineStartCache.keys().next().value;
|
|
48
|
+
if (firstKey !== undefined) {
|
|
49
|
+
lineStartCache.delete(firstKey);
|
|
43
50
|
}
|
|
51
|
+
};
|
|
52
|
+
const computeLineStarts = (source) => {
|
|
44
53
|
const starts = [0];
|
|
45
54
|
for (let position = 0; position < source.length; position++) {
|
|
46
|
-
if (source.charCodeAt(position) ===
|
|
55
|
+
if (source.charCodeAt(position) === CHAR_CODE_NEWLINE) {
|
|
47
56
|
starts.push(position + 1);
|
|
48
57
|
}
|
|
49
58
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
return starts;
|
|
60
|
+
};
|
|
61
|
+
const lineStartsFor = (source) => {
|
|
62
|
+
const cachedStarts = cachedLineStarts(source);
|
|
63
|
+
if (cachedStarts !== undefined) {
|
|
64
|
+
return cachedStarts;
|
|
55
65
|
}
|
|
66
|
+
const starts = computeLineStarts(source);
|
|
67
|
+
evictFirstLineStart();
|
|
56
68
|
lineStartCache.set(source, starts);
|
|
57
69
|
return starts;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const starts = lineStartsFor(source);
|
|
70
|
+
};
|
|
71
|
+
const lineIndexFor = (starts, index) => {
|
|
61
72
|
let low = 0;
|
|
62
73
|
let high = starts.length - 1;
|
|
63
74
|
while (low <= high) {
|
|
@@ -70,50 +81,57 @@ function locFromIndex(source, index) {
|
|
|
70
81
|
high = middle - 1;
|
|
71
82
|
}
|
|
72
83
|
}
|
|
73
|
-
|
|
84
|
+
return Math.max(0, high);
|
|
85
|
+
};
|
|
86
|
+
const locFromIndex = (source, index) => {
|
|
87
|
+
const starts = lineStartsFor(source);
|
|
88
|
+
const lineIndex = lineIndexFor(starts, index);
|
|
74
89
|
const lineStart = starts[lineIndex] ?? 0;
|
|
75
90
|
const line = lineIndex + 1;
|
|
76
91
|
return { column: index - lineStart, line };
|
|
77
|
-
}
|
|
78
|
-
|
|
92
|
+
};
|
|
93
|
+
const firstPatternLOC = (source, patterns) => {
|
|
79
94
|
let strippedSource = undefined;
|
|
80
95
|
for (const pattern of patterns) {
|
|
81
96
|
for (const match of source.matchAll(toGlobalRegExp(pattern))) {
|
|
82
97
|
strippedSource ??= stripCommentsAndStrings(source);
|
|
83
|
-
if (
|
|
84
|
-
|
|
98
|
+
if (isCodeAt(strippedSource, match.index)) {
|
|
99
|
+
return locFromIndex(source, match.index);
|
|
85
100
|
}
|
|
86
|
-
return locFromIndex(source, match.index);
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
return undefined;
|
|
90
|
-
}
|
|
91
|
-
|
|
104
|
+
};
|
|
105
|
+
const reportPatternMatches = (input) => {
|
|
92
106
|
const { context, node, source, spec } = input;
|
|
107
|
+
const message = effectDiagnosticMessage(spec.name, spec.message);
|
|
93
108
|
if (!spec.countPatterns) {
|
|
94
109
|
context.report({
|
|
95
|
-
loc:
|
|
96
|
-
message
|
|
110
|
+
loc: firstPatternLOC(source, spec.patterns ?? []),
|
|
111
|
+
message,
|
|
97
112
|
node,
|
|
98
113
|
});
|
|
99
114
|
return;
|
|
100
115
|
}
|
|
116
|
+
reportCountedPatternMatches(input, message);
|
|
117
|
+
};
|
|
118
|
+
const reportCountedPatternMatches = (input, message) => {
|
|
119
|
+
const { context, node, source, spec } = input;
|
|
101
120
|
let strippedSource = undefined;
|
|
102
|
-
for (const pattern of spec.countPatterns) {
|
|
121
|
+
for (const pattern of spec.countPatterns ?? []) {
|
|
103
122
|
for (const match of source.matchAll(toGlobalRegExp(pattern))) {
|
|
104
123
|
strippedSource ??= stripCommentsAndStrings(source);
|
|
105
|
-
if (
|
|
106
|
-
|
|
124
|
+
if (isCodeAt(strippedSource, match.index)) {
|
|
125
|
+
context.report({
|
|
126
|
+
loc: locFromIndex(source, match.index),
|
|
127
|
+
message,
|
|
128
|
+
node,
|
|
129
|
+
});
|
|
107
130
|
}
|
|
108
|
-
context.report({
|
|
109
|
-
loc: locFromIndex(source, match.index),
|
|
110
|
-
message: spec.message,
|
|
111
|
-
node,
|
|
112
|
-
});
|
|
113
131
|
}
|
|
114
132
|
}
|
|
115
|
-
}
|
|
116
|
-
|
|
133
|
+
};
|
|
134
|
+
const checkResultIndex = (result) => {
|
|
117
135
|
if (typeof result === 'number') {
|
|
118
136
|
return result;
|
|
119
137
|
}
|
|
@@ -121,11 +139,14 @@ function checkResultIndex(result) {
|
|
|
121
139
|
return result.index;
|
|
122
140
|
}
|
|
123
141
|
return undefined;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
142
|
+
};
|
|
143
|
+
const isCheckViolation = (result) => {
|
|
144
|
+
if (typeof result === 'boolean') {
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
};
|
|
149
|
+
const cachedSourceTokenPresence = (source) => {
|
|
129
150
|
let tokenPresence = sourceTokenPresenceCache.get(source);
|
|
130
151
|
if (tokenPresence !== undefined) {
|
|
131
152
|
return tokenPresence;
|
|
@@ -139,8 +160,8 @@ function cachedSourceTokenPresence(source) {
|
|
|
139
160
|
tokenPresence = new Map();
|
|
140
161
|
sourceTokenPresenceCache.set(source, tokenPresence);
|
|
141
162
|
return tokenPresence;
|
|
142
|
-
}
|
|
143
|
-
|
|
163
|
+
};
|
|
164
|
+
const hasTokenInSourceCached = (source, token) => {
|
|
144
165
|
const tokenPresence = cachedSourceTokenPresence(source);
|
|
145
166
|
const cachedValue = tokenPresence.get(token);
|
|
146
167
|
if (cachedValue !== undefined) {
|
|
@@ -149,14 +170,10 @@ function hasTokenInSourceCached(source, token) {
|
|
|
149
170
|
const hasToken = source.includes(token);
|
|
150
171
|
tokenPresence.set(token, hasToken);
|
|
151
172
|
return hasToken;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
function cachedTokenGate(source, tokens) {
|
|
157
|
-
return tokenGateCache.get(tokens)?.get(source);
|
|
158
|
-
}
|
|
159
|
-
function cacheTokenGate(source, tokens, hasToken) {
|
|
173
|
+
};
|
|
174
|
+
const hasAnyToken = (source, tokens) => tokens.some((token) => hasTokenInSourceCached(source, token));
|
|
175
|
+
const cachedTokenGate = (source, tokens) => tokenGateCache.get(tokens)?.get(source);
|
|
176
|
+
const cacheTokenGate = (source, tokens, hasToken) => {
|
|
160
177
|
let sourceCache = tokenGateCache.get(tokens);
|
|
161
178
|
if (!sourceCache) {
|
|
162
179
|
sourceCache = new Map();
|
|
@@ -170,77 +187,96 @@ function cacheTokenGate(source, tokens, hasToken) {
|
|
|
170
187
|
}
|
|
171
188
|
sourceCache.set(source, hasToken);
|
|
172
189
|
return hasToken;
|
|
173
|
-
}
|
|
174
|
-
|
|
190
|
+
};
|
|
191
|
+
const hasAnyTokenCached = (source, tokens) => {
|
|
175
192
|
const cachedValue = cachedTokenGate(source, tokens);
|
|
176
193
|
if (cachedValue !== undefined) {
|
|
177
194
|
return cachedValue;
|
|
178
195
|
}
|
|
179
196
|
return cacheTokenGate(source, tokens, hasAnyToken(source, tokens));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
197
|
+
};
|
|
198
|
+
const hasEveryTokenGroup = (source, tokenGroups) => tokenGroups.every((group) => hasAnyTokenCached(source, group));
|
|
199
|
+
const shouldSkipSource = (source, requiredTokens, requiredTokenGroups) => source === '' ||
|
|
200
|
+
Boolean(requiredTokens && !hasAnyTokenCached(source, requiredTokens)) ||
|
|
201
|
+
Boolean(requiredTokenGroups && !hasEveryTokenGroup(source, requiredTokenGroups));
|
|
202
|
+
const checkResultLOC = (source, spec, checkResult) => {
|
|
203
|
+
const index = checkResultIndex(checkResult);
|
|
204
|
+
if (index !== undefined) {
|
|
205
|
+
return locFromIndex(source, index);
|
|
206
|
+
}
|
|
207
|
+
return firstPatternLOC(source, spec.patterns ?? []);
|
|
208
|
+
};
|
|
209
|
+
const reportCheckResult = (context, node, source, spec, checkResult) => {
|
|
210
|
+
context.report({
|
|
211
|
+
loc: checkResultLOC(source, spec, checkResult),
|
|
212
|
+
message: effectDiagnosticMessage(spec.name, spec.message),
|
|
213
|
+
node,
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
const guidedContext = (context, spec) => ({
|
|
217
|
+
get filename() {
|
|
218
|
+
return context.filename;
|
|
219
|
+
},
|
|
220
|
+
get options() {
|
|
221
|
+
return context.options;
|
|
222
|
+
},
|
|
223
|
+
report(descriptor) {
|
|
224
|
+
context.report({
|
|
225
|
+
...descriptor,
|
|
226
|
+
message: effectDiagnosticMessage(spec.name, descriptor.message),
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
get sourceCode() {
|
|
230
|
+
return context.sourceCode;
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
const runProgramRule = (input) => {
|
|
190
234
|
const { context, node, source, spec } = input;
|
|
191
|
-
const canonicalSource =
|
|
235
|
+
const canonicalSource = canonicalizeEffectAPIAliases(source);
|
|
192
236
|
const checkResult = spec.check?.(canonicalSource, context);
|
|
193
237
|
if (checkResult !== undefined) {
|
|
194
238
|
if (!isCheckViolation(checkResult)) {
|
|
195
239
|
return;
|
|
196
240
|
}
|
|
197
|
-
|
|
198
|
-
context.report({
|
|
199
|
-
loc: index === undefined
|
|
200
|
-
? firstPatternLoc(canonicalSource, spec.patterns ?? [])
|
|
201
|
-
: locFromIndex(canonicalSource, index),
|
|
202
|
-
message: spec.message,
|
|
203
|
-
node,
|
|
204
|
-
});
|
|
241
|
+
reportCheckResult(context, node, canonicalSource, spec, checkResult);
|
|
205
242
|
return;
|
|
206
243
|
}
|
|
207
244
|
if (hasPattern(canonicalSource, spec.patterns ?? [])) {
|
|
208
245
|
reportPatternMatches({ context, node, source: canonicalSource, spec });
|
|
209
246
|
}
|
|
210
|
-
}
|
|
211
|
-
|
|
247
|
+
};
|
|
248
|
+
const makeProgramOnlyRule = (spec, options) => {
|
|
212
249
|
const requiredTokens = spec.tokens ?? options.defaultTokens;
|
|
213
250
|
const requiredTokenGroups = spec.tokenGroups;
|
|
214
|
-
const rule =
|
|
251
|
+
const rule = makeASTCapableRule(spec, options);
|
|
215
252
|
return {
|
|
216
253
|
...rule,
|
|
217
254
|
createOnce(context) {
|
|
218
255
|
let source = '';
|
|
219
256
|
let isSkipped = true;
|
|
220
257
|
return {
|
|
221
|
-
before() {
|
|
222
|
-
source = readSource(context);
|
|
223
|
-
isSkipped = shouldSkipSource(source, requiredTokens, requiredTokenGroups);
|
|
224
|
-
return isSkipped ? false : undefined;
|
|
225
|
-
},
|
|
226
258
|
Program(node) {
|
|
227
259
|
if (isSkipped) {
|
|
228
260
|
return;
|
|
229
261
|
}
|
|
230
262
|
runProgramRule({ context, node, source, spec });
|
|
231
263
|
},
|
|
264
|
+
before() {
|
|
265
|
+
source = readSource(context);
|
|
266
|
+
isSkipped = shouldSkipSource(source, requiredTokens, requiredTokenGroups);
|
|
267
|
+
if (isSkipped) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
return undefined;
|
|
271
|
+
},
|
|
232
272
|
};
|
|
233
273
|
},
|
|
234
274
|
};
|
|
235
|
-
}
|
|
236
|
-
|
|
275
|
+
};
|
|
276
|
+
const makeASTCapableRule = (spec, options) => {
|
|
237
277
|
const requiredTokens = spec.tokens ?? options.defaultTokens;
|
|
238
278
|
const requiredTokenGroups = spec.tokenGroups;
|
|
239
279
|
const rule = {
|
|
240
|
-
meta: {
|
|
241
|
-
schema: options.schema,
|
|
242
|
-
type: 'problem',
|
|
243
|
-
},
|
|
244
280
|
create(context) {
|
|
245
281
|
const source = readSource(context);
|
|
246
282
|
if (shouldSkipSource(source, requiredTokens, requiredTokenGroups)) {
|
|
@@ -248,7 +284,8 @@ function makeAstCapableRule(spec, options) {
|
|
|
248
284
|
Program() { },
|
|
249
285
|
};
|
|
250
286
|
}
|
|
251
|
-
const
|
|
287
|
+
const astContext = guidedContext(context, spec);
|
|
288
|
+
const astVisitors = spec.ast?.(astContext, source) ?? {};
|
|
252
289
|
return {
|
|
253
290
|
...astVisitors,
|
|
254
291
|
Program(node) {
|
|
@@ -259,251 +296,27 @@ function makeAstCapableRule(spec, options) {
|
|
|
259
296
|
},
|
|
260
297
|
};
|
|
261
298
|
},
|
|
299
|
+
meta: {
|
|
300
|
+
docs: {
|
|
301
|
+
description: effectDiagnosticMessage(spec.name, spec.message),
|
|
302
|
+
},
|
|
303
|
+
schema: options.schema,
|
|
304
|
+
type: 'problem',
|
|
305
|
+
},
|
|
262
306
|
};
|
|
263
307
|
return rule;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
const codeOnly = stripCommentsAndStrings(source);
|
|
280
|
-
return cacheBoolean(effectSignalCache, source, hasEffectValueImport(source) ||
|
|
281
|
-
effectImportAliases(source).some((alias) => new RegExp(`\\b${escapeRegExp(alias)}\\.`, 'u').test(codeOnly)));
|
|
282
|
-
}
|
|
283
|
-
const runtimeCallPattern = /\b(?:Effect\.(?:runPromise|runPromiseExit|runSync|runSyncExit|runFork)|[A-Za-z_$][\w$]*Runtime\.runMain)\s*\(/;
|
|
284
|
-
const boundaryFilePattern = /(?:^|\/)src\/(?:main|server|cli)\.ts$|\.entry\.ts$/;
|
|
285
|
-
const testFilePattern = /\.(?:test|spec)\.tsx?$/;
|
|
286
|
-
const ALIAS_CACHE_MAX = 256;
|
|
287
|
-
const BOOLEAN_CACHE_MAX = 512;
|
|
288
|
-
const effectAliasCache = new Map();
|
|
289
|
-
const runtimeFunctionAliasCache = new Map();
|
|
290
|
-
const canonicalSourceCache = new Map();
|
|
291
|
-
const effectSignalCache = new Map();
|
|
292
|
-
const runtimeCallCache = new Map();
|
|
293
|
-
function cachedAliases(cache, source) {
|
|
294
|
-
return cache.get(source);
|
|
295
|
-
}
|
|
296
|
-
function cacheAliases(cache, source, value) {
|
|
297
|
-
if (cache.size >= ALIAS_CACHE_MAX) {
|
|
298
|
-
const firstKey = cache.keys().next().value;
|
|
299
|
-
if (firstKey !== undefined) {
|
|
300
|
-
cache.delete(firstKey);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
cache.set(source, value);
|
|
304
|
-
return value;
|
|
305
|
-
}
|
|
306
|
-
function cachedBoolean(cache, source) {
|
|
307
|
-
return cache.get(source);
|
|
308
|
-
}
|
|
309
|
-
function cacheBoolean(cache, source, value) {
|
|
310
|
-
if (cache.size >= BOOLEAN_CACHE_MAX) {
|
|
311
|
-
const firstKey = cache.keys().next().value;
|
|
312
|
-
if (firstKey !== undefined) {
|
|
313
|
-
cache.delete(firstKey);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
cache.set(source, value);
|
|
317
|
-
return value;
|
|
318
|
-
}
|
|
319
|
-
function escapeRegExp(value) {
|
|
320
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
321
|
-
}
|
|
322
|
-
function hasLocalEffectBinding(source) {
|
|
323
|
-
return /\b(?:const|let|var|function|class|namespace)\s+Effect\b/.test(stripCommentsAndStrings(source));
|
|
324
|
-
}
|
|
325
|
-
function importSpecifierNames(specifier) {
|
|
326
|
-
const trimmed = specifier.trim();
|
|
327
|
-
if (trimmed.startsWith('type ')) {
|
|
328
|
-
return undefined;
|
|
329
|
-
}
|
|
330
|
-
const parts = trimmed.split(/\s+as\s+/);
|
|
331
|
-
const importedName = parts[0]?.trim();
|
|
332
|
-
const localName = parts[1]?.trim() ?? importedName;
|
|
333
|
-
return importedName && localName ? { importedName, localName } : undefined;
|
|
334
|
-
}
|
|
335
|
-
function hasAnyEffectImport(source) {
|
|
336
|
-
return /(?:^|\n)\s*import(?:\s+type)?(?:[\s\S]*?\s+from\s*)?['"](?:effect(?:\/[^'"]+)?|@effect\/[^'"]+)['"]/.test(stripComments(source));
|
|
337
|
-
}
|
|
338
|
-
function hasEffectValueImport(source) {
|
|
339
|
-
const commentFreeSource = stripComments(source);
|
|
340
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\s*{([^}]+)}\s*from\s*['"]effect['"]/g)) {
|
|
341
|
-
if (match[1]
|
|
342
|
-
.split(',')
|
|
343
|
-
.some((specifier) => importSpecifierNames(specifier)?.importedName === 'Effect')) {
|
|
344
|
-
return true;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return (/(?:^|\n)\s*import\s+(?!type\b)\*\s+as\s+[A-Za-z_$][\w$]*\s+from\s*['"]effect(?:\/Effect)?['"]/.test(commentFreeSource) || effectFunctionAliases(source, 'Effect').length > 0);
|
|
348
|
-
}
|
|
349
|
-
function effectImportAliases(source) {
|
|
350
|
-
const cachedValue = cachedAliases(effectAliasCache, source);
|
|
351
|
-
if (cachedValue) {
|
|
352
|
-
return cachedValue;
|
|
353
|
-
}
|
|
354
|
-
const aliases = new Set();
|
|
355
|
-
const commentFreeSource = stripComments(source);
|
|
356
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\s*{([^}]+)}\s*from\s*['"]effect['"]/g)) {
|
|
357
|
-
for (const specifier of match[1].split(',')) {
|
|
358
|
-
const names = importSpecifierNames(specifier);
|
|
359
|
-
if (!names) {
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
if (names.importedName === 'Effect') {
|
|
363
|
-
aliases.add('Effect');
|
|
364
|
-
aliases.add(names.localName);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*['"]effect(?:\/Effect)?['"]/g)) {
|
|
369
|
-
aliases.add('Effect');
|
|
370
|
-
aliases.add(match[1]);
|
|
371
|
-
}
|
|
372
|
-
if (aliases.size === 0 && !hasAnyEffectImport(source) && !hasLocalEffectBinding(source)) {
|
|
373
|
-
aliases.add('Effect');
|
|
374
|
-
}
|
|
375
|
-
return cacheAliases(effectAliasCache, source, [...aliases]);
|
|
376
|
-
}
|
|
377
|
-
function effectApiAliases(source, apiName) {
|
|
378
|
-
const aliases = new Set();
|
|
379
|
-
const commentFreeSource = stripComments(source);
|
|
380
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\s*{([^}]+)}\s*from\s*['"]effect['"]/g)) {
|
|
381
|
-
for (const specifier of match[1].split(',')) {
|
|
382
|
-
const names = importSpecifierNames(specifier);
|
|
383
|
-
if (names?.importedName === apiName) {
|
|
384
|
-
aliases.add(names.localName);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
for (const match of commentFreeSource.matchAll(new RegExp(`(?:^|\\n)\\s*import\\s+(?!type\\b)\\*\\s+as\\s+([A-Za-z_$][\\w$]*)\\s+from\\s*['"]effect/${escapeRegExp(apiName)}['"]`, 'g'))) {
|
|
389
|
-
aliases.add(match[1]);
|
|
390
|
-
}
|
|
391
|
-
if (aliases.size === 0 && !hasAnyEffectImport(source)) {
|
|
392
|
-
aliases.add(apiName);
|
|
393
|
-
}
|
|
394
|
-
return [...aliases];
|
|
395
|
-
}
|
|
396
|
-
function effectFunctionAliases(source, moduleName, functionName) {
|
|
397
|
-
const aliases = new Set();
|
|
398
|
-
const commentFreeSource = stripComments(source);
|
|
399
|
-
for (const match of commentFreeSource.matchAll(new RegExp(`(?:^|\\n)\\s*import\\s+(?!type\\b)\\s*{([^}]+)}\\s*from\\s*['"]effect/${escapeRegExp(moduleName)}['"]`, 'g'))) {
|
|
400
|
-
for (const specifier of match[1].split(',')) {
|
|
401
|
-
const names = importSpecifierNames(specifier);
|
|
402
|
-
if (names && (!functionName || names.importedName === functionName)) {
|
|
403
|
-
aliases.add(names.localName);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
return [...aliases];
|
|
408
|
-
}
|
|
409
|
-
function canonicalImportAliases(source) {
|
|
410
|
-
const aliases = new Map();
|
|
411
|
-
const commentFreeSource = stripComments(source);
|
|
412
|
-
const canonicalNames = new Set([
|
|
413
|
-
'Config',
|
|
414
|
-
'Context',
|
|
415
|
-
'Effect',
|
|
416
|
-
'Fiber',
|
|
417
|
-
'Layer',
|
|
418
|
-
'Queue',
|
|
419
|
-
'Schedule',
|
|
420
|
-
'Schema',
|
|
421
|
-
'Scope',
|
|
422
|
-
'Stream',
|
|
423
|
-
'TestClock',
|
|
424
|
-
]);
|
|
425
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\s*{([^}]+)}\s*from\s*['"]effect['"]/g)) {
|
|
426
|
-
for (const specifier of match[1].split(',')) {
|
|
427
|
-
const names = importSpecifierNames(specifier);
|
|
428
|
-
const importedName = names?.importedName;
|
|
429
|
-
const localName = names?.localName;
|
|
430
|
-
if (importedName &&
|
|
431
|
-
localName &&
|
|
432
|
-
canonicalNames.has(importedName) &&
|
|
433
|
-
localName !== importedName) {
|
|
434
|
-
aliases.set(localName, importedName);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s+(?!type\b)\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*['"]effect\/([A-Za-z]+)['"]/g)) {
|
|
439
|
-
const [, localName, moduleName] = match;
|
|
440
|
-
if (canonicalNames.has(moduleName) && localName !== moduleName) {
|
|
441
|
-
aliases.set(localName, moduleName);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return aliases;
|
|
445
|
-
}
|
|
446
|
-
function canonicalizeEffectApiAliases(source) {
|
|
447
|
-
const cachedValue = canonicalSourceCache.get(source);
|
|
448
|
-
if (cachedValue !== undefined) {
|
|
449
|
-
return cachedValue;
|
|
450
|
-
}
|
|
451
|
-
let canonicalSource = source;
|
|
452
|
-
for (const [localName, canonicalName] of canonicalImportAliases(source)) {
|
|
453
|
-
canonicalSource = canonicalSource.replace(new RegExp(`\\b${escapeRegExp(localName)}\\.`, 'g'), `${canonicalName}.`);
|
|
454
|
-
}
|
|
455
|
-
if (canonicalSourceCache.size >= ALIAS_CACHE_MAX) {
|
|
456
|
-
const firstKey = canonicalSourceCache.keys().next().value;
|
|
457
|
-
if (firstKey !== undefined) {
|
|
458
|
-
canonicalSourceCache.delete(firstKey);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
canonicalSourceCache.set(source, canonicalSource);
|
|
462
|
-
return canonicalSource;
|
|
463
|
-
}
|
|
464
|
-
function effectRuntimeFunctionAliases(source) {
|
|
465
|
-
const cachedValue = cachedAliases(runtimeFunctionAliasCache, source);
|
|
466
|
-
if (cachedValue) {
|
|
467
|
-
return cachedValue;
|
|
468
|
-
}
|
|
469
|
-
const aliases = new Set();
|
|
470
|
-
const runtimeNames = new Set([
|
|
471
|
-
'runFork',
|
|
472
|
-
'runPromise',
|
|
473
|
-
'runPromiseExit',
|
|
474
|
-
'runSync',
|
|
475
|
-
'runSyncExit',
|
|
476
|
-
]);
|
|
477
|
-
const commentFreeSource = stripComments(source);
|
|
478
|
-
for (const match of commentFreeSource.matchAll(/(?:^|\n)\s*import\s*{([^}]+)}\s*from\s*['"]effect\/Effect['"]/g)) {
|
|
479
|
-
for (const specifier of match[1].split(',')) {
|
|
480
|
-
const names = importSpecifierNames(specifier);
|
|
481
|
-
const importedName = names?.importedName;
|
|
482
|
-
const localName = names?.localName;
|
|
483
|
-
if (importedName && localName && runtimeNames.has(importedName)) {
|
|
484
|
-
aliases.add(localName);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
return cacheAliases(runtimeFunctionAliasCache, source, [...aliases]);
|
|
489
|
-
}
|
|
490
|
-
function hasRuntimeCall(source) {
|
|
491
|
-
const cachedValue = cachedBoolean(runtimeCallCache, source);
|
|
492
|
-
if (cachedValue !== undefined) {
|
|
493
|
-
return cachedValue;
|
|
494
|
-
}
|
|
495
|
-
const code = stripCommentsAndStrings(source);
|
|
496
|
-
if (runtimeCallPattern.test(code)) {
|
|
497
|
-
return cacheBoolean(runtimeCallCache, source, true);
|
|
498
|
-
}
|
|
499
|
-
return cacheBoolean(runtimeCallCache, source, effectImportAliases(source).some((alias) => new RegExp(`\\b${alias}\\.(?:runPromise|runPromiseExit|runSync|runSyncExit|runFork)\\s*\\(`).test(code)) ||
|
|
500
|
-
effectRuntimeFunctionAliases(source).some((alias) => new RegExp(`\\b${alias}\\s*\\(`).test(code)));
|
|
501
|
-
}
|
|
502
|
-
function isBoundaryFile(filename) {
|
|
503
|
-
return Boolean(filename && boundaryFilePattern.test(filename));
|
|
504
|
-
}
|
|
505
|
-
function isTestFile(filename) {
|
|
506
|
-
return Boolean(filename && testFilePattern.test(filename));
|
|
507
|
-
}
|
|
508
|
-
export { hasEffectSignal, effectApiAliases, effectFunctionAliases, effectImportAliases, hasRuntimeCall, isBoundaryFile, isTestFile, makeRules, runtimeCallPattern, };
|
|
308
|
+
};
|
|
309
|
+
const makeProgramRule = (spec, options) => {
|
|
310
|
+
if (spec.ast) {
|
|
311
|
+
return makeASTCapableRule(spec, options);
|
|
312
|
+
}
|
|
313
|
+
return makeProgramOnlyRule(spec, options);
|
|
314
|
+
};
|
|
315
|
+
/**
|
|
316
|
+
* Internal helper exported for package-local composition.
|
|
317
|
+
*
|
|
318
|
+
* @internal
|
|
319
|
+
*/
|
|
320
|
+
export const makeRules = (specs, options = {}) => Object.fromEntries(specs.map((spec) => [spec.name, makeProgramRule(spec, options)]));
|
|
321
|
+
export { effectAPIAliases, effectFunctionAliases, effectImportAliases, hasEffectSignal, hasRuntimeCall, isBoundaryFile, isTestFile, runtimeCallPattern, } from './effect-rule-aliases.js';
|
|
509
322
|
//# sourceMappingURL=effect-rule-core.js.map
|