@shivaedev/quality 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +69 -2
  3. package/dist/rules/suppressions/biome/configs.d.ts +21 -10
  4. package/dist/rules/suppressions/biome/configs.d.ts.map +1 -1
  5. package/dist/rules/suppressions/biome/configs.js +57 -21
  6. package/dist/rules/suppressions/biome/configs.js.map +1 -1
  7. package/dist/rules/suppressions/biome/declarations.d.ts +18 -0
  8. package/dist/rules/suppressions/biome/declarations.d.ts.map +1 -0
  9. package/dist/rules/suppressions/biome/declarations.js +20 -0
  10. package/dist/rules/suppressions/biome/declarations.js.map +1 -0
  11. package/dist/rules/suppressions/biome/resolve.d.ts +3 -0
  12. package/dist/rules/suppressions/biome/resolve.d.ts.map +1 -0
  13. package/dist/rules/suppressions/biome/resolve.js +70 -0
  14. package/dist/rules/suppressions/biome/resolve.js.map +1 -0
  15. package/dist/rules/suppressions/biome/weakenings.d.ts +3 -3
  16. package/dist/rules/suppressions/biome/weakenings.d.ts.map +1 -1
  17. package/dist/rules/suppressions/biome/weakenings.js +41 -33
  18. package/dist/rules/suppressions/biome/weakenings.js.map +1 -1
  19. package/dist/rules/suppressions/biome-overrides.d.ts.map +1 -1
  20. package/dist/rules/suppressions/biome-overrides.js +31 -23
  21. package/dist/rules/suppressions/biome-overrides.js.map +1 -1
  22. package/package.json +5 -3
  23. package/src/rules/suppressions/biome/configs.ts +97 -28
  24. package/src/rules/suppressions/biome/declarations.ts +37 -0
  25. package/src/rules/suppressions/biome/resolve.ts +86 -0
  26. package/src/rules/suppressions/biome/weakenings.ts +54 -37
  27. package/src/rules/suppressions/biome-overrides.ts +40 -31
  28. package/tsconfig/base.json +35 -0
  29. package/tsconfig/package.json +10 -0
@@ -1,43 +1,53 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { defineRule, type Finding } from "../../rule.ts";
3
- import { biomeConfigs, type Config } from "./biome/configs.ts";
3
+ import { biomeConfigs, type Chain } from "./biome/configs.ts";
4
+ import { Declaration, matches, type Scoped, scoped, scopeText } from "./biome/declarations.ts";
4
5
  import { type Weakening, weakeningsOf } from "./biome/weakenings.ts";
5
6
 
6
- const Declaration = Schema.Struct({
7
- rule: Schema.NonEmptyString,
8
- includes: Schema.NonEmptyArray(Schema.NonEmptyString),
9
- reason: Schema.String.check(Schema.isPattern(/\S/, { expected: "a reason that says why the scope needs the rule weakened" })),
10
- });
11
-
12
- type Declaration = typeof Declaration.Type;
13
-
14
7
  const BiomeOverridesOptions = Schema.Struct({
15
8
  declared: Schema.Array(Declaration).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
16
9
  });
17
10
 
18
- const sameScope = (left: ReadonlyArray<string>, right: ReadonlyArray<string>): boolean =>
19
- new Set(left).size === new Set(right).size && left.every((glob) => right.includes(glob));
11
+ interface Shipped extends Scoped {
12
+ readonly specifier: string;
13
+ }
20
14
 
21
- const matches = (declaration: Declaration, weakening: Weakening): boolean =>
22
- declaration.rule === weakening.rule && sameScope(declaration.includes, weakening.includes);
15
+ const shippedBy = ({ base, layers }: Chain): ReadonlyArray<Shipped> =>
16
+ layers.flatMap(({ preset }) =>
17
+ preset === undefined
18
+ ? []
19
+ : preset.declared.map(({ includes, rule }) => ({ includes: includes.map((glob) => scoped(base, glob)), rule, specifier: preset.specifier })),
20
+ );
23
21
 
24
- const scopeText = (includes: ReadonlyArray<string>): string => includes.map((glob) => `"${glob}"`).join(", ");
22
+ const undeclared = ({ includes, layer, line, rule }: Weakening): Finding =>
23
+ layer.preset === undefined
24
+ ? { file: layer.path, line, message: `Weakens "${rule}" for ${scopeText(includes)} without a declaration.`, subject: rule }
25
+ : {
26
+ file: layer.preset.file,
27
+ line: layer.preset.line,
28
+ message: `Extends "${layer.preset.specifier}", which weakens "${rule}" for ${scopeText(includes)} without a declaration.`,
29
+ subject: rule,
30
+ };
25
31
 
