eslint-plugin-complete 1.12.2 → 1.12.3

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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-complete",
3
- "version": "1.12.2",
3
+ "version": "1.12.3",
4
4
  "description": "An ESLint plugin that contains useful rules.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -44,7 +44,8 @@
44
44
  "dependencies": {
45
45
  "@typescript-eslint/type-utils": "catalog:",
46
46
  "@typescript-eslint/utils": "catalog:",
47
- "is-immutable-type": "catalog:"
47
+ "is-immutable-type": "catalog:",
48
+ "ts-api-utils": "catalog:"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@babel/core": "catalog:",
@@ -1,8 +1,5 @@
1
1
  import type { ImmutabilityCache, ImmutabilityOverrides } from "is-immutable-type";
2
2
  import ts from "typescript";
3
- /**
4
- * TODO: Remove this workaround after https://github.com/RebeccaStevens/is-immutable-type/pull/637
5
- * is released.
6
- */
7
- export declare function isImmutableTypeWithPrimitiveIntersectionPatch(program: ts.Program, type: ts.Type, overrides: ImmutabilityOverrides, cache: ImmutabilityCache): boolean;
3
+ /** TODO: Open a PR for this once the other PR is accepted. */
4
+ export declare function isImmutableTypeWithPatches(program: ts.Program, type: ts.Type, overrides: ImmutabilityOverrides, cache: ImmutabilityCache): boolean;
8
5
  //# sourceMappingURL=patch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/patch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,6CAA6C,CAC3D,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAGT"}
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/patch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,8DAA8D;AAC9D,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAGT"}
package/dist/src/patch.js CHANGED
@@ -1,15 +1,12 @@
1
1
  import { getTypeOfPropertyOfType } from "@typescript-eslint/type-utils";
2
2
  import { Immutability, isImmutableType } from "is-immutable-type";
3
3
  import ts from "typescript";
4
- /**
5
- * TODO: Remove this workaround after https://github.com/RebeccaStevens/is-immutable-type/pull/637
6
- * is released.
7
- */
8
- export function isImmutableTypeWithPrimitiveIntersectionPatch(program, type, overrides, cache) {
9
- cacheImmutablePrimitiveIntersections(program, type, overrides, cache);
4
+ /** TODO: Open a PR for this once the other PR is accepted. */
5
+ export function isImmutableTypeWithPatches(program, type, overrides, cache) {
6
+ cachePatchedImmutableTypes(program, type, overrides, cache);
10
7
  return isImmutableType(program, type, overrides, cache);
11
8
  }
12
- function cacheImmutablePrimitiveIntersections(program, type, overrides, cache) {
9
+ function cachePatchedImmutableTypes(program, type, overrides, cache) {
13
10
  const checker = program.getTypeChecker();
14
11
  const seenTypes = new Set();
15
12
  function visitType(typeToVisit) {
@@ -17,15 +14,34 @@ function cacheImmutablePrimitiveIntersections(program, type, overrides, cache) {
17
14
  return;
18
15
  }
19
16
  seenTypes.add(typeToVisit);
17
+ // The ReadonlyArray override does not match tuples reached through the type checker.
18
+ if (isTupleType(checker, typeToVisit)) {
19
+ const typeArguments = checker.getTypeArguments(typeToVisit);
20
+ for (const typeArgument of typeArguments) {
21
+ visitType(typeArgument);
22
+ }
23
+ if (typeToVisit.target.readonly) {
24
+ const isImmutable = typeArguments.every((typeArgument) => isImmutableType(program, typeArgument, overrides, cache));
25
+ const genericAlias = getGenericTupleAlias(typeToVisit);
26
+ if (!isImmutable && genericAlias !== undefined) {
27
+ cache.set(genericAlias, Immutability.ReadonlyDeep);
28
+ }
29
+ else if (isImmutable) {
30
+ const cacheKey = getTupleCacheKey(typeToVisit);
31
+ if (cacheKey !== undefined) {
32
+ cache.set(cacheKey, Immutability.Immutable);
33
+ }
34
+ }
35
+ return;
36
+ }
37
+ }
20
38
  if (typeToVisit.isIntersection()) {
21
39
  for (const childType of typeToVisit.types) {
22
40
  if (!isPrimitiveType(childType)) {
23
41
  visitType(childType);
24
42
  }
25
43
  }
26
- if (typeToVisit.types.some((childType) => isPrimitiveType(childType))
27
- && typeToVisit.types.every((childType) => isPrimitiveType(childType)
28
- || isImmutableType(program, childType, overrides, cache))) {
44
+ if (isImmutablePrimitiveIntersection(program, typeToVisit, overrides, cache)) {
29
45
  cache.set(typeToVisit, Immutability.Immutable);
30
46
  return;
31
47
  }
@@ -55,10 +71,36 @@ function cacheImmutablePrimitiveIntersections(program, type, overrides, cache) {
55
71
  }
56
72
  visitType(type);
57
73
  }
74
+ function isTupleType(checker, type) {
75
+ return checker.isTupleType(type);
76
+ }
77
+ function getTupleCacheKey(type) {
78
+ if (getGenericTupleAlias(type) !== undefined) {
79
+ return undefined;
80
+ }
81
+ return type.node ?? type.target;
82
+ }
83
+ function getGenericTupleAlias(type) {
84
+ const node = type.node;
85
+ return node !== undefined
86
+ && ts.isTypeAliasDeclaration(node)
87
+ && node.typeParameters !== undefined
88
+ ? node
89
+ : undefined;
90
+ }
58
91
  function isTypeReference(type) {
59
92
  return ((type.flags & ts.TypeFlags.Object) !== 0
60
93
  && (type.objectFlags & ts.ObjectFlags.Reference) !== 0);
61
94
  }
95
+ /**
96
+ * TODO: Remove this workaround after https://github.com/RebeccaStevens/is-immutable-type/pull/637
97
+ * is released.
98
+ */
99
+ function isImmutablePrimitiveIntersection(program, type, overrides, cache) {
100
+ return (type.types.some((childType) => isPrimitiveType(childType))
101
+ && type.types.every((childType) => isPrimitiveType(childType)
102
+ || isImmutableType(program, childType, overrides, cache)));
103
+ }
62
104
  function isPrimitiveType(type) {
63
105
  const primitiveFlags = ts.TypeFlags.StringLike
64
106
  | ts.TypeFlags.NumberLike
@@ -1 +1 @@
1
- {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../../src/patch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../../src/patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAKxE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,8DAA8D;AAC9D,MAAM,UAAU,0BAA0B,CACxC,OAAmB,EACnB,IAAa,EACb,SAAgC,EAChC,KAAwB;IAExB,0BAA0B,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5D,OAAO,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,0BAA0B,CACjC,OAAmB,EACnB,IAAa,EACb,SAAgC,EAChC,KAAwB;IAExB,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAW,CAAC;IAErC,SAAS,SAAS,CAAC,WAAoB;QACrC,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE3B,qFAAqF;QACrF,IAAI,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YACtC,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAC5D,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;gBACzC,SAAS,CAAC,YAAY,CAAC,CAAC;YAC1B,CAAC;YAED,IAAI,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAChC,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,EAAE,CACvD,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,CACzD,CAAC;gBACF,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;gBAEvD,IAAI,CAAC,WAAW,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;oBAC/C,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;gBACrD,CAAC;qBAAM,IAAI,WAAW,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;oBAC/C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;wBAC3B,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;gBACD,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,CAAC;YACjC,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBAC1C,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChC,SAAS,CAAC,SAAS,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;YAED,IACE,gCAAgC,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,EACxE,CAAC;gBACD,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC/C,OAAO;YACT,CAAC;QACH,CAAC;aAAM,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACjC,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBAC1C,SAAS,CAAC,SAAS,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,IAAI,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;YACjC,KAAK,MAAM,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,EAAE,CAAC;gBACjE,SAAS,CAAC,YAAY,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE,CAAC;YACnD,MAAM,YAAY,GAAG,uBAAuB,CAC1C,OAAO,EACP,WAAW,EACX,QAAQ,CACT,CAAC;YACF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC/B,SAAS,CAAC,YAAY,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YACrE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAClB,OAAuB,EACvB,IAAa;IAEb,OAAO,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,gBAAgB,CACvB,IAA2B;IAE3B,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC;AAClC,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAA2B;IAE3B,MAAM,IAAI,GAAwB,IAAI,CAAC,IAAI,CAAC;IAE5C,OAAO,IAAI,KAAK,SAAS;WACpB,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC;WAC/B,IAAI,CAAC,cAAc,KAAK,SAAS;QACpC,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IACpC,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;WACrC,CAAE,IAAsB,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAC1E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,gCAAgC,CACvC,OAAmB,EACnB,IAAyB,EACzB,SAAgC,EAChC,KAAwB;IAExB,OAAO,CACL,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;WACvD,IAAI,CAAC,KAAK,CAAC,KAAK,CACjB,CAAC,SAAS,EAAE,EAAE,CACZ,eAAe,CAAC,SAAS,CAAC;eACvB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAC3D,CACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IACpC,MAAM,cAAc,GAClB,EAAE,CAAC,SAAS,CAAC,UAAU;UACrB,EAAE,CAAC,SAAS,CAAC,UAAU;UACvB,EAAE,CAAC,SAAS,CAAC,UAAU;UACvB,EAAE,CAAC,SAAS,CAAC,WAAW;UACxB,EAAE,CAAC,SAAS,CAAC,YAAY;UACzB,EAAE,CAAC,SAAS,CAAC,QAAQ;UACrB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;IAEtB,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"type-declaration-immutability.d.ts","sourceRoot":"","sources":["../../../src/rules/type-declaration-immutability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAqCvD,eAAO,MAAM,2BAA2B;;CA0CtC,CAAC"}
1
+ {"version":3,"file":"type-declaration-immutability.d.ts","sourceRoot":"","sources":["../../../src/rules/type-declaration-immutability.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAuCvD,eAAO,MAAM,2BAA2B;;CA2GtC,CAAC"}
@@ -1,6 +1,9 @@
1
+ import { getTypeOfPropertyOfType } from "@typescript-eslint/type-utils";
1
2
  import { ESLintUtils } from "@typescript-eslint/utils";
2
3
  import { getDefaultOverrides, Immutability } from "is-immutable-type";
3
- import { isImmutableTypeWithPrimitiveIntersectionPatch } from "../patch.js";
4
+ import { isPropertyReadonlyInType } from "ts-api-utils";
5
+ import ts from "typescript";
6
+ import { isImmutableTypeWithPatches } from "../patch.js";
4
7
  import { createRule } from "../utils.js";
5
8
  const IMMUTABILITY_OVERRIDES = [
6
9
  ...getDefaultOverrides(),
@@ -40,7 +43,7 @@ export const typeDeclarationImmutability = createRule({
40
43
  },
41
44
  schema: [],
42
45
  messages: {
43
- mustBeImmutable: "Interfaces must be immutable.",
46
+ mustBeImmutable: 'Interface must be immutable. Found {{violationCount}} field {{violationNoun}}; the first offending field is "{{firstFieldName}}".',
44
47
  },
45
48
  },
46
49
  defaultOptions: [],
@@ -48,17 +51,51 @@ export const typeDeclarationImmutability = createRule({
48
51
  const parserServices = ESLintUtils.getParserServices(context);
49
52
  const { program } = parserServices;
50
53
  const checker = program.getTypeChecker();
51
- const immutabilityCache = new WeakMap();
52
54
  function checkInterface(node) {
53
55
  const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
54
56
  const type = checker.getTypeAtLocation(tsNode);
55
- if (!isImmutableTypeWithPrimitiveIntersectionPatch(program, type, IMMUTABILITY_OVERRIDES, immutabilityCache)) {
57
+ const immutabilityCache = new WeakMap();
58
+ if (!isImmutableTypeWithPatches(program, type, IMMUTABILITY_OVERRIDES, immutabilityCache)) {
59
+ const offendingFields = getOffendingFields(type);
60
+ const firstFieldName = offendingFields[0] ?? "(unknown)";
61
+ const violationCount = offendingFields.length === 0 ? 1 : offendingFields.length;
56
62
  context.report({
57
63
  node: node.id,
58
64
  messageId: "mustBeImmutable",
65
+ data: {
66
+ firstFieldName,
67
+ violationCount,
68
+ violationNoun: violationCount === 1 ? "violation" : "violations",
69
+ },
59
70
  });
60
71
  }
61
72
  }
73
+ function getOffendingFields(type) {
74
+ const offendingFields = type
75
+ .getProperties()
76
+ .filter((property) => isOffendingProperty(type, property))
77
+ .map((property) => property.getName());
78
+ for (const indexKind of [ts.IndexKind.String, ts.IndexKind.Number]) {
79
+ const indexInfo = checker.getIndexInfoOfType(type, indexKind);
80
+ if (indexInfo !== undefined
81
+ && (!indexInfo.isReadonly || !isImmutable(indexInfo.type))) {
82
+ offendingFields.push(indexKind === ts.IndexKind.String
83
+ ? "[string index]"
84
+ : "[number index]");
85
+ }
86
+ }
87
+ return offendingFields;
88
+ }
89
+ function isOffendingProperty(containingType, property) {
90
+ if (!isPropertyReadonlyInType(containingType, property.getEscapedName(), checker)) {
91
+ return true;
92
+ }
93
+ const propertyType = getTypeOfPropertyOfType(checker, containingType, property);
94
+ return propertyType !== undefined && !isImmutable(propertyType);
95
+ }
96
+ function isImmutable(type) {
97
+ return isImmutableTypeWithPatches(program, type, IMMUTABILITY_OVERRIDES, new WeakMap());
98
+ }
62
99
  return { TSInterfaceDeclaration: checkInterface };
63
100
  },
64
101
  });
@@ -1 +1 @@
1
- {"version":3,"file":"type-declaration-immutability.js","sourceRoot":"","sources":["../../../../../src/rules/type-declaration-immutability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,6CAA6C,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKzC,MAAM,sBAAsB,GAAG;IAC7B,GAAG,mBAAmB,EAAE;IACxB;QACE,IAAI,EAAE;YACJ,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,eAAe;SACtB;QACD,IAAI,EAAE,YAAY,CAAC,YAAY;QAC/B,EAAE,EAAE,YAAY,CAAC,SAAS;KAC3B;IACD;QACE,IAAI,EAAE;YACJ,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,aAAa;SACpB;QACD,IAAI,EAAE,YAAY,CAAC,YAAY;QAC/B,EAAE,EAAE,YAAY,CAAC,SAAS;KAC3B;IACD;QACE,IAAI,EAAE;YACJ,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,aAAa;SACpB;QACD,IAAI,EAAE,YAAY,CAAC,YAAY;QAC/B,EAAE,EAAE,YAAY,CAAC,SAAS;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAG,UAAU,CAAsB;IACzE,IAAI,EAAE,+BAA+B;IACrC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,wCAAwC;YACrD,WAAW,EAAE,IAAI;YACjB,oBAAoB,EAAE,IAAI;SAC3B;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,eAAe,EAAE,+BAA+B;SACjD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,iBAAiB,GAAsB,IAAI,OAAO,EAAE,CAAC;QAE3D,SAAS,cAAc,CAAC,IAAqC;YAC3D,MAAM,MAAM,GAAG,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAE/C,IACE,CAAC,6CAA6C,CAC5C,OAAO,EACP,IAAI,EACJ,sBAAsB,EACtB,iBAAiB,CAClB,EACD,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,IAAI,CAAC,EAAE;oBACb,SAAS,EAAE,iBAAiB;iBAC7B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"type-declaration-immutability.js","sourceRoot":"","sources":["../../../../../src/rules/type-declaration-immutability.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-complete",
3
- "version": "1.12.2",
3
+ "version": "1.12.3",
4
4
  "description": "An ESLint plugin that contains useful rules.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -44,7 +44,8 @@
44
44
  "dependencies": {
45
45
  "@typescript-eslint/type-utils": "8.68.0",
46
46
  "@typescript-eslint/utils": "8.68.0",
47
- "is-immutable-type": "5.0.4"
47
+ "is-immutable-type": "5.0.4",
48
+ "ts-api-utils": "2.5.0"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@babel/core": "7.29.7",