@intentius/chant 0.0.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 +365 -0
- package/package.json +22 -0
- package/src/attrref.test.ts +148 -0
- package/src/attrref.ts +50 -0
- package/src/barrel.test.ts +157 -0
- package/src/barrel.ts +101 -0
- package/src/bench.test.ts +227 -0
- package/src/build.test.ts +437 -0
- package/src/build.ts +425 -0
- package/src/builder.test.ts +312 -0
- package/src/builder.ts +56 -0
- package/src/child-project.ts +44 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/README.md +26 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +16 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +8 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +7 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/examples/getting-started/.gitkeep +0 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/justfile +26 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +29 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate-cli.ts +8 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate.ts +74 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/naming.ts +33 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/rollback.ts +45 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/coverage.ts +11 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/generated/.gitkeep +0 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/generator.ts +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/parser.ts +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/index.ts +9 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/rules/index.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/rules/sample.ts +18 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lsp/completions.ts +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lsp/hover.ts +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/plugin.ts +110 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/serializer.ts +24 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/spec/fetch.ts +21 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/spec/parse.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate.ts +24 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/tsconfig.json +10 -0
- package/src/cli/commands/__fixtures__/sample-rule.ts +11 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +222 -0
- package/src/cli/commands/build.test.ts +149 -0
- package/src/cli/commands/build.ts +344 -0
- package/src/cli/commands/diff.test.ts +148 -0
- package/src/cli/commands/diff.ts +221 -0
- package/src/cli/commands/doctor.test.ts +239 -0
- package/src/cli/commands/doctor.ts +224 -0
- package/src/cli/commands/import.test.ts +379 -0
- package/src/cli/commands/import.ts +335 -0
- package/src/cli/commands/init-lexicon.test.ts +297 -0
- package/src/cli/commands/init-lexicon.ts +993 -0
- package/src/cli/commands/init.test.ts +317 -0
- package/src/cli/commands/init.ts +505 -0
- package/src/cli/commands/licenses.ts +165 -0
- package/src/cli/commands/lint.test.ts +332 -0
- package/src/cli/commands/lint.ts +408 -0
- package/src/cli/commands/list.test.ts +100 -0
- package/src/cli/commands/list.ts +108 -0
- package/src/cli/commands/update.test.ts +38 -0
- package/src/cli/commands/update.ts +207 -0
- package/src/cli/conflict-check.test.ts +255 -0
- package/src/cli/conflict-check.ts +89 -0
- package/src/cli/debug.ts +8 -0
- package/src/cli/format.test.ts +140 -0
- package/src/cli/format.ts +133 -0
- package/src/cli/handlers/build.ts +58 -0
- package/src/cli/handlers/dev.ts +38 -0
- package/src/cli/handlers/init.ts +46 -0
- package/src/cli/handlers/lint.ts +36 -0
- package/src/cli/handlers/misc.ts +57 -0
- package/src/cli/handlers/serve.ts +26 -0
- package/src/cli/index.ts +3 -0
- package/src/cli/lsp/capabilities.ts +46 -0
- package/src/cli/lsp/diagnostics.ts +52 -0
- package/src/cli/lsp/server.test.ts +618 -0
- package/src/cli/lsp/server.ts +393 -0
- package/src/cli/main.test.ts +257 -0
- package/src/cli/main.ts +224 -0
- package/src/cli/mcp/resources/context.ts +59 -0
- package/src/cli/mcp/server.test.ts +747 -0
- package/src/cli/mcp/server.ts +402 -0
- package/src/cli/mcp/tools/build.ts +117 -0
- package/src/cli/mcp/tools/import.ts +48 -0
- package/src/cli/mcp/tools/lint.ts +45 -0
- package/src/cli/plugins.test.ts +31 -0
- package/src/cli/plugins.ts +94 -0
- package/src/cli/registry.ts +73 -0
- package/src/cli/reporters/stylish.test.ts +282 -0
- package/src/cli/reporters/stylish.ts +186 -0
- package/src/cli/watch.test.ts +81 -0
- package/src/cli/watch.ts +101 -0
- package/src/codegen/case.test.ts +30 -0
- package/src/codegen/case.ts +11 -0
- package/src/codegen/coverage.ts +167 -0
- package/src/codegen/docs.ts +634 -0
- package/src/codegen/fetch.test.ts +119 -0
- package/src/codegen/fetch.ts +261 -0
- package/src/codegen/generate-registry.test.ts +118 -0
- package/src/codegen/generate-registry.ts +107 -0
- package/src/codegen/generate-runtime-index.test.ts +81 -0
- package/src/codegen/generate-runtime-index.ts +99 -0
- package/src/codegen/generate-typescript.test.ts +146 -0
- package/src/codegen/generate-typescript.ts +161 -0
- package/src/codegen/generate.ts +206 -0
- package/src/codegen/json-patch.test.ts +113 -0
- package/src/codegen/json-patch.ts +151 -0
- package/src/codegen/json-schema.test.ts +196 -0
- package/src/codegen/json-schema.ts +209 -0
- package/src/codegen/naming.ts +201 -0
- package/src/codegen/package.ts +161 -0
- package/src/codegen/rollback.test.ts +92 -0
- package/src/codegen/rollback.ts +115 -0
- package/src/codegen/topo-sort.test.ts +69 -0
- package/src/codegen/topo-sort.ts +46 -0
- package/src/codegen/typecheck.test.ts +37 -0
- package/src/codegen/typecheck.ts +74 -0
- package/src/codegen/validate.test.ts +86 -0
- package/src/codegen/validate.ts +143 -0
- package/src/composite.test.ts +426 -0
- package/src/composite.ts +243 -0
- package/src/config.test.ts +91 -0
- package/src/config.ts +87 -0
- package/src/declarable.test.ts +160 -0
- package/src/declarable.ts +47 -0
- package/src/detectLexicon.test.ts +236 -0
- package/src/detectLexicon.ts +37 -0
- package/src/discovery/cache.test.ts +78 -0
- package/src/discovery/cache.ts +86 -0
- package/src/discovery/collect.test.ts +269 -0
- package/src/discovery/collect.ts +51 -0
- package/src/discovery/cycles.test.ts +238 -0
- package/src/discovery/cycles.ts +107 -0
- package/src/discovery/files.test.ts +154 -0
- package/src/discovery/files.ts +61 -0
- package/src/discovery/graph.test.ts +476 -0
- package/src/discovery/graph.ts +150 -0
- package/src/discovery/import.test.ts +199 -0
- package/src/discovery/import.ts +20 -0
- package/src/discovery/index.test.ts +272 -0
- package/src/discovery/index.ts +132 -0
- package/src/discovery/resolve.test.ts +267 -0
- package/src/discovery/resolve.ts +54 -0
- package/src/errors.test.ts +138 -0
- package/src/errors.ts +86 -0
- package/src/import/base-parser.test.ts +67 -0
- package/src/import/base-parser.ts +48 -0
- package/src/import/generator.ts +21 -0
- package/src/import/ir-utils.test.ts +103 -0
- package/src/import/ir-utils.ts +87 -0
- package/src/import/parser.ts +41 -0
- package/src/index.ts +60 -0
- package/src/intrinsic-interpolation.test.ts +91 -0
- package/src/intrinsic-interpolation.ts +89 -0
- package/src/intrinsic.test.ts +69 -0
- package/src/intrinsic.ts +43 -0
- package/src/lexicon-integrity.test.ts +94 -0
- package/src/lexicon-integrity.ts +69 -0
- package/src/lexicon-manifest.test.ts +101 -0
- package/src/lexicon-manifest.ts +71 -0
- package/src/lexicon-output.test.ts +182 -0
- package/src/lexicon-output.ts +82 -0
- package/src/lexicon-schema.test.ts +239 -0
- package/src/lexicon-schema.ts +144 -0
- package/src/lexicon.ts +212 -0
- package/src/lint/config-overrides.test.ts +254 -0
- package/src/lint/config.test.ts +644 -0
- package/src/lint/config.ts +375 -0
- package/src/lint/declarative.test.ts +256 -0
- package/src/lint/declarative.ts +187 -0
- package/src/lint/engine.test.ts +465 -0
- package/src/lint/engine.ts +172 -0
- package/src/lint/named-checks.test.ts +37 -0
- package/src/lint/named-checks.ts +33 -0
- package/src/lint/parser.test.ts +129 -0
- package/src/lint/parser.ts +42 -0
- package/src/lint/post-synth.test.ts +113 -0
- package/src/lint/post-synth.ts +76 -0
- package/src/lint/presets/relaxed.json +19 -0
- package/src/lint/presets/strict.json +19 -0
- package/src/lint/rule-loader.test.ts +67 -0
- package/src/lint/rule-loader.ts +67 -0
- package/src/lint/rule-options.test.ts +141 -0
- package/src/lint/rule.test.ts +196 -0
- package/src/lint/rule.ts +98 -0
- package/src/lint/rules/barrel-import-style.test.ts +80 -0
- package/src/lint/rules/barrel-import-style.ts +59 -0
- package/src/lint/rules/composite-scope.ts +55 -0
- package/src/lint/rules/cor017-composite-name-match.test.ts +107 -0
- package/src/lint/rules/cor017-composite-name-match.ts +108 -0
- package/src/lint/rules/cor018-composite-prefer-lexicon-type.test.ts +172 -0
- package/src/lint/rules/cor018-composite-prefer-lexicon-type.ts +167 -0
- package/src/lint/rules/declarable-naming-convention.test.ts +69 -0
- package/src/lint/rules/declarable-naming-convention.ts +70 -0
- package/src/lint/rules/enforce-barrel-import.test.ts +169 -0
- package/src/lint/rules/enforce-barrel-import.ts +81 -0
- package/src/lint/rules/enforce-barrel-ref.test.ts +114 -0
- package/src/lint/rules/enforce-barrel-ref.ts +75 -0
- package/src/lint/rules/evl001-non-literal-expression.test.ts +158 -0
- package/src/lint/rules/evl001-non-literal-expression.ts +149 -0
- package/src/lint/rules/evl002-control-flow-resource.test.ts +110 -0
- package/src/lint/rules/evl002-control-flow-resource.ts +61 -0
- package/src/lint/rules/evl003-dynamic-property-access.test.ts +63 -0
- package/src/lint/rules/evl003-dynamic-property-access.ts +41 -0
- package/src/lint/rules/evl004-spread-non-const.test.ts +130 -0
- package/src/lint/rules/evl004-spread-non-const.ts +111 -0
- package/src/lint/rules/evl005-resource-block-body.test.ts +59 -0
- package/src/lint/rules/evl005-resource-block-body.ts +49 -0
- package/src/lint/rules/evl006-barrel-usage.test.ts +63 -0
- package/src/lint/rules/evl006-barrel-usage.ts +95 -0
- package/src/lint/rules/evl007-invalid-siblings.test.ts +87 -0
- package/src/lint/rules/evl007-invalid-siblings.ts +139 -0
- package/src/lint/rules/evl008-unresolvable-barrel-ref.test.ts +118 -0
- package/src/lint/rules/evl008-unresolvable-barrel-ref.ts +140 -0
- package/src/lint/rules/evl009-composite-no-constant.test.ts +162 -0
- package/src/lint/rules/evl009-composite-no-constant.ts +171 -0
- package/src/lint/rules/evl010-composite-no-transform.test.ts +121 -0
- package/src/lint/rules/evl010-composite-no-transform.ts +69 -0
- package/src/lint/rules/export-required.test.ts +213 -0
- package/src/lint/rules/export-required.ts +158 -0
- package/src/lint/rules/file-declarable-limit.test.ts +148 -0
- package/src/lint/rules/file-declarable-limit.ts +96 -0
- package/src/lint/rules/flat-declarations.test.ts +210 -0
- package/src/lint/rules/flat-declarations.ts +70 -0
- package/src/lint/rules/index.ts +99 -0
- package/src/lint/rules/no-cyclic-declarable-ref.test.ts +135 -0
- package/src/lint/rules/no-cyclic-declarable-ref.ts +178 -0
- package/src/lint/rules/no-redundant-type-import.test.ts +129 -0
- package/src/lint/rules/no-redundant-type-import.ts +85 -0
- package/src/lint/rules/no-redundant-value-cast.test.ts +51 -0
- package/src/lint/rules/no-redundant-value-cast.ts +46 -0
- package/src/lint/rules/no-string-ref.test.ts +100 -0
- package/src/lint/rules/no-string-ref.ts +66 -0
- package/src/lint/rules/no-unused-declarable-import.test.ts +74 -0
- package/src/lint/rules/no-unused-declarable-import.ts +103 -0
- package/src/lint/rules/no-unused-declarable.test.ts +134 -0
- package/src/lint/rules/no-unused-declarable.ts +118 -0
- package/src/lint/rules/prefer-namespace-import.test.ts +102 -0
- package/src/lint/rules/prefer-namespace-import.ts +63 -0
- package/src/lint/rules/single-concern-file.test.ts +156 -0
- package/src/lint/rules/single-concern-file.ts +98 -0
- package/src/lint/rules/stale-barrel-types.ts +60 -0
- package/src/lint/selectors.test.ts +113 -0
- package/src/lint/selectors.ts +188 -0
- package/src/lsp/lexicon-providers.ts +191 -0
- package/src/lsp/types.ts +79 -0
- package/src/mcp/types.ts +22 -0
- package/src/project/scan.test.ts +178 -0
- package/src/project/scan.ts +182 -0
- package/src/project/sync.test.ts +87 -0
- package/src/project/sync.ts +46 -0
- package/src/project-validation.test.ts +64 -0
- package/src/project-validation.ts +79 -0
- package/src/pseudo-parameter.test.ts +39 -0
- package/src/pseudo-parameter.ts +47 -0
- package/src/runtime.ts +68 -0
- package/src/serializer-walker.test.ts +124 -0
- package/src/serializer-walker.ts +83 -0
- package/src/serializer.ts +42 -0
- package/src/sort.test.ts +290 -0
- package/src/sort.ts +58 -0
- package/src/stack-output.ts +82 -0
- package/src/types.test.ts +307 -0
- package/src/types.ts +46 -0
- package/src/utils.test.ts +195 -0
- package/src/utils.ts +46 -0
- package/src/validation.test.ts +308 -0
- package/src/validation.ts +50 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { LintRule, LintDiagnostic, LintContext, LintRunOptions } from "./rule";
|
|
2
|
+
import { parseFile } from "./parser";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents a disable directive found in source code comments
|
|
7
|
+
*/
|
|
8
|
+
interface DisableDirective {
|
|
9
|
+
/** Line number where the directive appears (1-based) */
|
|
10
|
+
line: number;
|
|
11
|
+
/** Type of directive */
|
|
12
|
+
type: "file" | "line" | "next-line";
|
|
13
|
+
/** Specific rule IDs to disable, or undefined for all rules */
|
|
14
|
+
ruleIds?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse disable comments from source code
|
|
19
|
+
* Supports:
|
|
20
|
+
* - // chant-disable - disable all rules for entire file
|
|
21
|
+
* - // chant-disable-line - disable all rules for current line
|
|
22
|
+
* - // chant-disable-next-line - disable all rules for next line
|
|
23
|
+
* - // chant-disable rule-id1 rule-id2 - disable specific rules for file
|
|
24
|
+
* - // chant-disable-line rule-id1 - disable specific rules for line
|
|
25
|
+
* - // chant-disable-next-line rule-id1 - disable specific rules for next line
|
|
26
|
+
*/
|
|
27
|
+
function parseDisableComments(content: string): DisableDirective[] {
|
|
28
|
+
const directives: DisableDirective[] = [];
|
|
29
|
+
const lines = content.split("\n");
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < lines.length; i++) {
|
|
32
|
+
const line = lines[i];
|
|
33
|
+
const lineNumber = i + 1;
|
|
34
|
+
|
|
35
|
+
// Match disable comments
|
|
36
|
+
const disableFileMatch = line.match(/\/\/\s*chant-disable(?:\s+(.+))?$/);
|
|
37
|
+
const disableLineMatch = line.match(/\/\/\s*chant-disable-line(?:\s+(.+))?$/);
|
|
38
|
+
const disableNextLineMatch = line.match(/\/\/\s*chant-disable-next-line(?:\s+(.+))?$/);
|
|
39
|
+
|
|
40
|
+
if (disableNextLineMatch) {
|
|
41
|
+
const ruleIds = disableNextLineMatch[1]?.trim().split(/\s+/).filter(Boolean);
|
|
42
|
+
directives.push({
|
|
43
|
+
line: lineNumber + 1, // Next line
|
|
44
|
+
type: "next-line",
|
|
45
|
+
ruleIds: ruleIds && ruleIds.length > 0 ? ruleIds : undefined,
|
|
46
|
+
});
|
|
47
|
+
} else if (disableLineMatch) {
|
|
48
|
+
const ruleIds = disableLineMatch[1]?.trim().split(/\s+/).filter(Boolean);
|
|
49
|
+
directives.push({
|
|
50
|
+
line: lineNumber,
|
|
51
|
+
type: "line",
|
|
52
|
+
ruleIds: ruleIds && ruleIds.length > 0 ? ruleIds : undefined,
|
|
53
|
+
});
|
|
54
|
+
} else if (disableFileMatch) {
|
|
55
|
+
const ruleIds = disableFileMatch[1]?.trim().split(/\s+/).filter(Boolean);
|
|
56
|
+
directives.push({
|
|
57
|
+
line: lineNumber,
|
|
58
|
+
type: "file",
|
|
59
|
+
ruleIds: ruleIds && ruleIds.length > 0 ? ruleIds : undefined,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return directives;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if a diagnostic should be suppressed based on disable directives
|
|
69
|
+
*/
|
|
70
|
+
function isDiagnosticDisabled(
|
|
71
|
+
diagnostic: LintDiagnostic,
|
|
72
|
+
directives: DisableDirective[],
|
|
73
|
+
allRuleIds: Set<string>
|
|
74
|
+
): boolean {
|
|
75
|
+
// Check for file-level disables
|
|
76
|
+
const fileDisables = directives.filter((d) => d.type === "file");
|
|
77
|
+
for (const directive of fileDisables) {
|
|
78
|
+
if (!directive.ruleIds) {
|
|
79
|
+
// Disable all rules
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
// Check if rule ID exists before checking if it's disabled
|
|
83
|
+
if (directive.ruleIds.some((id) => allRuleIds.has(id))) {
|
|
84
|
+
if (directive.ruleIds.includes(diagnostic.ruleId)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Silently ignore non-existent rule IDs
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Check for line-specific disables
|
|
92
|
+
const lineDisables = directives.filter(
|
|
93
|
+
(d) => (d.type === "line" || d.type === "next-line") && d.line === diagnostic.line
|
|
94
|
+
);
|
|
95
|
+
for (const directive of lineDisables) {
|
|
96
|
+
if (!directive.ruleIds) {
|
|
97
|
+
// Disable all rules
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
// Check if rule ID exists before checking if it's disabled
|
|
101
|
+
if (directive.ruleIds.some((id) => allRuleIds.has(id))) {
|
|
102
|
+
if (directive.ruleIds.includes(diagnostic.ruleId)) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Silently ignore non-existent rule IDs
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Execute lint rules on a set of files
|
|
114
|
+
* @param files - Array of file paths to lint
|
|
115
|
+
* @param rules - Array of lint rules to execute
|
|
116
|
+
* @param ruleOptions - Optional map of rule ID to options object
|
|
117
|
+
* @returns Array of diagnostics from all rules and files, with disable comments applied
|
|
118
|
+
*/
|
|
119
|
+
export async function runLint(
|
|
120
|
+
files: string[],
|
|
121
|
+
rules: LintRule[],
|
|
122
|
+
ruleOptions?: Map<string, Record<string, unknown>>,
|
|
123
|
+
runOptions?: LintRunOptions,
|
|
124
|
+
): Promise<LintDiagnostic[]> {
|
|
125
|
+
const allDiagnostics: LintDiagnostic[] = [];
|
|
126
|
+
const allRuleIds = new Set(rules.map((r) => r.id));
|
|
127
|
+
|
|
128
|
+
for (const filePath of files) {
|
|
129
|
+
try {
|
|
130
|
+
// Parse the file
|
|
131
|
+
const sourceFile = parseFile(filePath);
|
|
132
|
+
|
|
133
|
+
// Read file content for disable comment parsing
|
|
134
|
+
const content = readFileSync(filePath, "utf-8");
|
|
135
|
+
const directives = parseDisableComments(content);
|
|
136
|
+
|
|
137
|
+
// Create lint context
|
|
138
|
+
const context: LintContext = {
|
|
139
|
+
sourceFile,
|
|
140
|
+
entities: [],
|
|
141
|
+
filePath,
|
|
142
|
+
lexicon: undefined,
|
|
143
|
+
barrelExports: runOptions?.barrelExports,
|
|
144
|
+
projectExports: runOptions?.projectExports,
|
|
145
|
+
projectScan: runOptions?.projectScan,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// Execute each rule
|
|
149
|
+
for (const rule of rules) {
|
|
150
|
+
const options = ruleOptions?.get(rule.id);
|
|
151
|
+
const diagnostics = rule.check(context, options);
|
|
152
|
+
allDiagnostics.push(...diagnostics);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Filter out disabled diagnostics for this file
|
|
156
|
+
const filteredDiagnostics = allDiagnostics.filter(
|
|
157
|
+
(diagnostic) => diagnostic.file === filePath && !isDiagnosticDisabled(diagnostic, directives, allRuleIds)
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Replace file diagnostics with filtered ones
|
|
161
|
+
const otherFileDiagnostics = allDiagnostics.filter((d) => d.file !== filePath);
|
|
162
|
+
allDiagnostics.length = 0;
|
|
163
|
+
allDiagnostics.push(...otherFileDiagnostics, ...filteredDiagnostics);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
// If parsing fails, skip this file and continue with others
|
|
166
|
+
// In a real implementation, you might want to collect these errors
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return allDiagnostics;
|
|
172
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
import { registerCheck, getNamedCheck, listChecks } from "./named-checks";
|
|
4
|
+
import type { LintContext } from "./rule";
|
|
5
|
+
|
|
6
|
+
describe("named-checks", () => {
|
|
7
|
+
test("registerCheck and getNamedCheck", () => {
|
|
8
|
+
registerCheck("is-string-literal", (node) => ts.isStringLiteral(node));
|
|
9
|
+
const check = getNamedCheck("is-string-literal");
|
|
10
|
+
expect(check).toBeDefined();
|
|
11
|
+
|
|
12
|
+
const sf = ts.createSourceFile("test.ts", `const a = "hello";`, ts.ScriptTarget.Latest, true);
|
|
13
|
+
const ctx: LintContext = { sourceFile: sf, entities: [], filePath: "test.ts" };
|
|
14
|
+
|
|
15
|
+
// Test with a string literal node
|
|
16
|
+
let found = false;
|
|
17
|
+
ts.forEachChild(sf, function visit(node) {
|
|
18
|
+
if (ts.isStringLiteral(node)) {
|
|
19
|
+
found = check!(node, ctx);
|
|
20
|
+
}
|
|
21
|
+
ts.forEachChild(node, visit);
|
|
22
|
+
});
|
|
23
|
+
expect(found).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("getNamedCheck returns undefined for unknown check", () => {
|
|
27
|
+
expect(getNamedCheck("nonexistent-check")).toBeUndefined();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("listChecks returns registered check names", () => {
|
|
31
|
+
registerCheck("test-check-a", () => true);
|
|
32
|
+
registerCheck("test-check-b", () => false);
|
|
33
|
+
const checks = listChecks();
|
|
34
|
+
expect(checks).toContain("test-check-a");
|
|
35
|
+
expect(checks).toContain("test-check-b");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type * as ts from "typescript";
|
|
2
|
+
import type { LintContext } from "./rule";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A named check function that evaluates a condition on a node.
|
|
6
|
+
*/
|
|
7
|
+
export type NamedCheckFn = (node: ts.Node, context: LintContext) => boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Registry of named check functions.
|
|
11
|
+
*/
|
|
12
|
+
const checkRegistry = new Map<string, NamedCheckFn>();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Register a named check function.
|
|
16
|
+
*/
|
|
17
|
+
export function registerCheck(name: string, fn: NamedCheckFn): void {
|
|
18
|
+
checkRegistry.set(name, fn);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get a named check by name. Returns undefined if not found.
|
|
23
|
+
*/
|
|
24
|
+
export function getNamedCheck(name: string): NamedCheckFn | undefined {
|
|
25
|
+
return checkRegistry.get(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* List all registered check names.
|
|
30
|
+
*/
|
|
31
|
+
export function listChecks(): string[] {
|
|
32
|
+
return Array.from(checkRegistry.keys());
|
|
33
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
2
|
+
import { parseFile } from "./parser";
|
|
3
|
+
import { writeFileSync, unlinkSync, mkdirSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import * as ts from "typescript";
|
|
6
|
+
|
|
7
|
+
const TEST_DIR = join(import.meta.dir, "__test_parser__");
|
|
8
|
+
const VALID_FILE = join(TEST_DIR, "valid.ts");
|
|
9
|
+
const INVALID_FILE = join(TEST_DIR, "invalid.ts");
|
|
10
|
+
const NONEXISTENT_FILE = join(TEST_DIR, "nonexistent.ts");
|
|
11
|
+
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
14
|
+
|
|
15
|
+
// Create a valid TypeScript file
|
|
16
|
+
writeFileSync(
|
|
17
|
+
VALID_FILE,
|
|
18
|
+
`export interface User {
|
|
19
|
+
name: string;
|
|
20
|
+
age: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function greet(user: User): string {
|
|
24
|
+
return \`Hello, \${user.name}!\`;
|
|
25
|
+
}
|
|
26
|
+
`
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Create an invalid TypeScript file (syntax error)
|
|
30
|
+
writeFileSync(
|
|
31
|
+
INVALID_FILE,
|
|
32
|
+
`export interface User {
|
|
33
|
+
name: string
|
|
34
|
+
age: number // missing semicolon is ok, but let's make a real syntax error
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function broken( {
|
|
38
|
+
return "missing closing paren and body";
|
|
39
|
+
`
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterAll(() => {
|
|
44
|
+
try {
|
|
45
|
+
unlinkSync(VALID_FILE);
|
|
46
|
+
} catch {}
|
|
47
|
+
try {
|
|
48
|
+
unlinkSync(INVALID_FILE);
|
|
49
|
+
} catch {}
|
|
50
|
+
try {
|
|
51
|
+
unlinkSync(NONEXISTENT_FILE);
|
|
52
|
+
} catch {}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("parseFile", () => {
|
|
56
|
+
test("parses valid TypeScript file and returns SourceFile", () => {
|
|
57
|
+
const sourceFile = parseFile(VALID_FILE);
|
|
58
|
+
|
|
59
|
+
expect(sourceFile).toBeDefined();
|
|
60
|
+
expect(sourceFile.fileName).toBe(VALID_FILE);
|
|
61
|
+
expect(sourceFile.kind).toBe(ts.SyntaxKind.SourceFile);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("returns SourceFile with expected structure", () => {
|
|
65
|
+
const sourceFile = parseFile(VALID_FILE);
|
|
66
|
+
|
|
67
|
+
// Should have statements (interface and function declarations)
|
|
68
|
+
expect(sourceFile.statements.length).toBeGreaterThan(0);
|
|
69
|
+
|
|
70
|
+
// First statement should be interface declaration
|
|
71
|
+
const firstStatement = sourceFile.statements[0];
|
|
72
|
+
expect(firstStatement.kind).toBe(ts.SyntaxKind.InterfaceDeclaration);
|
|
73
|
+
|
|
74
|
+
// Second statement should be function declaration
|
|
75
|
+
const secondStatement = sourceFile.statements[1];
|
|
76
|
+
expect(secondStatement.kind).toBe(ts.SyntaxKind.FunctionDeclaration);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("sets parent nodes correctly", () => {
|
|
80
|
+
const sourceFile = parseFile(VALID_FILE);
|
|
81
|
+
|
|
82
|
+
// Check that parent nodes are set
|
|
83
|
+
const firstStatement = sourceFile.statements[0];
|
|
84
|
+
expect(firstStatement.parent).toBe(sourceFile);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("throws clear error for invalid TypeScript", () => {
|
|
88
|
+
expect(() => parseFile(INVALID_FILE)).toThrow("TypeScript parsing failed");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("throws error with file location for syntax errors", () => {
|
|
92
|
+
try {
|
|
93
|
+
parseFile(INVALID_FILE);
|
|
94
|
+
expect.unreachable("Should have thrown an error");
|
|
95
|
+
} catch (err) {
|
|
96
|
+
expect(err).toBeInstanceOf(Error);
|
|
97
|
+
const error = err as Error;
|
|
98
|
+
expect(error.message).toContain(INVALID_FILE);
|
|
99
|
+
expect(error.message).toContain("TypeScript parsing failed");
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("throws clear error when file does not exist", () => {
|
|
104
|
+
expect(() => parseFile(NONEXISTENT_FILE)).toThrow("Failed to read file");
|
|
105
|
+
expect(() => parseFile(NONEXISTENT_FILE)).toThrow(NONEXISTENT_FILE);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("handles empty file", () => {
|
|
109
|
+
const emptyFile = join(TEST_DIR, "empty.ts");
|
|
110
|
+
writeFileSync(emptyFile, "");
|
|
111
|
+
|
|
112
|
+
const sourceFile = parseFile(emptyFile);
|
|
113
|
+
expect(sourceFile).toBeDefined();
|
|
114
|
+
expect(sourceFile.statements.length).toBe(0);
|
|
115
|
+
|
|
116
|
+
unlinkSync(emptyFile);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("handles file with only comments", () => {
|
|
120
|
+
const commentsFile = join(TEST_DIR, "comments.ts");
|
|
121
|
+
writeFileSync(commentsFile, "// Just a comment\n/* Another comment */");
|
|
122
|
+
|
|
123
|
+
const sourceFile = parseFile(commentsFile);
|
|
124
|
+
expect(sourceFile).toBeDefined();
|
|
125
|
+
expect(sourceFile.statements.length).toBe(0);
|
|
126
|
+
|
|
127
|
+
unlinkSync(commentsFile);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parse a TypeScript file into an AST
|
|
6
|
+
* @param path - Absolute or relative path to the TypeScript file
|
|
7
|
+
* @returns Parsed TypeScript SourceFile
|
|
8
|
+
* @throws Error if the file cannot be read or parsed
|
|
9
|
+
*/
|
|
10
|
+
export function parseFile(path: string): ts.SourceFile {
|
|
11
|
+
let content: string;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
content = readFileSync(path, "utf-8");
|
|
15
|
+
} catch (err) {
|
|
16
|
+
throw new Error(`Failed to read file ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const sourceFile = ts.createSourceFile(
|
|
20
|
+
path,
|
|
21
|
+
content,
|
|
22
|
+
ts.ScriptTarget.Latest,
|
|
23
|
+
true // setParentNodes
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// Check for syntax errors (parseDiagnostics is internal but accessible)
|
|
27
|
+
const diagnostics = [
|
|
28
|
+
...(sourceFile as unknown as { parseDiagnostics: ts.DiagnosticWithLocation[] }).parseDiagnostics,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
if (diagnostics.length > 0) {
|
|
32
|
+
const errors = diagnostics
|
|
33
|
+
.map((d) => {
|
|
34
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(d.start ?? 0);
|
|
35
|
+
return `${path}:${line + 1}:${character + 1} - ${ts.flattenDiagnosticMessageText(d.messageText, "\n")}`;
|
|
36
|
+
})
|
|
37
|
+
.join("\n");
|
|
38
|
+
throw new Error(`TypeScript parsing failed:\n${errors}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return sourceFile;
|
|
42
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
import { runPostSynthChecks } from "./post-synth";
|
|
3
|
+
import type { PostSynthCheck, PostSynthContext } from "./post-synth";
|
|
4
|
+
|
|
5
|
+
function createBuildResult(overrides: Partial<PostSynthContext["buildResult"]> = {}) {
|
|
6
|
+
return {
|
|
7
|
+
outputs: new Map<string, string>(),
|
|
8
|
+
entities: new Map(),
|
|
9
|
+
warnings: [] as string[],
|
|
10
|
+
errors: [] as Array<{ message: string; name: string }>,
|
|
11
|
+
sourceFileCount: 0,
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("post-synth checks", () => {
|
|
17
|
+
test("runs check and collects diagnostics", () => {
|
|
18
|
+
const check: PostSynthCheck = {
|
|
19
|
+
id: "PS001",
|
|
20
|
+
description: "Check for empty outputs",
|
|
21
|
+
check(ctx) {
|
|
22
|
+
if (ctx.outputs.size === 0) {
|
|
23
|
+
return [{ checkId: "PS001", severity: "warning", message: "No outputs produced" }];
|
|
24
|
+
}
|
|
25
|
+
return [];
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const result = createBuildResult();
|
|
30
|
+
const diags = runPostSynthChecks([check], result);
|
|
31
|
+
expect(diags).toHaveLength(1);
|
|
32
|
+
expect(diags[0].checkId).toBe("PS001");
|
|
33
|
+
expect(diags[0].severity).toBe("warning");
|
|
34
|
+
expect(diags[0].message).toBe("No outputs produced");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("returns empty when no issues found", () => {
|
|
38
|
+
const check: PostSynthCheck = {
|
|
39
|
+
id: "PS002",
|
|
40
|
+
description: "Always passes",
|
|
41
|
+
check() {
|
|
42
|
+
return [];
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const diags = runPostSynthChecks([check], createBuildResult());
|
|
47
|
+
expect(diags).toHaveLength(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("aggregates diagnostics from multiple checks", () => {
|
|
51
|
+
const checks: PostSynthCheck[] = [
|
|
52
|
+
{
|
|
53
|
+
id: "PS003A",
|
|
54
|
+
description: "Check A",
|
|
55
|
+
check() {
|
|
56
|
+
return [{ checkId: "PS003A", severity: "error", message: "Error A" }];
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "PS003B",
|
|
61
|
+
description: "Check B",
|
|
62
|
+
check() {
|
|
63
|
+
return [
|
|
64
|
+
{ checkId: "PS003B", severity: "warning", message: "Warning B1" },
|
|
65
|
+
{ checkId: "PS003B", severity: "info", message: "Info B2" },
|
|
66
|
+
];
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const diags = runPostSynthChecks(checks, createBuildResult());
|
|
72
|
+
expect(diags).toHaveLength(3);
|
|
73
|
+
expect(diags[0].checkId).toBe("PS003A");
|
|
74
|
+
expect(diags[1].checkId).toBe("PS003B");
|
|
75
|
+
expect(diags[2].checkId).toBe("PS003B");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("provides entities and outputs in context", () => {
|
|
79
|
+
const entities = new Map([["myBucket", { kind: "resource" }]]);
|
|
80
|
+
const outputs = new Map([["aws", '{"AWSTemplateFormatVersion":"2010-09-09"}']]);
|
|
81
|
+
|
|
82
|
+
const check: PostSynthCheck = {
|
|
83
|
+
id: "PS004",
|
|
84
|
+
description: "Check entities",
|
|
85
|
+
check(ctx) {
|
|
86
|
+
const diags = [];
|
|
87
|
+
for (const [name] of ctx.entities) {
|
|
88
|
+
diags.push({
|
|
89
|
+
checkId: "PS004",
|
|
90
|
+
severity: "info" as const,
|
|
91
|
+
message: `Found entity: ${name}`,
|
|
92
|
+
entity: name,
|
|
93
|
+
lexicon: "aws",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return diags;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const diags = runPostSynthChecks(
|
|
101
|
+
[check],
|
|
102
|
+
createBuildResult({ entities: entities as never, outputs }),
|
|
103
|
+
);
|
|
104
|
+
expect(diags).toHaveLength(1);
|
|
105
|
+
expect(diags[0].entity).toBe("myBucket");
|
|
106
|
+
expect(diags[0].lexicon).toBe("aws");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("handles empty check list", () => {
|
|
110
|
+
const diags = runPostSynthChecks([], createBuildResult());
|
|
111
|
+
expect(diags).toHaveLength(0);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Declarable } from "../declarable";
|
|
2
|
+
import type { SerializerResult } from "../serializer";
|
|
3
|
+
import type { Severity } from "./rule";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Context provided to post-synthesis checks.
|
|
7
|
+
*/
|
|
8
|
+
export interface PostSynthContext {
|
|
9
|
+
/** The build result outputs (lexicon name → serialized output) */
|
|
10
|
+
outputs: Map<string, string | SerializerResult>;
|
|
11
|
+
/** Map of entity name to Declarable entity */
|
|
12
|
+
entities: Map<string, Declarable>;
|
|
13
|
+
/** Raw build result object */
|
|
14
|
+
buildResult: {
|
|
15
|
+
outputs: Map<string, string | SerializerResult>;
|
|
16
|
+
entities: Map<string, Declarable>;
|
|
17
|
+
warnings: string[];
|
|
18
|
+
errors: Array<{ message: string; name: string }>;
|
|
19
|
+
sourceFileCount: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extract the primary content string from a serializer output.
|
|
25
|
+
*/
|
|
26
|
+
export function getPrimaryOutput(output: string | SerializerResult): string {
|
|
27
|
+
return typeof output === "string" ? output : output.primary;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A diagnostic from a post-synthesis check.
|
|
32
|
+
*/
|
|
33
|
+
export interface PostSynthDiagnostic {
|
|
34
|
+
/** ID of the check that produced this diagnostic */
|
|
35
|
+
checkId: string;
|
|
36
|
+
/** Severity level */
|
|
37
|
+
severity: Severity;
|
|
38
|
+
/** Human-readable message */
|
|
39
|
+
message: string;
|
|
40
|
+
/** Optional entity name related to this diagnostic */
|
|
41
|
+
entity?: string;
|
|
42
|
+
/** Optional lexicon related to this diagnostic */
|
|
43
|
+
lexicon?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A post-synthesis check that validates build output.
|
|
48
|
+
*/
|
|
49
|
+
export interface PostSynthCheck {
|
|
50
|
+
/** Unique identifier for this check */
|
|
51
|
+
id: string;
|
|
52
|
+
/** Human-readable description */
|
|
53
|
+
description: string;
|
|
54
|
+
/** Execute the check and return diagnostics */
|
|
55
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Run a set of post-synthesis checks against a build result.
|
|
60
|
+
*/
|
|
61
|
+
export function runPostSynthChecks(
|
|
62
|
+
checks: PostSynthCheck[],
|
|
63
|
+
buildResult: PostSynthContext["buildResult"],
|
|
64
|
+
): PostSynthDiagnostic[] {
|
|
65
|
+
const ctx: PostSynthContext = {
|
|
66
|
+
outputs: buildResult.outputs,
|
|
67
|
+
entities: buildResult.entities,
|
|
68
|
+
buildResult,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
72
|
+
for (const check of checks) {
|
|
73
|
+
diagnostics.push(...check.check(ctx));
|
|
74
|
+
}
|
|
75
|
+
return diagnostics;
|
|
76
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": {
|
|
3
|
+
"COR001": "warning",
|
|
4
|
+
"COR002": "off",
|
|
5
|
+
"COR003": "off",
|
|
6
|
+
"COR004": "off",
|
|
7
|
+
"COR005": "off",
|
|
8
|
+
"COR006": "off",
|
|
9
|
+
"COR007": "off",
|
|
10
|
+
"COR008": "warning",
|
|
11
|
+
"COR009": "off",
|
|
12
|
+
"COR010": "warning",
|
|
13
|
+
"COR011": "warning",
|
|
14
|
+
"COR012": "off",
|
|
15
|
+
"COR013": "off",
|
|
16
|
+
"COR014": "off",
|
|
17
|
+
"COR015": "off"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": {
|
|
3
|
+
"COR001": "error",
|
|
4
|
+
"COR002": "error",
|
|
5
|
+
"COR003": "warning",
|
|
6
|
+
"COR004": "warning",
|
|
7
|
+
"COR005": "warning",
|
|
8
|
+
"COR006": "error",
|
|
9
|
+
"COR007": "warning",
|
|
10
|
+
"COR008": "error",
|
|
11
|
+
"COR009": "warning",
|
|
12
|
+
"COR010": "warning",
|
|
13
|
+
"COR011": "error",
|
|
14
|
+
"COR012": "warning",
|
|
15
|
+
"COR013": "info",
|
|
16
|
+
"COR014": "warning",
|
|
17
|
+
"COR015": "warning"
|
|
18
|
+
}
|
|
19
|
+
}
|