26
- const undeclared = (weakening: Weakening): Finding => ({
27
- file: weakening.file,
28
- line: weakening.line,
29
- message: `Weakens "${weakening.rule}" for ${scopeText(weakening.includes)} without a declaration.`,
30
- subject: weakening.rule,
32
+ const unused = (file: string, declaration: Scoped): Finding => ({
33
+ file,
34
+ message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which no Biome config weakens. Remove the declaration.`,
35
+ subject: declaration.rule,
31
36
  });
32
37
 
33
- const unused = (file: string, declaration: Declaration): Finding => ({
38
+ const repeated = (file: string, declaration: Scoped, shipped: Shipped): Finding => ({
34
39
  file,
35
- message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which no Biome config weakens. Remove the declaration.`,
40
+ message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which "${shipped.specifier}" already declares. Remove the declaration.`,
36
41
  subject: declaration.rule,
37
42
  });
38
43
 
39
- const unreadable = (config: Config): ReadonlyArray<Finding> =>
40
- config._tag === "Unreadable" ? [{ file: config.path, message: `Cannot read this Biome config: ${config.reason}.` }] : [];
44
+ const staleOrRepeated = (file: string, weakenings: ReadonlyArray<Weakening>, shipped: ReadonlyArray<Shipped>) => (declaration: Scoped) => {
45
+ if (!weakenings.some((weakening) => matches(declaration, weakening))) {
46
+ return [unused(file, declaration)];
47
+ }
48
+ const already = shipped.find((candidate) => matches(declaration, candidate));
49
+ return already === undefined ? [] : [repeated(file, declaration, already)];
50
+ };
41
51
 
42
52
  export const biomeOverrides = defineRule({
43
53
  id: "suppressions/biome-overrides",
@@ -46,16 +56,15 @@ export const biomeOverrides = defineRule({
46
56
  options: Schema.toStandardSchemaV1(BiomeOverridesOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
47
57
  registrable: false,
48
58
  check: async (inputs) => {
49
- const configs = await biomeConfigs(inputs);
59
+ const { chains, problems, root } = await biomeConfigs(inputs);
50
60
  const { declared } = inputs.options;
51
- const weakenings = configs.flatMap((config) => (config._tag === "Config" ? weakeningsOf(config.json, config.path, config.base) : []));
52
- const root = configs.find((config) => !config.path.includes("/"))?.path ?? "biome.json";
61
+ const weakenings = chains.flatMap(weakeningsOf);
62
+ const shipped = chains.flatMap(shippedBy);
63
+ const covered = (weakening: Weakening): boolean => [...declared, ...shipped].some((declaration) => matches(declaration, weakening));
53
64
  return [
54
- ...configs.flatMap(unreadable),
55
- ...weakenings.filter((weakening) => !declared.some((declaration) => matches(declaration, weakening))).map(undeclared),
56
- ...declared
57
- .filter((declaration) => !weakenings.some((weakening) => matches(declaration, weakening)))
58
- .map((declaration) => unused(root, declaration)),
65
+ ...problems,
66
+ ...weakenings.filter((weakening) => !covered(weakening)).map(undeclared),
67
+ ...declared.flatMap(staleOrRepeated(root, weakenings, shipped)),
59
68
  ];
60
69
  },
61
70
  });
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "lib": ["ESNext"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "moduleDetection": "force",
8
+ "verbatimModuleSyntax": true,
9
+ "isolatedModules": true,
10
+ "erasableSyntaxOnly": true,
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "allowJs": true,
14
+ "checkJs": true,
15
+ "noEmit": true,
16
+ "strict": true,
17
+ "noImplicitAny": true,
18
+ "strictBuiltinIteratorReturn": true,
19
+ "useUnknownInCatchVariables": true,
20
+ "noUncheckedIndexedAccess": true,
21
+ "exactOptionalPropertyTypes": true,
22
+ "noImplicitOverride": true,
23
+ "noImplicitReturns": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "allowUnreachableCode": false,
28
+ "allowUnusedLabels": false,
29
+ "noUncheckedSideEffectImports": true,
30
+ "libReplacement": false,
31
+ "stableTypeOrdering": true,
32
+ "forceConsistentCasingInFileNames": true,
33
+ "skipLibCheck": true
34
+ }
35
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./base.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "sourceMap": true,
8
+ "rewriteRelativeImportExtensions": true
9
+ }
10
+ }