oxlint-plugin-effect 0.7.0 → 0.8.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/README.md +25 -0
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/plugin.d.ts +1 -1
- package/dist/presets/recommended.d.ts +16 -1
- package/dist/presets/recommended.js +17 -2
- package/dist/rules/_anti-slop-dictionary-types.js +243 -0
- package/dist/rules/index.d.ts +13 -2
- package/dist/rules/index.js +24 -2
- package/dist/rules/no-chained-type-assertions.d.ts +7 -0
- package/dist/rules/no-chained-type-assertions.js +60 -0
- package/dist/rules/no-conditional-empty-object-spread.d.ts +7 -0
- package/dist/rules/no-conditional-empty-object-spread.js +79 -0
- package/dist/rules/no-known-value-widening.d.ts +7 -0
- package/dist/rules/no-known-value-widening.js +144 -0
- package/dist/rules/no-object-parameters.d.ts +7 -0
- package/dist/rules/no-object-parameters.js +70 -0
- package/dist/rules/no-runtime-typeof.d.ts +7 -0
- package/dist/rules/no-runtime-typeof.js +24 -0
- package/dist/rules/no-shape-in-symbol-names.d.ts +7 -0
- package/dist/rules/no-shape-in-symbol-names.js +34 -0
- package/dist/rules/no-unknown-parameters.d.ts +7 -0
- package/dist/rules/no-unknown-parameters.js +55 -0
- package/dist/rules/no-unknown-type-aliases.d.ts +7 -0
- package/dist/rules/no-unknown-type-aliases.js +48 -0
- package/dist/rules/no-unsafe-dictionary-type.d.ts +7 -0
- package/dist/rules/no-unsafe-dictionary-type.js +75 -0
- package/dist/rules/no-widen-then-assert.d.ts +7 -0
- package/dist/rules/no-widen-then-assert.js +199 -0
- package/dist/rules/prefer-effect-fn.d.ts +6 -0
- package/dist/rules/prefer-effect-fn.js +31 -0
- package/dist/vendor/effect-oxlint/AST.d.ts +1 -1
- package/dist/vendor/effect-oxlint/AST.js +1 -1
- package/dist/vendor/effect-oxlint/Comment.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Comment.js +1 -1
- package/dist/vendor/effect-oxlint/Diagnostic.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Diagnostic.js +1 -1
- package/dist/vendor/effect-oxlint/Plugin.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Plugin.js +1 -1
- package/dist/vendor/effect-oxlint/Rule.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Rule.js +1 -1
- package/dist/vendor/effect-oxlint/RuleContext.d.ts +1 -7
- package/dist/vendor/effect-oxlint/Scope.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Scope.js +1 -1
- package/dist/vendor/effect-oxlint/SourceCode.d.ts +1 -1
- package/dist/vendor/effect-oxlint/SourceCode.js +1 -1
- package/dist/vendor/effect-oxlint/Testing.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Testing.js +1 -1
- package/dist/vendor/effect-oxlint/Token.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Token.js +1 -1
- package/dist/vendor/effect-oxlint/Visitor.d.ts +1 -1
- package/dist/vendor/effect-oxlint/Visitor.js +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { fromId } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
4
|
+
import "../vendor/effect-oxlint/index.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
//#region src/rules/no-widen-then-assert.ts
|
|
7
|
+
/**
|
|
8
|
+
* Ported from dmmulroy/anti-slop at
|
|
9
|
+
* b5d2288db1f00469a1d5f2e3b0e265e5a5676fd0.
|
|
10
|
+
*/
|
|
11
|
+
const functionBoundaryTypes = new Set([
|
|
12
|
+
"ArrowFunctionExpression",
|
|
13
|
+
"FunctionDeclaration",
|
|
14
|
+
"FunctionExpression",
|
|
15
|
+
"TSDeclareFunction",
|
|
16
|
+
"TSEmptyBodyFunctionExpression"
|
|
17
|
+
]);
|
|
18
|
+
function unwrapExpressionParentheses(expression) {
|
|
19
|
+
let current = expression;
|
|
20
|
+
while (current.type === "ParenthesizedExpression") current = current.expression;
|
|
21
|
+
return current;
|
|
22
|
+
}
|
|
23
|
+
function unwrapTypeParentheses(type) {
|
|
24
|
+
let current = type;
|
|
25
|
+
while (current.type === "TSParenthesizedType") current = current.typeAnnotation;
|
|
26
|
+
return current;
|
|
27
|
+
}
|
|
28
|
+
function typeReferenceName(type) {
|
|
29
|
+
return type.typeName.type === "Identifier" ? type.typeName.name : null;
|
|
30
|
+
}
|
|
31
|
+
function isUnknownOrAnyType(type) {
|
|
32
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
33
|
+
return unwrapped.type === "TSUnknownKeyword" || unwrapped.type === "TSAnyKeyword";
|
|
34
|
+
}
|
|
35
|
+
function isBroadRecordKeyType(type) {
|
|
36
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
37
|
+
if (unwrapped.type === "TSStringKeyword" || unwrapped.type === "TSNumberKeyword" || unwrapped.type === "TSSymbolKeyword") return true;
|
|
38
|
+
if (unwrapped.type === "TSUnionType") return unwrapped.types.every(isBroadRecordKeyType);
|
|
39
|
+
return unwrapped.type === "TSTypeReference" && typeReferenceName(unwrapped) === "PropertyKey";
|
|
40
|
+
}
|
|
41
|
+
function isBroadRecordType(type) {
|
|
42
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
43
|
+
if (unwrapped.type === "TSTypeReference") {
|
|
44
|
+
if (typeReferenceName(unwrapped) === "Readonly") {
|
|
45
|
+
const [inner] = unwrapped.typeArguments?.params ?? [];
|
|
46
|
+
return inner !== void 0 && isBroadRecordType(inner);
|
|
47
|
+
}
|
|
48
|
+
if (typeReferenceName(unwrapped) !== "Record") return false;
|
|
49
|
+
const parameters = unwrapped.typeArguments?.params ?? [];
|
|
50
|
+
return parameters.length === 2 && parameters[0] !== void 0 && parameters[1] !== void 0 && isBroadRecordKeyType(parameters[0]) && isUnknownOrAnyType(parameters[1]);
|
|
51
|
+
}
|
|
52
|
+
if (unwrapped.type !== "TSTypeLiteral" || unwrapped.members.length !== 1) return false;
|
|
53
|
+
const [member] = unwrapped.members;
|
|
54
|
+
const [parameter] = member?.type === "TSIndexSignature" ? member.parameters : [];
|
|
55
|
+
return member?.type === "TSIndexSignature" && member.parameters.length === 1 && parameter !== void 0 && isBroadRecordKeyType(parameter.typeAnnotation.typeAnnotation) && isUnknownOrAnyType(member.typeAnnotation.typeAnnotation);
|
|
56
|
+
}
|
|
57
|
+
function broadTypeKind(type) {
|
|
58
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
59
|
+
if (unwrapped.type === "TSUnknownKeyword" || unwrapped.type === "TSAnyKeyword") return "top";
|
|
60
|
+
if (unwrapped.type === "TSObjectKeyword") return "object";
|
|
61
|
+
return isBroadRecordType(unwrapped) ? "record" : null;
|
|
62
|
+
}
|
|
63
|
+
function assertedExpression(node) {
|
|
64
|
+
return unwrapExpressionParentheses(node.expression);
|
|
65
|
+
}
|
|
66
|
+
function assertionFromExpression(expression) {
|
|
67
|
+
const unwrapped = unwrapExpressionParentheses(expression);
|
|
68
|
+
return unwrapped.type === "TSAsExpression" || unwrapped.type === "TSTypeAssertion" ? unwrapped : null;
|
|
69
|
+
}
|
|
70
|
+
function normalizedTypeText(sourceText, type) {
|
|
71
|
+
return sourceText.slice(type.start, type.end).replaceAll(/\s+/gu, "");
|
|
72
|
+
}
|
|
73
|
+
function typesHaveSameSyntax(sourceText, left, right) {
|
|
74
|
+
return left !== null && normalizedTypeText(sourceText, unwrapTypeParentheses(left)) === normalizedTypeText(sourceText, unwrapTypeParentheses(right));
|
|
75
|
+
}
|
|
76
|
+
function isDefinitelyObjectType(type) {
|
|
77
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
78
|
+
switch (unwrapped.type) {
|
|
79
|
+
case "TSArrayType":
|
|
80
|
+
case "TSConstructorType":
|
|
81
|
+
case "TSFunctionType":
|
|
82
|
+
case "TSMappedType":
|
|
83
|
+
case "TSObjectKeyword":
|
|
84
|
+
case "TSTupleType": return true;
|
|
85
|
+
case "TSTypeLiteral": return unwrapped.members.length > 0;
|
|
86
|
+
case "TSIntersectionType": return unwrapped.types.every(isDefinitelyObjectType);
|
|
87
|
+
case "TSTypeOperator": return unwrapped.operator === "readonly" && isDefinitelyObjectType(unwrapped.typeAnnotation);
|
|
88
|
+
default: return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function isDefinitelyNarrowerRecordType(type) {
|
|
92
|
+
const unwrapped = unwrapTypeParentheses(type);
|
|
93
|
+
if (unwrapped.type === "TSTypeLiteral") return unwrapped.members.some((member) => member.type !== "TSIndexSignature");
|
|
94
|
+
if (unwrapped.type !== "TSTypeReference") return false;
|
|
95
|
+
if (typeReferenceName(unwrapped) === "Readonly") {
|
|
96
|
+
const [inner] = unwrapped.typeArguments?.params ?? [];
|
|
97
|
+
return inner !== void 0 && isDefinitelyNarrowerRecordType(inner);
|
|
98
|
+
}
|
|
99
|
+
if (typeReferenceName(unwrapped) !== "Record") return false;
|
|
100
|
+
const parameters = unwrapped.typeArguments?.params ?? [];
|
|
101
|
+
return parameters.length === 2 && parameters[1] !== void 0 && !isUnknownOrAnyType(parameters[1]);
|
|
102
|
+
}
|
|
103
|
+
function functionBoundary(node) {
|
|
104
|
+
let current = node.parent;
|
|
105
|
+
while (current !== null && current.type !== "Program") {
|
|
106
|
+
if (functionBoundaryTypes.has(current.type)) return current;
|
|
107
|
+
current = current.parent;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
function resolvedVariableForIdentifier(scopes, identifier) {
|
|
112
|
+
for (const scope of scopes) {
|
|
113
|
+
const reference = scope.references.find((candidate) => candidate.identifier.start === identifier.start && candidate.identifier.end === identifier.end);
|
|
114
|
+
if (reference !== void 0) return reference.resolved;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
function variableDeclarator(variable) {
|
|
119
|
+
for (const definition of variable.defs) if (definition.type === "Variable" && definition.node.type === "VariableDeclarator") return definition.node;
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
function knownValueEvidence(expression, scopes, boundary, visitedVariables) {
|
|
123
|
+
const unwrapped = unwrapExpressionParentheses(expression);
|
|
124
|
+
if (unwrapped.type === "TSAsExpression" || unwrapped.type === "TSTypeAssertion") {
|
|
125
|
+
if (broadTypeKind(unwrapped.typeAnnotation) !== null) return null;
|
|
126
|
+
return { type: unwrapped.typeAnnotation };
|
|
127
|
+
}
|
|
128
|
+
if (unwrapped.type === "Literal" || unwrapped.type === "TemplateLiteral") return { type: null };
|
|
129
|
+
if (unwrapped.type === "ArrayExpression" || unwrapped.type === "ArrowFunctionExpression" || unwrapped.type === "ClassExpression" || unwrapped.type === "FunctionExpression" || unwrapped.type === "NewExpression" || unwrapped.type === "ObjectExpression") return { type: null };
|
|
130
|
+
if (unwrapped.type !== "Identifier") return null;
|
|
131
|
+
const variable = resolvedVariableForIdentifier(scopes, unwrapped);
|
|
132
|
+
if (variable === null || visitedVariables.has(variable)) return null;
|
|
133
|
+
const annotatedIdentifier = variable.identifiers.find((identifier) => identifier.typeAnnotation !== null && identifier.typeAnnotation !== void 0);
|
|
134
|
+
const annotation = annotatedIdentifier?.typeAnnotation?.typeAnnotation;
|
|
135
|
+
if (annotation !== void 0 && annotatedIdentifier !== void 0) {
|
|
136
|
+
if (functionBoundary(annotatedIdentifier) !== boundary || broadTypeKind(annotation) !== null) return null;
|
|
137
|
+
return { type: annotation };
|
|
138
|
+
}
|
|
139
|
+
const declarator = variableDeclarator(variable);
|
|
140
|
+
if (declarator === null || declarator.parent.type !== "VariableDeclaration" || declarator.parent.kind !== "const" || declarator.init === null || variable.references.some((reference) => reference.isWrite() && !reference.init) || functionBoundary(declarator) !== boundary) return null;
|
|
141
|
+
return knownValueEvidence(declarator.init, scopes, boundary, new Set([...visitedVariables, variable]));
|
|
142
|
+
}
|
|
143
|
+
function widenedBinding(variable, scopes) {
|
|
144
|
+
const declarator = variableDeclarator(variable);
|
|
145
|
+
if (declarator === null || declarator.parent.type !== "VariableDeclaration" || declarator.parent.kind !== "const" || declarator.id.type !== "Identifier" || declarator.init === null || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
146
|
+
const identifier = variable.identifiers.find((candidate) => candidate.start === declarator.id.start && candidate.end === declarator.id.end);
|
|
147
|
+
const boundary = functionBoundary(declarator);
|
|
148
|
+
const declaredType = identifier?.typeAnnotation?.typeAnnotation;
|
|
149
|
+
const initializerAssertion = assertionFromExpression(declarator.init);
|
|
150
|
+
const initializerBroadKind = initializerAssertion === null ? null : broadTypeKind(initializerAssertion.typeAnnotation);
|
|
151
|
+
const broadKind = (declaredType === void 0 ? null : broadTypeKind(declaredType)) ?? initializerBroadKind;
|
|
152
|
+
if (broadKind === null) return null;
|
|
153
|
+
const evidence = knownValueEvidence(initializerAssertion !== null && initializerBroadKind !== null ? assertedExpression(initializerAssertion) : declarator.init, scopes, boundary, new Set([variable]));
|
|
154
|
+
return evidence === null ? null : {
|
|
155
|
+
broadKind,
|
|
156
|
+
evidence,
|
|
157
|
+
declaredAt: declarator.end,
|
|
158
|
+
boundary
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
|
|
162
|
+
if (broadTypeKind(assertedType) !== null) return false;
|
|
163
|
+
if (broadKind === "top") return true;
|
|
164
|
+
if (typesHaveSameSyntax(sourceText, evidence.type, assertedType)) return true;
|
|
165
|
+
if (broadKind === "object") return isDefinitelyObjectType(assertedType);
|
|
166
|
+
return isDefinitelyNarrowerRecordType(assertedType);
|
|
167
|
+
}
|
|
168
|
+
/** Detect immutable local bindings that erase a known type and are later asserted back to a narrower type. */
|
|
169
|
+
const noWidenThenAssert = define({
|
|
170
|
+
name: "no-widen-then-assert",
|
|
171
|
+
meta: meta({
|
|
172
|
+
type: "problem",
|
|
173
|
+
description: "Disallow local const flows that explicitly widen a known value before asserting the widened binding to a narrower type.",
|
|
174
|
+
messages: { widenThenAssert: "Binding \"{{name}}\" erases established type evidence by widening the value, then reconstructs that evidence with a type assertion. Preserve the precise type end-to-end; if the input is genuinely unknown, parse it once at the boundary instead." }
|
|
175
|
+
}),
|
|
176
|
+
create: function* () {
|
|
177
|
+
const context = yield* RuleContext;
|
|
178
|
+
const scopes = context.sourceCode.scopeManager.scopes;
|
|
179
|
+
const checkAssertion = (node) => {
|
|
180
|
+
const expression = assertedExpression(node);
|
|
181
|
+
if (expression.type !== "Identifier") return Effect.void;
|
|
182
|
+
const variable = resolvedVariableForIdentifier(scopes, expression);
|
|
183
|
+
if (variable === null) return Effect.void;
|
|
184
|
+
const widened = widenedBinding(variable, scopes);
|
|
185
|
+
if (widened === null || node.start <= widened.declaredAt || functionBoundary(node) !== widened.boundary || !assertionIsNarrower(context.sourceCode.text, widened.broadKind, widened.evidence, node.typeAnnotation)) return Effect.void;
|
|
186
|
+
return context.report(fromId({
|
|
187
|
+
node,
|
|
188
|
+
messageId: "widenThenAssert",
|
|
189
|
+
data: { name: expression.name }
|
|
190
|
+
}));
|
|
191
|
+
};
|
|
192
|
+
return {
|
|
193
|
+
TSAsExpression: checkAssertion,
|
|
194
|
+
TSTypeAssertion: checkAssertion
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
//#endregion
|
|
199
|
+
export { noWidenThenAssert };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
4
|
+
import "../vendor/effect-oxlint/index.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
//#region src/rules/prefer-effect-fn.ts
|
|
7
|
+
const isStaticMember = (node, object, property) => node.type === "MemberExpression" && !node.computed && node.object.type === "Identifier" && node.object.name === object && node.property.type === "Identifier" && node.property.name === property;
|
|
8
|
+
const isEffectGenCall = (node) => node.type === "CallExpression" && node.callee.type !== "Super" && isStaticMember(node.callee, "Effect", "gen");
|
|
9
|
+
const isEffectWithSpanCall = (node) => node.type === "CallExpression" && node.callee.type !== "Super" && isStaticMember(node.callee, "Effect", "withSpan");
|
|
10
|
+
const spansEffectGenDirectly = (node) => node.callee.type !== "Super" && node.callee.type === "MemberExpression" && !node.callee.computed && node.callee.property.type === "Identifier" && node.callee.property.name === "withSpan" && isEffectGenCall(node.callee.object);
|
|
11
|
+
const pipesOnlyWithSpanFromEffectGen = (node) => node.callee.type !== "Super" && node.callee.type === "MemberExpression" && !node.callee.computed && node.callee.property.type === "Identifier" && node.callee.property.name === "pipe" && isEffectGenCall(node.callee.object) && node.arguments.length === 1 && node.arguments[0] !== void 0 && isEffectWithSpanCall(node.arguments[0]);
|
|
12
|
+
const preferEffectFn = define({
|
|
13
|
+
name: "prefer-effect-fn",
|
|
14
|
+
meta: meta({
|
|
15
|
+
type: "suggestion",
|
|
16
|
+
description: "Use Effect.fn for a named generator operation."
|
|
17
|
+
}),
|
|
18
|
+
create: function* () {
|
|
19
|
+
const ctx = yield* RuleContext;
|
|
20
|
+
return { CallExpression: (node) => {
|
|
21
|
+
if (node.type !== "CallExpression") return Effect.void;
|
|
22
|
+
if (!spansEffectGenDirectly(node) && !pipesOnlyWithSpanFromEffectGen(node)) return Effect.void;
|
|
23
|
+
return ctx.report(make({
|
|
24
|
+
node,
|
|
25
|
+
message: "Avoid a span on Effect.gen. Define the named operation with Effect.fn."
|
|
26
|
+
}));
|
|
27
|
+
} };
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
//#endregion
|
|
31
|
+
export { preferEffectFn };
|
|
@@ -196,4 +196,4 @@ declare const hasAncestor: {
|
|
|
196
196
|
}, type: string): boolean;
|
|
197
197
|
};
|
|
198
198
|
//#endregion
|
|
199
|
-
export { AST_d_exports
|
|
199
|
+
export { AST_d_exports };
|
|
@@ -211,4 +211,4 @@ const findAncestor = dual(2, (node, type) => {
|
|
|
211
211
|
*/
|
|
212
212
|
const hasAncestor = dual(2, (node, type) => Option.isSome(findAncestor(node, type)));
|
|
213
213
|
//#endregion
|
|
214
|
-
export { AST_exports, calleeName,
|
|
214
|
+
export { AST_exports, calleeName, importSource, matchImport, matchMember, memberNames, narrow };
|
|
@@ -52,4 +52,4 @@ declare const isDisableDirective: (comment: Comment) => boolean;
|
|
|
52
52
|
*/
|
|
53
53
|
declare const isEnableDirective: (comment: Comment) => boolean;
|
|
54
54
|
//#endregion
|
|
55
|
-
export { Comment_d_exports
|
|
55
|
+
export { Comment_d_exports };
|
|
@@ -64,4 +64,4 @@ const isEnableDirective = (comment) => {
|
|
|
64
64
|
return Str.startsWith("eslint-enable")(trimmed) || Str.startsWith("oxlint-enable")(trimmed);
|
|
65
65
|
};
|
|
66
66
|
//#endregion
|
|
67
|
-
export { Comment_exports
|
|
67
|
+
export { Comment_exports };
|
|
@@ -83,4 +83,4 @@ declare const removeFix: (nodeOrToken: Ranged) => FixFn;
|
|
|
83
83
|
*/
|
|
84
84
|
declare const composeFixes: (...fixes: ReadonlyArray<FixFn>) => FixFn;
|
|
85
85
|
//#endregion
|
|
86
|
-
export {
|
|
86
|
+
export { Diagnostic_d_exports };
|
|
@@ -112,4 +112,4 @@ const extractFixes = (result) => {
|
|
|
112
112
|
*/
|
|
113
113
|
const composeFixes = (...fixes) => (fixer) => Arr.flatMap(fixes, (fn) => Array.from(extractFixes(fn(fixer))));
|
|
114
114
|
//#endregion
|
|
115
|
-
export { Diagnostic_exports,
|
|
115
|
+
export { Diagnostic_exports, fromId, make, replaceText, withFix };
|
|
@@ -215,4 +215,4 @@ declare const banMultiple: (config: {
|
|
|
215
215
|
readonly specs: ReadonlyArray<BanSpec>;
|
|
216
216
|
}) => CreateRule;
|
|
217
217
|
//#endregion
|
|
218
|
-
export {
|
|
218
|
+
export { Rule_d_exports };
|
|
@@ -22,12 +22,6 @@ declare const RuleContext_base: Context$1.ServiceClass<RuleContext, "oxlint-plug
|
|
|
22
22
|
* @since 0.1.0
|
|
23
23
|
*/
|
|
24
24
|
declare class RuleContext extends RuleContext_base {}
|
|
25
|
-
/**
|
|
26
|
-
* Build a `RuleContext` value from the raw oxlint `Context`.
|
|
27
|
-
*
|
|
28
|
-
* @internal
|
|
29
|
-
*/
|
|
30
|
-
declare const fromOxlintContext: (ctx: Context) => RuleContext["Service"];
|
|
31
25
|
/**
|
|
32
26
|
* Effectful access to the rule ID.
|
|
33
27
|
*
|
|
@@ -74,4 +68,4 @@ declare const ast: Effect.Effect<ESTree.Program, never, RuleContext>;
|
|
|
74
68
|
*/
|
|
75
69
|
declare const report: (diagnostic: Diagnostic) => Effect.Effect<void, never, RuleContext>;
|
|
76
70
|
//#endregion
|
|
77
|
-
export { RuleContext, ast, cwd, filename,
|
|
71
|
+
export { RuleContext, ast, cwd, filename, id, report, sourceCode, text };
|
|
@@ -97,4 +97,4 @@ declare const throughReferences: (scope: Scope) => ReadonlyArray<Reference>;
|
|
|
97
97
|
*/
|
|
98
98
|
declare const isStrict: (scope: Scope) => boolean;
|
|
99
99
|
//#endregion
|
|
100
|
-
export { Scope_d_exports
|
|
100
|
+
export { Scope_d_exports };
|
|
@@ -107,4 +107,4 @@ const throughReferences = (scope) => scope.through;
|
|
|
107
107
|
*/
|
|
108
108
|
const isStrict = (scope) => scope.isStrict;
|
|
109
109
|
//#endregion
|
|
110
|
-
export { Scope_exports,
|
|
110
|
+
export { Scope_exports, findVariableUp };
|
|
@@ -177,4 +177,4 @@ declare const isSpaceBetween: (first: ESTree.Node | Token | Comment, second: EST
|
|
|
177
177
|
*/
|
|
178
178
|
declare const getLines: () => Effect.Effect<ReadonlyArray<string>, never, RuleContext>;
|
|
179
179
|
//#endregion
|
|
180
|
-
export { SourceCode_d_exports
|
|
180
|
+
export { SourceCode_d_exports };
|
|
@@ -200,4 +200,4 @@ const isSpaceBetween = (first, second) => withSourceCode((sc) => sc.isSpaceBetwe
|
|
|
200
200
|
*/
|
|
201
201
|
const getLines = () => withSourceCode((sc) => sc.getLines());
|
|
202
202
|
//#endregion
|
|
203
|
-
export { SourceCode_exports,
|
|
203
|
+
export { SourceCode_exports, isGlobalReference };
|
|
@@ -507,4 +507,4 @@ declare const expectDiagnostics: (result: ReadonlyArray<ReportedDiagnostic>, exp
|
|
|
507
507
|
*/
|
|
508
508
|
declare const expectNoDiagnostics: (result: ReadonlyArray<ReportedDiagnostic>) => void;
|
|
509
509
|
//#endregion
|
|
510
|
-
export {
|
|
510
|
+
export { Testing_d_exports };
|
|
@@ -963,4 +963,4 @@ const expectNoDiagnostics = (result) => Arr.match(result, {
|
|
|
963
963
|
}
|
|
964
964
|
});
|
|
965
965
|
//#endregion
|
|
966
|
-
export { Testing_exports
|
|
966
|
+
export { Testing_exports };
|
|
@@ -95,4 +95,4 @@ declare const value: (token: Token) => string;
|
|
|
95
95
|
*/
|
|
96
96
|
declare const type: (token: Token) => string;
|
|
97
97
|
//#endregion
|
|
98
|
-
export { Token_d_exports
|
|
98
|
+
export { Token_d_exports };
|
|
@@ -100,4 +100,4 @@ const value = (token) => token.value;
|
|
|
100
100
|
*/
|
|
101
101
|
const type = (token) => token.type;
|
|
102
102
|
//#endregion
|
|
103
|
-
export { Token_exports
|
|
103
|
+
export { Token_exports };
|
|
@@ -163,4 +163,4 @@ declare const accumulate: <A>(nodeType: string, extract: (node: ESTree.Node) =>
|
|
|
163
163
|
*/
|
|
164
164
|
declare const toOxlintVisitor: (effectVisitor: EffectVisitor, runHandler: (effect: Effect.Effect<void, never, RuleContext>) => void) => Visitor;
|
|
165
165
|
//#endregion
|
|
166
|
-
export {
|
|
166
|
+
export { EffectVisitor, Visitor_d_exports };
|
|
@@ -135,4 +135,4 @@ const accumulate = (nodeType, extract, analyze) => Effect.gen(function* () {
|
|
|
135
135
|
*/
|
|
136
136
|
const toOxlintVisitor = (effectVisitor, runHandler) => R.map(effectVisitor, (handler) => (node) => runHandler(handler(node)));
|
|
137
137
|
//#endregion
|
|
138
|
-
export { Visitor_exports,
|
|
138
|
+
export { Visitor_exports, merge, toOxlintVisitor };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxlint-plugin-effect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "oxlint plugin with Effect-specific lint rules",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"url": "https://github.com/cevr/effect-oxlint"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
|
-
"dist"
|
|
11
|
+
"dist",
|
|
12
|
+
"THIRD_PARTY_NOTICES.md"
|
|
12
13
|
],
|
|
13
14
|
"type": "module",
|
|
14
15
|
"exports": {
|
|
@@ -48,8 +49,9 @@
|
|
|
48
49
|
"fmt": "oxfmt",
|
|
49
50
|
"fmt:check": "oxfmt --check",
|
|
50
51
|
"test": "bun run build && bun test",
|
|
51
|
-
"gate": "concurrently -n type,style,test -c blue,yellow,green \"bun run typecheck\" \"bun run lint\" \"bun run test\"",
|
|
52
|
+
"gate": "concurrently -n type,style,generated,test -c blue,yellow,magenta,green \"bun run typecheck\" \"bun run lint\" \"bun run codegen:check\" \"bun run test\"",
|
|
52
53
|
"codegen": "bun run scripts/codegen.ts",
|
|
54
|
+
"codegen:check": "bun run scripts/codegen.ts --check",
|
|
53
55
|
"add-rule": "bun run scripts/add-rule.ts",
|
|
54
56
|
"version": "changeset version",
|
|
55
57
|
"release": "bun run build && changeset publish",
|