ai-deslop 0.2.0 → 0.2.2

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.
Files changed (97) hide show
  1. package/README.md +35 -106
  2. package/dist/index.d.ts +18 -0
  3. package/dist/index.js +84 -0
  4. package/dist/rules/no-array-filter-map.d.ts +2 -0
  5. package/dist/rules/no-array-filter-map.js +30 -0
  6. package/dist/rules/no-call-only-assertions.d.ts +2 -0
  7. package/dist/rules/no-call-only-assertions.js +87 -0
  8. package/dist/rules/no-chained-type-assertions.d.ts +2 -0
  9. package/dist/rules/no-chained-type-assertions.js +60 -0
  10. package/dist/rules/no-conditional-empty-object-spread.d.ts +2 -0
  11. package/dist/rules/no-conditional-empty-object-spread.js +40 -0
  12. package/dist/rules/no-duplicate-types.d.ts +2 -0
  13. package/dist/rules/no-duplicate-types.js +143 -0
  14. package/dist/rules/no-known-value-widening.d.ts +2 -0
  15. package/dist/rules/no-known-value-widening.js +300 -0
  16. package/dist/rules/no-module-mocking.d.ts +2 -0
  17. package/dist/rules/no-module-mocking.js +69 -0
  18. package/dist/rules/no-object-parameters.d.ts +2 -0
  19. package/dist/rules/no-object-parameters.js +56 -0
  20. package/dist/rules/no-pass-through-type-alias.d.ts +2 -0
  21. package/dist/rules/no-pass-through-type-alias.js +41 -0
  22. package/dist/rules/no-reduce-accumulator-copy.d.ts +2 -0
  23. package/dist/rules/no-reduce-accumulator-copy.js +99 -0
  24. package/dist/rules/no-reflect-apply.d.ts +2 -0
  25. package/dist/rules/no-reflect-apply.js +25 -0
  26. package/dist/rules/no-reflect-get.d.ts +2 -0
  27. package/dist/rules/no-reflect-get.js +25 -0
  28. package/dist/rules/no-runtime-typeof.d.ts +2 -0
  29. package/dist/rules/no-runtime-typeof.js +64 -0
  30. package/dist/rules/no-shape-in-symbol-names.d.ts +2 -0
  31. package/dist/rules/no-shape-in-symbol-names.js +40 -0
  32. package/dist/rules/no-unknown-parameters.d.ts +2 -0
  33. package/dist/rules/no-unknown-parameters.js +51 -0
  34. package/dist/rules/no-unknown-returns.d.ts +2 -0
  35. package/dist/rules/no-unknown-returns.js +58 -0
  36. package/dist/rules/no-unknown-type-aliases.d.ts +2 -0
  37. package/dist/rules/no-unknown-type-aliases.js +40 -0
  38. package/dist/rules/no-unsafe-dictionary-type.d.ts +2 -0
  39. package/dist/rules/no-unsafe-dictionary-type.js +134 -0
  40. package/dist/rules/no-widen-then-assert.d.ts +2 -0
  41. package/dist/rules/no-widen-then-assert.js +270 -0
  42. package/dist/rules/require-safety-comment-for-type-assertion.d.ts +2 -0
  43. package/dist/rules/require-safety-comment-for-type-assertion.js +100 -0
  44. package/dist/shared/array-method.d.ts +12 -0
  45. package/dist/shared/array-method.js +84 -0
  46. package/dist/shared/dictionary-types.d.ts +20 -0
  47. package/dist/shared/dictionary-types.js +377 -0
  48. package/dist/shared/function-parameters.d.ts +8 -0
  49. package/dist/shared/function-parameters.js +40 -0
  50. package/dist/shared/lexical-type-parameters.d.ts +5 -0
  51. package/dist/shared/lexical-type-parameters.js +47 -0
  52. package/dist/shared/reflect-method.d.ts +3 -0
  53. package/dist/shared/reflect-method.js +20 -0
  54. package/dist/shared/scope.d.ts +3 -0
  55. package/dist/shared/scope.js +11 -0
  56. package/dist/shared/type-alias-resolution.d.ts +23 -0
  57. package/dist/shared/type-alias-resolution.js +162 -0
  58. package/dist/tailwind/candidates.d.ts +14 -0
  59. package/dist/tailwind/candidates.js +24 -0
  60. package/dist/tailwind/design-system.d.ts +3 -0
  61. package/dist/tailwind/design-system.js +41 -0
  62. package/dist/tailwind/rule.d.ts +3 -0
  63. package/dist/tailwind/rule.js +133 -0
  64. package/dist/tailwind/worker.d.ts +1 -0
  65. package/dist/tailwind/worker.js +13 -0
  66. package/package.json +16 -5
  67. package/src/index.ts +0 -87
  68. package/src/rules/no-array-filter-map.ts +0 -28
  69. package/src/rules/no-call-only-assertions.ts +0 -94
  70. package/src/rules/no-chained-type-assertions.ts +0 -77
  71. package/src/rules/no-conditional-empty-object-spread.ts +0 -49
  72. package/src/rules/no-known-value-widening.ts +0 -415
  73. package/src/rules/no-module-mocking.ts +0 -80
  74. package/src/rules/no-object-parameters.ts +0 -83
  75. package/src/rules/no-pass-through-type-alias.ts +0 -52
  76. package/src/rules/no-reduce-accumulator-copy.ts +0 -109
  77. package/src/rules/no-reflect-apply.ts +0 -28
  78. package/src/rules/no-reflect-get.ts +0 -28
  79. package/src/rules/no-runtime-typeof.ts +0 -77
  80. package/src/rules/no-shape-in-symbol-names.ts +0 -46
  81. package/src/rules/no-unknown-parameters.ts +0 -69
  82. package/src/rules/no-unknown-returns.ts +0 -82
  83. package/src/rules/no-unknown-type-aliases.ts +0 -54
  84. package/src/rules/no-unsafe-dictionary-type.ts +0 -154
  85. package/src/rules/no-widen-then-assert.ts +0 -366
  86. package/src/rules/require-safety-comment-for-type-assertion.ts +0 -131
  87. package/src/shared/array-method.ts +0 -94
  88. package/src/shared/dictionary-types.ts +0 -515
  89. package/src/shared/function-parameters.ts +0 -49
  90. package/src/shared/lexical-type-parameters.ts +0 -61
  91. package/src/shared/reflect-method.ts +0 -24
  92. package/src/shared/scope.ts +0 -15
  93. package/src/shared/type-alias-resolution.ts +0 -250
  94. package/src/tailwind/candidates.ts +0 -38
  95. package/src/tailwind/design-system.ts +0 -59
  96. package/src/tailwind/rule.ts +0 -126
  97. package/src/tailwind/worker.ts +0 -38
@@ -0,0 +1,64 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ function isRuntimeFunction(node) {
3
+ return (node.type === "ArrowFunctionExpression" ||
4
+ node.type === "FunctionDeclaration" ||
5
+ node.type === "FunctionExpression");
6
+ }
7
+ function isInsideTypeGuard(node) {
8
+ let current = node.parent;
9
+ while (current !== null && current.type !== "Program") {
10
+ if (isRuntimeFunction(current)) {
11
+ return current.returnType?.typeAnnotation.type === "TSTypePredicate";
12
+ }
13
+ current = current.parent;
14
+ }
15
+ return false;
16
+ }
17
+ /** Return whether typeof safely probes for the existence of a possibly absent binding. */
18
+ function isExistenceProbe(node) {
19
+ const parent = node.parent;
20
+ if (parent.type !== "BinaryExpression")
21
+ return false;
22
+ if (!["===", "!==", "==", "!="].includes(parent.operator))
23
+ return false;
24
+ const other = parent.left === node ? parent.right : parent.left;
25
+ return other.type === "Literal" && other.value === "undefined";
26
+ }
27
+ /** Disallow runtime typeof checks that narrow unparsed values instead of decoding them. */
28
+ export const noRuntimeTypeofRule = defineRule({
29
+ meta: {
30
+ type: "problem",
31
+ docs: {
32
+ description: "Disallow runtime typeof checks; external values must be decoded into meaningful types at their I/O boundary.",
33
+ },
34
+ messages: {
35
+ runtimeTypeof: "A `typeof` check narrows a representation without establishing its contract. Parse input at its I/O boundary, then branch on the domain value.",
36
+ },
37
+ schema: [
38
+ {
39
+ type: "object",
40
+ properties: {
41
+ allowInTypeGuards: { type: "boolean" },
42
+ },
43
+ additionalProperties: false,
44
+ },
45
+ ],
46
+ defaultOptions: [{ allowInTypeGuards: false }],
47
+ },
48
+ createOnce(context) {
49
+ return {
50
+ UnaryExpression(node) {
51
+ const option = context.options?.[0];
52
+ const allowInTypeGuards = typeof option === "object" &&
53
+ option !== null &&
54
+ !Array.isArray(option) &&
55
+ option.allowInTypeGuards === true;
56
+ if (node.operator === "typeof" &&
57
+ !isExistenceProbe(node) &&
58
+ (!allowInTypeGuards || !isInsideTypeGuard(node))) {
59
+ context.report({ node, messageId: "runtimeTypeof" });
60
+ }
61
+ },
62
+ };
63
+ },
64
+ });
@@ -0,0 +1,2 @@
1
+ /** Ban the case-insensitive substring "shape" in every JavaScript and TypeScript symbol name. */
2
+ export declare const noForbiddenTermInSymbolNamesRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,40 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ const FORBIDDEN_SYMBOL_NAME = "shape";
3
+ function containsForbiddenSymbolName(name) {
4
+ return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
5
+ }
6
+ /** Return whether an identifier names a statically accessed member owned by another value. */
7
+ function isBorrowedMemberName(node) {
8
+ const parent = node.parent;
9
+ if (parent === null || parent.type !== "MemberExpression")
10
+ return false;
11
+ return parent.property === node && parent.computed === false;
12
+ }
13
+ /** Ban the case-insensitive substring "shape" in every JavaScript and TypeScript symbol name. */
14
+ export const noForbiddenTermInSymbolNamesRule = defineRule({
15
+ meta: {
16
+ type: "problem",
17
+ docs: {
18
+ description: 'Disallow the case-insensitive substring "shape" in JavaScript, TypeScript, private, and JSX symbol names.',
19
+ },
20
+ messages: {
21
+ forbiddenSymbolName: 'Rename symbol "{{name}}" for its domain role; "shape" describes structure rather than ownership.',
22
+ },
23
+ },
24
+ createOnce(context) {
25
+ const reportForbiddenSymbolName = (node) => {
26
+ if (!containsForbiddenSymbolName(node.name) || isBorrowedMemberName(node))
27
+ return;
28
+ context.report({
29
+ node,
30
+ messageId: "forbiddenSymbolName",
31
+ data: { name: node.name },
32
+ });
33
+ };
34
+ return {
35
+ Identifier: reportForbiddenSymbolName,
36
+ PrivateIdentifier: reportForbiddenSymbolName,
37
+ JSXIdentifier: reportForbiddenSymbolName,
38
+ };
39
+ },
40
+ });
@@ -0,0 +1,2 @@
1
+ /** Disallow unknown inputs except explicitly named error-cause enrichment. */
2
+ export declare const noUnknownParametersRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,51 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ import { containsUnknownType, functionParameterBindingName, functionParameterTypeAnnotation, } from "../shared/function-parameters.js";
3
+ function isTypePredicateSubject(owner, parameterName) {
4
+ const predicate = owner.returnType?.typeAnnotation;
5
+ return (predicate?.type === "TSTypePredicate" &&
6
+ predicate.parameterName.type === "Identifier" &&
7
+ predicate.parameterName.name === parameterName);
8
+ }
9
+ /** Disallow unknown inputs except explicitly named error-cause enrichment. */
10
+ export const noUnknownParametersRule = defineRule({
11
+ meta: {
12
+ type: "problem",
13
+ docs: {
14
+ description: "Disallow explicitly unknown function parameters except `cause` and type-predicate subjects; decode unknown input at its I/O boundary instead.",
15
+ },
16
+ messages: {
17
+ unknownParameter: "Parameter `{{parameter}}` leaves input unparsed. Accept a named domain type; run the expected schema or parser at the I/O boundary before calling this function.",
18
+ },
19
+ },
20
+ createOnce(context) {
21
+ const checkParameters = (node) => {
22
+ for (const parameter of node.params) {
23
+ const annotation = functionParameterTypeAnnotation(parameter);
24
+ if (annotation === null || annotation === undefined)
25
+ continue;
26
+ if (!containsUnknownType(annotation.typeAnnotation))
27
+ continue;
28
+ const name = functionParameterBindingName(parameter, context.sourceCode);
29
+ if (name === "cause" || isTypePredicateSubject(node, name))
30
+ continue;
31
+ context.report({
32
+ node: annotation.typeAnnotation,
33
+ messageId: "unknownParameter",
34
+ data: { parameter: name },
35
+ });
36
+ }
37
+ };
38
+ return {
39
+ ArrowFunctionExpression: checkParameters,
40
+ FunctionDeclaration: checkParameters,
41
+ FunctionExpression: checkParameters,
42
+ TSCallSignatureDeclaration: checkParameters,
43
+ TSConstructSignatureDeclaration: checkParameters,
44
+ TSConstructorType: checkParameters,
45
+ TSDeclareFunction: checkParameters,
46
+ TSEmptyBodyFunctionExpression: checkParameters,
47
+ TSFunctionType: checkParameters,
48
+ TSMethodSignature: checkParameters,
49
+ };
50
+ },
51
+ });
@@ -0,0 +1,2 @@
1
+ /** Ban function contracts that return unknown instead of a parsed domain type. */
2
+ export declare const noUnknownReturnsRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,58 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ import { createTypeAliasEnvironment, resolvedTypeMatches, } from "../shared/type-alias-resolution.js";
3
+ /** Ban function contracts that return unknown instead of a parsed domain type. */
4
+ export const noUnknownReturnsRule = defineRule({
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Disallow functions whose explicit return contract is unknown or Promise<unknown>.",
9
+ },
10
+ messages: {
11
+ unknownReturn: "This function exposes `unknown` to its caller. Parse the value at its boundary and return a named domain type.",
12
+ },
13
+ },
14
+ createOnce(context) {
15
+ let environment = null;
16
+ const resolvesToUnknown = (type) => environment !== null &&
17
+ resolvedTypeMatches(type, environment, (resolved, matches) => {
18
+ if (resolved.type === "TSUnknownKeyword")
19
+ return true;
20
+ if (resolved.type === "TSParenthesizedType") {
21
+ return matches(resolved.typeAnnotation);
22
+ }
23
+ if (resolved.type === "TSUnionType")
24
+ return resolved.types.some(matches);
25
+ if (resolved.type !== "TSTypeReference" ||
26
+ resolved.typeName.type !== "Identifier" ||
27
+ (resolved.typeName.name !== "Promise" &&
28
+ resolved.typeName.name !== "PromiseLike")) {
29
+ return false;
30
+ }
31
+ const value = resolved.typeArguments?.params[0];
32
+ return value !== undefined && matches(value);
33
+ });
34
+ const checkReturnType = (node) => {
35
+ const annotation = node.returnType;
36
+ if (annotation === null || annotation === undefined)
37
+ return;
38
+ if (!resolvesToUnknown(annotation.typeAnnotation))
39
+ return;
40
+ context.report({ node: annotation.typeAnnotation, messageId: "unknownReturn" });
41
+ };
42
+ return {
43
+ Program(node) {
44
+ environment = createTypeAliasEnvironment(node, context.sourceCode.visitorKeys);
45
+ },
46
+ ArrowFunctionExpression: checkReturnType,
47
+ FunctionDeclaration: checkReturnType,
48
+ FunctionExpression: checkReturnType,
49
+ TSCallSignatureDeclaration: checkReturnType,
50
+ TSConstructSignatureDeclaration: checkReturnType,
51
+ TSConstructorType: checkReturnType,
52
+ TSDeclareFunction: checkReturnType,
53
+ TSEmptyBodyFunctionExpression: checkReturnType,
54
+ TSFunctionType: checkReturnType,
55
+ TSMethodSignature: checkReturnType,
56
+ };
57
+ },
58
+ });
@@ -0,0 +1,2 @@
1
+ /** Ban named aliases that merely conceal TypeScript's unknown top type. */
2
+ export declare const noUnknownTypeAliasesRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,40 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ import { createTypeAliasEnvironment, resolvedTypeMatches, } from "../shared/type-alias-resolution.js";
3
+ /** Ban named aliases that merely conceal TypeScript's unknown top type. */
4
+ export const noUnknownTypeAliasesRule = defineRule({
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Disallow type aliases whose resolved type is unknown; unknown must remain visible at an allowed boundary.",
9
+ },
10
+ messages: {
11
+ unknownAlias: "Type alias `{{alias}}` hides `unknown`. Keep `unknown` explicit at the parsing boundary or on an allowed `cause` field; otherwise use the parsed owner type.",
12
+ },
13
+ },
14
+ createOnce(context) {
15
+ let environment = null;
16
+ const resolvesToUnknown = (type) => environment !== null &&
17
+ resolvedTypeMatches(type, environment, (resolved, matches) => {
18
+ if (resolved.type === "TSUnknownKeyword")
19
+ return true;
20
+ if (resolved.type === "TSParenthesizedType") {
21
+ return matches(resolved.typeAnnotation);
22
+ }
23
+ return resolved.type === "TSUnionType" && resolved.types.some(matches);
24
+ });
25
+ return {
26
+ Program(node) {
27
+ environment = createTypeAliasEnvironment(node, context.sourceCode.visitorKeys);
28
+ },
29
+ TSTypeAliasDeclaration(node) {
30
+ if (!resolvesToUnknown(node.typeAnnotation))
31
+ return;
32
+ context.report({
33
+ node: node.id,
34
+ messageId: "unknownAlias",
35
+ data: { alias: node.id.name },
36
+ });
37
+ },
38
+ };
39
+ },
40
+ });
@@ -0,0 +1,2 @@
1
+ /** Disallow object-dictionary contracts whose direct value type is an unsafe escape hatch. */
2
+ export declare const noUnsafeDictionaryTypeRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,134 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ import { classifyUnsafeDictionary, classifyUnsafeDictionaryValue, createTypeEnvironment, } from "../shared/dictionary-types.js";
3
+ import { visibleTypeAlias } from "../shared/type-alias-resolution.js";
4
+ const typeNodeKinds = new Set([
5
+ "JSDocNonNullableType",
6
+ "JSDocNullableType",
7
+ "JSDocUnknownType",
8
+ "TSAnyKeyword",
9
+ "TSArrayType",
10
+ "TSBigIntKeyword",
11
+ "TSBooleanKeyword",
12
+ "TSConditionalType",
13
+ "TSConstructorType",
14
+ "TSFunctionType",
15
+ "TSImportType",
16
+ "TSIndexedAccessType",
17
+ "TSInferType",
18
+ "TSIntersectionType",
19
+ "TSIntrinsicKeyword",
20
+ "TSLiteralType",
21
+ "TSMappedType",
22
+ "TSNamedTupleMember",
23
+ "TSNeverKeyword",
24
+ "TSNullKeyword",
25
+ "TSNumberKeyword",
26
+ "TSObjectKeyword",
27
+ "TSParenthesizedType",
28
+ "TSStringKeyword",
29
+ "TSSymbolKeyword",
30
+ "TSTemplateLiteralType",
31
+ "TSThisType",
32
+ "TSTupleType",
33
+ "TSTypeLiteral",
34
+ "TSTypeOperator",
35
+ "TSTypePredicate",
36
+ "TSTypeQuery",
37
+ "TSTypeReference",
38
+ "TSUndefinedKeyword",
39
+ "TSUnionType",
40
+ "TSUnknownKeyword",
41
+ "TSVoidKeyword",
42
+ ]);
43
+ function isTypeNode(node) {
44
+ return typeNodeKinds.has(node.type);
45
+ }
46
+ function typeReferenceName(type) {
47
+ return type.typeName.type === "Identifier" ? type.typeName.name : null;
48
+ }
49
+ function isInsideTypeAliasDeclaration(node) {
50
+ let current = node.parent;
51
+ while (current !== null && current.type !== "Program") {
52
+ if (current.type === "TSTypeAliasDeclaration")
53
+ return true;
54
+ current = current.parent;
55
+ }
56
+ return false;
57
+ }
58
+ function isPlainAliasConsumerUse(node, environment) {
59
+ if (node.type !== "TSTypeReference" || node.typeArguments?.params.length)
60
+ return false;
61
+ const name = typeReferenceName(node);
62
+ return (name !== null &&
63
+ visibleTypeAlias(name, node, environment.typeAliases) !== null &&
64
+ !isInsideTypeAliasDeclaration(node));
65
+ }
66
+ function isInsideTypeParameterConstraint(node) {
67
+ let child = node;
68
+ let parent = child.parent;
69
+ while (parent !== null && parent.type !== "Program") {
70
+ if (parent.type === "TSTypeParameter" && parent.constraint === child)
71
+ return true;
72
+ child = parent;
73
+ parent = child.parent;
74
+ }
75
+ return false;
76
+ }
77
+ function shouldReportType(node, environment) {
78
+ if (isInsideTypeParameterConstraint(node))
79
+ return false;
80
+ if (isPlainAliasConsumerUse(node, environment))
81
+ return false;
82
+ if (classifyUnsafeDictionary(node, environment) === null)
83
+ return false;
84
+ let current = node.parent;
85
+ while (current !== null && current.type !== "Program") {
86
+ if (isTypeNode(current) && classifyUnsafeDictionary(current, environment) !== null)
87
+ return false;
88
+ current = current.parent;
89
+ }
90
+ return true;
91
+ }
92
+ /** Disallow object-dictionary contracts whose direct value type is an unsafe escape hatch. */
93
+ export const noUnsafeDictionaryTypeRule = defineRule({
94
+ meta: {
95
+ type: "problem",
96
+ docs: {
97
+ description: "Disallow object-dictionary contracts whose direct value type is unknown, any, object, {}, or a union/alias containing one of those escape hatches.",
98
+ },
99
+ messages: {
100
+ unsafeDictionary: "This dictionary's {{value}} value type gives callers no concrete value contract. Use an owner/schema-derived value type; parse external payloads before insertion.",
101
+ },
102
+ },
103
+ createOnce(context) {
104
+ let environment = null;
105
+ const report = (node, value) => {
106
+ context.report({ node, messageId: "unsafeDictionary", data: { value } });
107
+ };
108
+ const reportIfUnsafe = (node) => {
109
+ if (environment === null || !shouldReportType(node, environment))
110
+ return;
111
+ const unsafe = classifyUnsafeDictionary(node, environment);
112
+ if (unsafe === null)
113
+ return;
114
+ report(node, unsafe.unsafeValue);
115
+ };
116
+ return {
117
+ Program(node) {
118
+ environment = createTypeEnvironment(node, context.sourceCode.visitorKeys);
119
+ },
120
+ TSTypeReference: reportIfUnsafe,
121
+ TSTypeLiteral: reportIfUnsafe,
122
+ TSMappedType: reportIfUnsafe,
123
+ TSIndexSignature(node) {
124
+ if (environment === null ||
125
+ node.typeAnnotation === null ||
126
+ node.parent.type === "TSTypeLiteral")
127
+ return;
128
+ const unsafe = classifyUnsafeDictionaryValue(node.typeAnnotation.typeAnnotation, environment);
129
+ if (unsafe !== null)
130
+ report(node, unsafe.unsafeValue);
131
+ },
132
+ };
133
+ },
134
+ });
@@ -0,0 +1,2 @@
1
+ /** Detect immutable local bindings that erase a known type and are later asserted back to a narrower type. */
2
+ export declare const noWidenThenAssertRule: import("@oxlint/plugins").Rule;