@eagleoutice/flowr 2.2.15 → 2.3.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.
- package/README.md +226 -6
- package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
- package/abstract-interpretation/data-frame/absint-info.js +31 -0
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +59 -0
- package/abstract-interpretation/data-frame/absint-visitor.js +173 -0
- package/abstract-interpretation/data-frame/domain.d.ts +107 -0
- package/abstract-interpretation/data-frame/domain.js +315 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
- package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
- package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
- package/abstract-interpretation/data-frame/resolve-args.js +118 -0
- package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
- package/abstract-interpretation/data-frame/semantics.js +366 -0
- package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
- package/abstract-interpretation/data-frame/shape-inference.js +117 -0
- package/benchmark/slicer.d.ts +18 -2
- package/benchmark/slicer.js +143 -5
- package/benchmark/stats/print.js +123 -45
- package/benchmark/stats/size-of.d.ts +7 -0
- package/benchmark/stats/size-of.js +1 -0
- package/benchmark/stats/stats.d.ts +30 -1
- package/benchmark/stats/stats.js +4 -2
- package/benchmark/summarizer/data.d.ts +33 -2
- package/benchmark/summarizer/first-phase/input.js +5 -1
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +49 -3
- package/benchmark/summarizer/second-phase/process.js +101 -3
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +5 -1
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +13 -8
- package/cli/common/options.js +4 -0
- package/cli/export-quads-app.js +2 -1
- package/cli/flowr.js +58 -57
- package/cli/repl/commands/repl-cfg.js +13 -13
- package/cli/repl/commands/repl-commands.js +2 -2
- package/cli/repl/commands/repl-dataflow.js +10 -10
- package/cli/repl/commands/repl-execute.d.ts +2 -3
- package/cli/repl/commands/repl-execute.js +4 -4
- package/cli/repl/commands/repl-lineage.js +4 -4
- package/cli/repl/commands/repl-main.d.ts +12 -1
- package/cli/repl/commands/repl-normalize.js +6 -6
- package/cli/repl/commands/repl-parse.js +2 -2
- package/cli/repl/commands/repl-query.js +9 -9
- package/cli/repl/commands/repl-version.js +1 -1
- package/cli/repl/core.d.ts +5 -2
- package/cli/repl/core.js +10 -8
- package/cli/repl/server/connection.d.ts +3 -1
- package/cli/repl/server/connection.js +7 -5
- package/cli/repl/server/server.d.ts +3 -2
- package/cli/repl/server/server.js +4 -2
- package/cli/script-core/statistics-core.d.ts +2 -1
- package/cli/script-core/statistics-core.js +2 -2
- package/cli/script-core/statistics-helper-core.d.ts +2 -1
- package/cli/script-core/statistics-helper-core.js +5 -4
- package/cli/slicer-app.js +4 -2
- package/cli/statistics-app.js +2 -1
- package/cli/statistics-helper-app.js +2 -1
- package/config.d.ts +43 -10
- package/config.js +47 -43
- package/control-flow/cfg-dead-code.js +45 -2
- package/control-flow/cfg-simplification.d.ts +2 -0
- package/control-flow/control-flow-graph.d.ts +2 -0
- package/control-flow/control-flow-graph.js +8 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +5 -3
- package/control-flow/dfg-cfg-guided-visitor.js +15 -4
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +4 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +20 -2
- package/control-flow/semantic-cfg-guided-visitor.js +24 -4
- package/core/pipeline-executor.d.ts +4 -1
- package/core/pipeline-executor.js +6 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -0
- package/core/steps/all/core/10-normalize.js +1 -1
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
- package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
- package/core/steps/all/static-slicing/00-slice.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +32 -31
- package/core/steps/pipeline/default-pipelines.js +8 -8
- package/core/steps/pipeline-step.d.ts +2 -1
- package/dataflow/environments/built-in-config.d.ts +3 -3
- package/dataflow/environments/built-in.d.ts +11 -3
- package/dataflow/environments/built-in.js +5 -3
- package/dataflow/environments/default-builtin-config.js +4 -2
- package/dataflow/environments/define.d.ts +2 -1
- package/dataflow/environments/define.js +4 -5
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +29 -0
- package/dataflow/eval/resolve/alias-tracking.d.ts +7 -2
- package/dataflow/eval/resolve/alias-tracking.js +11 -8
- package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
- package/dataflow/eval/resolve/resolve-argument.js +118 -0
- package/dataflow/eval/resolve/resolve.d.ts +65 -18
- package/dataflow/eval/resolve/resolve.js +144 -48
- package/dataflow/eval/values/string/string-constants.d.ts +1 -1
- package/dataflow/eval/values/string/string-constants.js +7 -2
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +11 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +10 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +6 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +19 -15
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
- package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
- package/dataflow/processor.d.ts +5 -0
- package/documentation/doc-util/doc-cfg.js +4 -3
- package/documentation/doc-util/doc-code.d.ts +1 -1
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-functions.d.ts +24 -0
- package/documentation/doc-util/doc-functions.js +65 -0
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-print.d.ts +5 -0
- package/documentation/doc-util/doc-print.js +36 -0
- package/documentation/doc-util/doc-query.js +13 -2
- package/documentation/doc-util/doc-repl.js +2 -1
- package/documentation/doc-util/doc-search.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +28 -6
- package/documentation/doc-util/doc-types.js +89 -45
- package/documentation/print-cfg-wiki.js +6 -7
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +10 -10
- package/documentation/print-engines-wiki.js +1 -2
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +12 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +223 -34
- package/documentation/print-linting-and-testing-wiki.js +2 -4
- package/documentation/print-normalized-ast-wiki.js +3 -3
- package/documentation/print-query-wiki.js +18 -2
- package/documentation/print-readme.js +24 -1
- package/documentation/print-search-wiki.js +1 -2
- package/linter/linter-executor.d.ts +3 -1
- package/linter/linter-executor.js +3 -2
- package/linter/linter-format.d.ts +67 -7
- package/linter/linter-format.js +12 -1
- package/linter/linter-rules.d.ts +178 -16
- package/linter/linter-rules.js +14 -4
- package/linter/linter-tags.d.ts +80 -0
- package/linter/linter-tags.js +85 -0
- package/linter/rules/absolute-path.d.ts +71 -0
- package/linter/rules/absolute-path.js +177 -0
- package/linter/rules/dataframe-access-validation.d.ts +53 -0
- package/linter/rules/dataframe-access-validation.js +116 -0
- package/linter/rules/deprecated-functions.d.ts +43 -0
- package/linter/rules/deprecated-functions.js +58 -0
- package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
- package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
- package/linter/rules/naming-convention.d.ts +71 -0
- package/linter/rules/naming-convention.js +168 -0
- package/linter/rules/seeded-randomness.d.ts +65 -0
- package/linter/rules/seeded-randomness.js +122 -0
- package/linter/rules/unused-definition.d.ts +41 -0
- package/linter/rules/unused-definition.js +105 -0
- package/package.json +5 -2
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.js +2 -3
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +1 -1
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +2 -2
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -116
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.js +2 -2
- package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +16 -12
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/query.d.ts +76 -16
- package/queries/query.js +2 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
- package/r-bridge/lang-4.x/convert-values.js +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +7 -5
- package/r-bridge/shell.d.ts +3 -2
- package/r-bridge/shell.js +4 -5
- package/search/flowr-search-builder.d.ts +6 -2
- package/search/flowr-search-builder.js +7 -0
- package/search/flowr-search-filters.d.ts +32 -8
- package/search/flowr-search-filters.js +42 -15
- package/search/flowr-search.d.ts +4 -0
- package/search/search-executor/search-enrichers.d.ts +7 -3
- package/search/search-executor/search-enrichers.js +29 -20
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.d.ts +2 -0
- package/search/search-executor/search-transformer.js +10 -1
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +2 -3
- package/statistics/statistics.d.ts +3 -1
- package/statistics/statistics.js +5 -4
- package/util/containers.d.ts +12 -9
- package/util/containers.js +12 -9
- package/util/files.d.ts +8 -2
- package/util/files.js +22 -4
- package/util/objects.d.ts +5 -4
- package/util/r-value.d.ts +23 -0
- package/util/r-value.js +113 -0
- package/util/range.d.ts +5 -1
- package/util/range.js +11 -3
- package/util/text/strings.d.ts +6 -0
- package/util/text/strings.js +35 -0
- package/util/version.js +1 -1
- package/linter/rules/1-deprecated-functions.d.ts +0 -34
- package/linter/rules/1-deprecated-functions.js +0 -54
- package/util/cfg/cfg.d.ts +0 -0
- package/util/cfg/cfg.js +0 -2
|
@@ -12,48 +12,151 @@ const shell_1 = require("../r-bridge/shell");
|
|
|
12
12
|
const doc_query_1 = require("./doc-util/doc-query");
|
|
13
13
|
const doc_types_1 = require("./doc-util/doc-types");
|
|
14
14
|
const path_1 = __importDefault(require("path"));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const doc_repl_1 = require("./doc-util/doc-repl");
|
|
16
|
+
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
17
|
+
const linter_tags_1 = require("../linter/linter-tags");
|
|
18
|
+
const html_hover_over_1 = require("../util/html-hover-over");
|
|
19
|
+
const strings_1 = require("../util/text/strings");
|
|
20
|
+
const assert_1 = require("../util/assert");
|
|
21
|
+
const doc_print_1 = require("./doc-util/doc-print");
|
|
22
|
+
const doc_functions_1 = require("./doc-util/doc-functions");
|
|
23
|
+
const SpecialTagColors = {
|
|
24
|
+
[linter_tags_1.LintingRuleTag.Bug]: 'red',
|
|
25
|
+
[linter_tags_1.LintingRuleTag.Security]: 'orange',
|
|
26
|
+
[linter_tags_1.LintingRuleTag.Smell]: 'yellow',
|
|
27
|
+
[linter_tags_1.LintingRuleTag.QuickFix]: 'lightgray',
|
|
28
|
+
};
|
|
29
|
+
function makeTagBadge(name, info) {
|
|
30
|
+
const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', true).replaceAll('\n', ' ');
|
|
31
|
+
return (0, html_hover_over_1.textWithTooltip)(`<a href='#${name}'> + `-${SpecialTagColors[name] ?? 'teal'}) </a>`, doc);
|
|
32
|
+
}
|
|
33
|
+
function prettyPrintExpectedOutput(expected) {
|
|
34
|
+
if (expected.trim() === '[]') {
|
|
35
|
+
return '* no lints';
|
|
36
|
+
}
|
|
37
|
+
let lines = expected.trim().split('\n');
|
|
38
|
+
if (lines.length <= 1) {
|
|
39
|
+
return expected;
|
|
40
|
+
}
|
|
41
|
+
//
|
|
42
|
+
lines = expected.trim().replace(/^\s*\[+\s*{*/m, '').replace(/\s*}*\s*]+\s*$/, '').split('\n').filter(l => l.trim() !== '');
|
|
43
|
+
/* take the indentation of the last line and remove it from all but the first: */
|
|
44
|
+
const indentation = lines[lines.length - 1].match(/^\s*/)?.[0] ?? '';
|
|
45
|
+
return lines.map((line, i) => {
|
|
46
|
+
if (i === 0) {
|
|
47
|
+
return line;
|
|
48
|
+
}
|
|
49
|
+
return line.replace(new RegExp('^' + indentation, 'g'), '');
|
|
50
|
+
}).join('\n');
|
|
51
|
+
}
|
|
52
|
+
function buildSamplesFromLinterTestCases(shell, testFile) {
|
|
53
|
+
const reports = (0, doc_functions_1.getFunctionsFromFolder)({ files: [path_1.default.resolve('test/functionality/linter/' + testFile)], fname: /assertLinter/ });
|
|
54
|
+
if (reports.info.length === 0) {
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
let result = `#### Additional Examples
|
|
58
|
+
|
|
59
|
+
These examples are synthesized from the test cases in: ${(0, doc_files_1.linkFlowRSourceFile)('test/functionality/linter/' + testFile)}\n\n`;
|
|
60
|
+
for (const report of reports.info) {
|
|
61
|
+
const args = report.arguments;
|
|
62
|
+
if (args.length < 5) {
|
|
63
|
+
console.error('Test case for linter rule ' + report.name + ' does not have enough arguments! Expected at least 5, got ' + args.length);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const testName = args[0].getText(report.source);
|
|
67
|
+
if (report.comments?.some(c => c.includes('@ignore-in-wiki'))) {
|
|
68
|
+
console.warn(`Skipping test case for linter rule ${testName} (${testFile}) as it is marked with @ignore-in-wiki`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// drop any quotes around the test name
|
|
72
|
+
const testNameClean = testName.replace(/^['"]|['"]$/g, '');
|
|
73
|
+
result += `\n${(0, doc_structure_1.section)('Test Case: ' + testNameClean, 4)}
|
|
20
74
|
|
|
21
|
-
|
|
75
|
+
${report.comments ? report.comments.map(c => `> ${c}`).join('\n') + '\n' : ''}
|
|
76
|
+
Given the following input:
|
|
77
|
+
${(0, doc_code_1.codeBlock)('r', args[2].getText(report.source).replace(/^['"]|['"]$/g, '').replace(/\\n/g, '\n'))}
|
|
78
|
+
${args.length >= 7 ? `\nAnd using the following [configuration](#configuration): ${(0, doc_code_1.codeBlock)('ts', prettyPrintExpectedOutput(args[6].getText(report.source)))}` : ''}
|
|
22
79
|
|
|
23
|
-
|
|
80
|
+
We expect the linter to report the following:
|
|
81
|
+
${(0, doc_code_1.codeBlock)('ts', prettyPrintExpectedOutput(args[4].getText(report.source)))}
|
|
24
82
|
|
|
25
|
-
${
|
|
83
|
+
See [here](${(0, doc_types_1.getTypePathLink)({ filePath: report.source.fileName, lineNumber: report.lineNumber })}) for the test-case implementation.
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function registerRules(rVersion, shell, tagTypes, format = 'short') {
|
|
89
|
+
const ruleExplanations = new Map();
|
|
90
|
+
rule(shell, 'deprecated-functions', 'DeprecatedFunctionsConfig', 'DEPRECATED_FUNCTIONS', 'lint-deprecated-functions', `
|
|
26
91
|
first <- data.frame(x = c(1, 2, 3), y = c(1, 2, 3))
|
|
27
92
|
second <- data.frame(x = c(1, 3, 2), y = c(1, 3, 2))
|
|
28
93
|
dplyr::all_equal(first, second)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
${await rule(shell, 'file-path-validity', 'FilePathValidityConfig', 'File Path Validity', 'This rule finds places in the code where files are being read from. In such places, it checks whether the file path is valid and whether the file exists on disk.', `
|
|
94
|
+
`, tagTypes);
|
|
95
|
+
rule(shell, 'file-path-validity', 'FilePathValidityConfig', 'FILE_PATH_VALIDITY', 'lint-file-path-validity', `
|
|
32
96
|
my_data <- read.csv("C:/Users/me/Documents/My R Scripts/Reproducible.csv")
|
|
33
|
-
|
|
97
|
+
`, tagTypes);
|
|
98
|
+
rule(shell, 'absolute-file-paths', 'AbsoluteFilePathConfig', 'ABSOLUTE_PATH', 'lint-absolute-path', `
|
|
99
|
+
read.csv("C:/Users/me/Documents/My R Scripts/Reproducible.csv")
|
|
100
|
+
`, tagTypes);
|
|
101
|
+
rule(shell, 'unused-definitions', 'UnusedDefinitionConfig', 'UNUSED_DEFINITION', 'lint-unused-definition', `
|
|
102
|
+
x <- 42
|
|
103
|
+
y <- 3
|
|
104
|
+
print(x)
|
|
105
|
+
`, tagTypes);
|
|
106
|
+
rule(shell, 'seeded-randomness', 'SeededRandomnessConfig', 'SEEDED_RANDOMNESS', 'lint-seeded-randomness', 'runif(1)', tagTypes);
|
|
107
|
+
rule(shell, 'naming-convention', 'NamingConventionConfig', 'NAMING_CONVENTION', 'lint-naming-convention', `
|
|
108
|
+
myVar <- 42
|
|
109
|
+
print(myVar)
|
|
110
|
+
`, tagTypes);
|
|
111
|
+
rule(shell, 'dataframe-access-validation', 'DataFrameAccessValidationConfig', 'DATA_FRAME_ACCESS_VALIDATION', 'lint-dataframe-access-validation', `
|
|
112
|
+
df <- data.frame(id = 1:5, name = 6:10)
|
|
113
|
+
df[6, "value"]
|
|
114
|
+
`, tagTypes);
|
|
115
|
+
function rule(shell, name, configType, ruleType, testfile, example, types) {
|
|
116
|
+
const rule = linter_rules_1.LintingRules[name];
|
|
117
|
+
const tags = rule.info.tags.toSorted((a, b) => {
|
|
118
|
+
// sort but specials first
|
|
119
|
+
if (a === b) {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
if (SpecialTagColors[a] && SpecialTagColors[b]) {
|
|
123
|
+
return SpecialTagColors[b].localeCompare(SpecialTagColors[a]);
|
|
124
|
+
}
|
|
125
|
+
else if (SpecialTagColors[a]) {
|
|
126
|
+
return -1;
|
|
127
|
+
}
|
|
128
|
+
else if (SpecialTagColors[b]) {
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
return a.localeCompare(b);
|
|
132
|
+
}).map(t => makeTagBadge(t, types)).join(' ');
|
|
133
|
+
if (format === 'short') {
|
|
134
|
+
ruleExplanations.set(name, () => Promise.resolve(`
|
|
135
|
+
**[${rule.info.name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name}):** ${rule.info.description} [see ${(0, doc_types_1.shortLinkFile)(ruleType, types)}]\\
|
|
136
|
+
${tags}
|
|
34
137
|
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
rootFolder: path_1.default.resolve('./src/linter/'),
|
|
40
|
-
typeName: configType,
|
|
41
|
-
inlineTypes: doc_types_1.mermaidHide
|
|
42
|
-
});
|
|
43
|
-
return `
|
|
44
|
-
### ${friendlyName} (\`${name}\`)
|
|
45
|
-
|
|
46
|
-
${description}
|
|
138
|
+
`.trim()));
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
ruleExplanations.set(name, async () => `
|
|
47
142
|
|
|
48
|
-
|
|
143
|
+
${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linter', rVersion })}
|
|
144
|
+
${(0, doc_structure_1.section)(rule.info.name + ` <sup>[<a href="${doc_files_1.FlowrWikiBaseRef}/Linter">overview</a>]</sup>`, 2, name)}
|
|
49
145
|
|
|
50
|
-
|
|
146
|
+
${tags}
|
|
147
|
+
|
|
148
|
+
${rule.info.description}\\
|
|
149
|
+
_This linting rule is implemented in ${(0, doc_types_1.shortLinkFile)(ruleType, types)}._
|
|
51
150
|
|
|
52
|
-
Linting rules can be configured by passing a configuration object to the linter query as shown in the example below. The \`${name}\` rule accepts the following configuration options:
|
|
53
151
|
|
|
54
|
-
|
|
152
|
+
### Configuration
|
|
55
153
|
|
|
56
|
-
|
|
154
|
+
Linting rules can be configured by passing a configuration object to the linter query as shown in the example below.
|
|
155
|
+
The \`${name}\` rule accepts the following configuration options:
|
|
156
|
+
|
|
157
|
+
${Object.getOwnPropertyNames(linter_rules_1.LintingRules[name].info.defaultConfig).sort().map(key => `- ${(0, doc_types_1.shortLink)(`${configType}:::${key}`, types)}\\\n${(0, doc_types_1.getDocumentationForType)(`${configType}::${key}`, types)}`).join('\n')}
|
|
158
|
+
|
|
159
|
+
### Examples
|
|
57
160
|
|
|
58
161
|
${(0, doc_code_1.codeBlock)('r', example)}
|
|
59
162
|
|
|
@@ -61,16 +164,102 @@ The linting query can be used to run this rule on the above example:
|
|
|
61
164
|
|
|
62
165
|
${await (0, doc_query_1.showQuery)(shell, example, [{ type: 'linter', rules: [{ name, config: {} }] }], { collapseQuery: true })}
|
|
63
166
|
|
|
64
|
-
|
|
65
|
-
|
|
167
|
+
${buildSamplesFromLinterTestCases(shell, `${testfile}.test.ts`)}
|
|
168
|
+
|
|
169
|
+
`.trim());
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return ruleExplanations;
|
|
173
|
+
}
|
|
174
|
+
function getAllLintingRulesWitTag(tag) {
|
|
175
|
+
return Object.entries(linter_rules_1.LintingRules).filter(([_, rule]) => rule.info.tags.includes(tag)).map(([name]) => name);
|
|
176
|
+
}
|
|
177
|
+
function linkToRule(name) {
|
|
178
|
+
return `[${name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name})`;
|
|
179
|
+
}
|
|
180
|
+
async function getTextMainPage(shell, tagTypes, rVersion) {
|
|
181
|
+
const rules = registerRules(rVersion, shell, tagTypes.info);
|
|
182
|
+
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linter', rVersion })}
|
|
183
|
+
|
|
184
|
+
This page describes the flowR linter, which is a tool that utilizes flowR's dataflow analysis to find common issues in R scripts. The linter can currently be used through the linter [query](${doc_files_1.FlowrWikiBaseRef}/Query%20API).
|
|
185
|
+
For example:
|
|
186
|
+
|
|
187
|
+
${await (async () => {
|
|
188
|
+
const code = 'read.csv("/root/x.txt")';
|
|
189
|
+
const res = await (0, doc_query_1.showQuery)(shell, code, [{ type: 'linter' }], { showCode: false, collapseQuery: true, collapseResult: false });
|
|
190
|
+
return await (0, doc_repl_1.documentReplSession)(shell, [{
|
|
191
|
+
command: `:query @linter ${JSON.stringify(code)}`,
|
|
192
|
+
description: `
|
|
193
|
+
The linter will analyze the code and return any issues found.
|
|
194
|
+
Formatted more nicely, this returns:
|
|
195
|
+
|
|
196
|
+
${res}
|
|
197
|
+
`
|
|
198
|
+
}]);
|
|
199
|
+
})()}
|
|
200
|
+
|
|
201
|
+
${(0, doc_structure_1.section)('Linting Rules', 2, 'linting-rules')}
|
|
202
|
+
|
|
203
|
+
The following linting rules are available:
|
|
204
|
+
|
|
205
|
+
${await (async () => {
|
|
206
|
+
let result = '';
|
|
207
|
+
for (const k of Object.keys(linter_rules_1.LintingRules).sort()) {
|
|
208
|
+
const rule = rules.get(k);
|
|
209
|
+
(0, assert_1.guard)(rule !== undefined, `Linting rule ${k} is not documented!`);
|
|
210
|
+
result += '\n\n' + await rule();
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
})()}
|
|
214
|
+
|
|
215
|
+
${(0, doc_structure_1.section)('Tags', 2, 'tags')}
|
|
216
|
+
|
|
217
|
+
We use tags to categorize linting rules. The following tags are available:
|
|
218
|
+
|
|
219
|
+
| Tag/Badge   | Description |
|
|
220
|
+
| --- | :-- |
|
|
221
|
+
${Object.entries(linter_tags_1.LintingRuleTag).map(([name, tag]) => {
|
|
222
|
+
return `| <a id="${tag}"></a> ${makeTagBadge(tag, tagTypes.info)} | ${(0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, tagTypes.info).replaceAll(/\n/g, ' ')} (rule${getAllLintingRulesWitTag(tag).length === 1 ? '' : 's'}: ${(0, strings_1.joinWithLast)(getAllLintingRulesWitTag(tag).map(l => linkToRule(l))) || '_none_'}) | `;
|
|
223
|
+
}).join('\n')}
|
|
224
|
+
|
|
225
|
+
`.trim();
|
|
226
|
+
}
|
|
227
|
+
async function getRulesPages(shell, tagTypes, rVersion) {
|
|
228
|
+
const rules = registerRules(rVersion, shell, tagTypes.info, 'long');
|
|
229
|
+
const result = {};
|
|
230
|
+
for (const [name, rule] of rules) {
|
|
231
|
+
const filepath = path_1.default.resolve('./wiki', `lint-${name}.md`);
|
|
232
|
+
result[filepath] = await rule();
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
/** Maps file-names to their content, the 'main' file is named 'main' */
|
|
237
|
+
async function getTexts(shell) {
|
|
238
|
+
const rVersion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
239
|
+
const tagTypes = (0, doc_types_1.getTypesFromFolder)({
|
|
240
|
+
rootFolder: path_1.default.resolve('./src/linter/'),
|
|
241
|
+
inlineTypes: doc_types_1.mermaidHide
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
'main': await getTextMainPage(shell, tagTypes, rVersion),
|
|
245
|
+
...await getRulesPages(shell, tagTypes, rVersion)
|
|
246
|
+
};
|
|
66
247
|
}
|
|
248
|
+
/* As an intermediary solution to changing the wiki system, we make this script generate separate files for each linter rule using fixed paths */
|
|
67
249
|
if (require.main === module) {
|
|
68
250
|
(0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
|
|
69
251
|
const shell = new shell_1.RShell();
|
|
70
|
-
void
|
|
71
|
-
console.log(
|
|
252
|
+
void (getTexts(shell).then(data => {
|
|
253
|
+
console.log(data['main']);
|
|
254
|
+
for (const [file, content] of Object.entries(data)) {
|
|
255
|
+
if (file === 'main') {
|
|
256
|
+
continue; // main is printed above
|
|
257
|
+
}
|
|
258
|
+
const filepath = path_1.default.resolve('./wiki', file);
|
|
259
|
+
(0, doc_print_1.writeWikiTo)(content, filepath);
|
|
260
|
+
}
|
|
72
261
|
}).finally(() => {
|
|
73
262
|
shell.close();
|
|
74
|
-
});
|
|
263
|
+
}));
|
|
75
264
|
}
|
|
76
265
|
//# sourceMappingURL=print-linter-wiki.js.map
|
|
@@ -11,10 +11,10 @@ const doc_types_1 = require("./doc-util/doc-types");
|
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
|
|
13
13
|
function getText() {
|
|
14
|
-
const { info } = (0, doc_types_1.
|
|
14
|
+
const { info } = (0, doc_types_1.getTypesFromFolder)({
|
|
15
15
|
rootFolder: path_1.default.resolve('./test'),
|
|
16
16
|
files: [path_1.default.resolve('./src/dataflow/graph/dataflowgraph-builder.ts')],
|
|
17
|
-
|
|
17
|
+
typeNameForMermaid: 'parameter',
|
|
18
18
|
inlineTypes: doc_types_1.mermaidHide
|
|
19
19
|
});
|
|
20
20
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linting and testing definitions' })}
|
|
@@ -188,8 +188,6 @@ See [test/performance](${doc_files_1.RemoteFlowrFilePathBaseRef}test/performance
|
|
|
188
188
|
Using the vitest Extension for Visual Studio Code, you can start tests directly from the definition and explore your suite in the Testing tab.
|
|
189
189
|
To get started, install the [vitest Extension](https://marketplace.visualstudio.com/items?itemName=vitest.explorer).
|
|
190
190
|
|
|
191
|
-

|
|
192
|
-
|
|
193
191
|
| Testing Tab | In Code |
|
|
194
192
|
|:---------------------------------------:|:-------------------------------------:|
|
|
195
193
|
|  |  |
|
|
@@ -23,9 +23,9 @@ const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
|
|
|
23
23
|
async function getText(shell) {
|
|
24
24
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
25
25
|
const now = performance.now();
|
|
26
|
-
const types = (0, doc_types_1.
|
|
26
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
27
27
|
rootFolder: path_1.default.resolve('./src'),
|
|
28
|
-
|
|
28
|
+
typeNameForMermaid: 'RNode',
|
|
29
29
|
inlineTypes: doc_types_1.mermaidHide
|
|
30
30
|
});
|
|
31
31
|
const elapsed = performance.now() - now;
|
|
@@ -70,7 +70,7 @@ In general, we provide node types for:
|
|
|
70
70
|
Every node is a link, which directly refers to the implementation in the source code.
|
|
71
71
|
Grayed-out parts are used for structuring the AST, grouping together related nodes.
|
|
72
72
|
|
|
73
|
-
${(0, doc_code_1.codeBlock)('mermaid', types.
|
|
73
|
+
${(0, doc_code_1.codeBlock)('mermaid', types.mermaid)}
|
|
74
74
|
|
|
75
75
|
_The generation of the class diagram required ${(0, time_1.printAsMs)(elapsed)}._
|
|
76
76
|
</details>
|
|
@@ -36,6 +36,7 @@ const doc_types_1 = require("./doc-util/doc-types");
|
|
|
36
36
|
const path_1 = __importDefault(require("path"));
|
|
37
37
|
const control_flow_query_executor_1 = require("../queries/catalog/control-flow-query/control-flow-query-executor");
|
|
38
38
|
const doc_cfg_1 = require("./doc-util/doc-cfg");
|
|
39
|
+
const df_shape_query_executor_1 = require("../queries/catalog/df-shape-query/df-shape-query-executor");
|
|
39
40
|
(0, doc_query_1.registerQueryDocumentation)('call-context', {
|
|
40
41
|
name: 'Call-Context Query',
|
|
41
42
|
type: 'active',
|
|
@@ -333,6 +334,22 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
|
333
334
|
This query provides access to the current configuration of the flowR instance. See the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on what the configuration represents.`;
|
|
334
335
|
}
|
|
335
336
|
});
|
|
337
|
+
(0, doc_query_1.registerQueryDocumentation)('df-shape', {
|
|
338
|
+
name: 'Dataframe Shape Inference Query',
|
|
339
|
+
type: 'active',
|
|
340
|
+
shortDescription: 'Returns the shapes inferred for all dataframes in the code.',
|
|
341
|
+
functionName: df_shape_query_executor_1.executeDfShapeQuery.name,
|
|
342
|
+
functionFile: '../queries/catalog/df-shape-query/df-shape-query-format.ts',
|
|
343
|
+
buildExplanation: async (shell) => {
|
|
344
|
+
const exampleCode = 'x <- data.frame(a=1:3)\nfilter(x, FALSE)';
|
|
345
|
+
return `
|
|
346
|
+
This query infers all shapes of dataframes within the code. For example, you can use:
|
|
347
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
348
|
+
type: 'df-shape'
|
|
349
|
+
}], { showCode: true, collapseQuery: true })}
|
|
350
|
+
`;
|
|
351
|
+
}
|
|
352
|
+
});
|
|
336
353
|
(0, doc_query_1.registerQueryDocumentation)('compound', {
|
|
337
354
|
name: 'Compound Query',
|
|
338
355
|
type: 'virtual',
|
|
@@ -564,9 +581,8 @@ ${await (0, doc_cfg_1.printCfgCode)(shell, exampleCode, { showCode: false, prefi
|
|
|
564
581
|
functionName: location_map_query_executor_1.executeLocationMapQuery.name,
|
|
565
582
|
functionFile: '../queries/catalog/location-map-query/location-map-query-executor.ts',
|
|
566
583
|
buildExplanation: async (shell) => {
|
|
567
|
-
const types = (0, doc_types_1.
|
|
584
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
568
585
|
files: [path_1.default.resolve('./src/util/range.ts')],
|
|
569
|
-
typeName: 'SourceRange'
|
|
570
586
|
});
|
|
571
587
|
const exampleCode = 'x + 1\nx * 2';
|
|
572
588
|
return `
|
|
@@ -14,6 +14,7 @@ const doc_repl_1 = require("./doc-util/doc-repl");
|
|
|
14
14
|
const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
|
|
15
15
|
const doc_general_1 = require("./doc-util/doc-general");
|
|
16
16
|
const doc_dfg_1 = require("./doc-util/doc-dfg");
|
|
17
|
+
const doc_query_1 = require("./doc-util/doc-query");
|
|
17
18
|
async function getText(shell) {
|
|
18
19
|
const dateOptions = { year: 'numeric', month: 'short', day: 'numeric' };
|
|
19
20
|
return `
|
|
@@ -31,6 +32,28 @@ available for [VSCode](${doc_files_1.FlowrVsCode}), [Positron](${doc_files_1.Flo
|
|
|
31
32
|
and [Docker](${doc_files_1.FlowrDockerRef}).
|
|
32
33
|
It offers a wide variety of features, for example:
|
|
33
34
|
|
|
35
|
+
* 🐞 **code linting**\\
|
|
36
|
+
Analyze your R scripts for common issues and potential bugs (see the [wiki page](${doc_files_1.FlowrGithubBaseRef}/flowr/wiki/Linter) for more information on the currently supported linters).
|
|
37
|
+
|
|
38
|
+
${(0, doc_general_1.prefixLines)((0, doc_structure_1.details)('Example: Linting code with flowR', `To lint your code, you can use the [REPL](${doc_files_1.FlowrWikiBaseRef}/Interface#using-the-repl) or the [Visual Studio Code extension](${doc_files_1.FlowrVsCode}) (see [vscode-flowr#283](https://github.com/flowr-analysis/vscode-flowr/pull/283)).
|
|
39
|
+
|
|
40
|
+
${await (async () => {
|
|
41
|
+
const code = 'read.csv("/root/x.txt")';
|
|
42
|
+
const res = await (0, doc_query_1.showQuery)(shell, code, [{ type: 'linter' }], { showCode: false, collapseQuery: true, collapseResult: false });
|
|
43
|
+
return await (0, doc_repl_1.documentReplSession)(shell, [{
|
|
44
|
+
command: `:query @linter ${JSON.stringify(code)}`,
|
|
45
|
+
description: `
|
|
46
|
+
The linter will analyze the code and return any issues found.
|
|
47
|
+
Formatted more nicely, this returns:
|
|
48
|
+
|
|
49
|
+
${res}
|
|
50
|
+
`
|
|
51
|
+
}]);
|
|
52
|
+
})()}
|
|
53
|
+
|
|
54
|
+
`), ' ')}
|
|
55
|
+
|
|
56
|
+
|
|
34
57
|
* 🍕 **program slicing**\\
|
|
35
58
|
Given a point of interest like the visualization of a plot, _flowR_ reduces the program to just the parts which are relevant
|
|
36
59
|
for the computation of the point of interest.
|
|
@@ -117,7 +140,7 @@ You can enter ${(0, doc_cli_option_1.getReplCommand)('help')} to gain more infor
|
|
|
117
140
|
|
|
118
141
|
<summary>Example REPL session</summary>
|
|
119
142
|
|
|
120
|
-

|
|
143
|
+

|
|
121
144
|
|
|
122
145
|
</details>
|
|
123
146
|
|
|
@@ -15,9 +15,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
15
15
|
const flowr_search_executor_1 = require("../search/flowr-search-executor");
|
|
16
16
|
async function getText(shell) {
|
|
17
17
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
18
|
-
const types = (0, doc_types_1.
|
|
18
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
19
19
|
rootFolder: path_1.default.resolve('./src/search/'),
|
|
20
|
-
typeName: 'FlowrSearchGenerator',
|
|
21
20
|
inlineTypes: doc_types_1.mermaidHide
|
|
22
21
|
});
|
|
23
22
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'search API', rVersion: rversion })}
|
|
@@ -3,7 +3,9 @@ import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/de
|
|
|
3
3
|
import type { DataflowInformation } from '../dataflow/info';
|
|
4
4
|
import type { LintingResults } from './linter-format';
|
|
5
5
|
import type { DeepPartial } from 'ts-essentials';
|
|
6
|
+
import type { FlowrConfigOptions } from '../config';
|
|
6
7
|
export declare function executeLintingRule<Name extends LintingRuleNames>(ruleName: Name, input: {
|
|
7
8
|
normalize: NormalizedAst;
|
|
8
9
|
dataflow: DataflowInformation;
|
|
9
|
-
|
|
10
|
+
config: FlowrConfigOptions;
|
|
11
|
+
}, lintingRuleConfig?: DeepPartial<LintingRuleConfig<Name>>): LintingResults<Name>;
|
|
@@ -4,9 +4,10 @@ exports.executeLintingRule = executeLintingRule;
|
|
|
4
4
|
const linter_rules_1 = require("./linter-rules");
|
|
5
5
|
const flowr_search_executor_1 = require("../search/flowr-search-executor");
|
|
6
6
|
const flowr_search_1 = require("../search/flowr-search");
|
|
7
|
-
|
|
7
|
+
const objects_1 = require("../util/objects");
|
|
8
|
+
function executeLintingRule(ruleName, input, lintingRuleConfig) {
|
|
8
9
|
const rule = linter_rules_1.LintingRules[ruleName];
|
|
9
|
-
const fullConfig =
|
|
10
|
+
const fullConfig = (0, objects_1.deepMergeObject)(rule.info.defaultConfig, lintingRuleConfig);
|
|
10
11
|
const ruleSearch = rule.createSearch(fullConfig, input);
|
|
11
12
|
const searchStart = Date.now();
|
|
12
13
|
const searchResult = (0, flowr_search_executor_1.runSearch)(ruleSearch, input);
|
|
@@ -6,7 +6,28 @@ import type { TransformerNames } from '../search/search-executor/search-transfor
|
|
|
6
6
|
import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
7
7
|
import type { LintingRuleConfig, LintingRuleMetadata, LintingRuleNames, LintingRuleResult } from './linter-rules';
|
|
8
8
|
import type { DataflowInformation } from '../dataflow/info';
|
|
9
|
-
import type {
|
|
9
|
+
import type { FlowrConfigOptions } from '../config';
|
|
10
|
+
import type { DeepPartial, DeepReadonly } from 'ts-essentials';
|
|
11
|
+
import type { LintingRuleTag } from './linter-tags';
|
|
12
|
+
import type { SourceRange } from '../util/range';
|
|
13
|
+
export interface LinterRuleInformation<Config extends MergeableRecord = never> {
|
|
14
|
+
/** Human-Readable name of the linting rule. */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/**
|
|
17
|
+
* The default config for this linting rule.
|
|
18
|
+
* This config is combined with the user config when executing the rule.
|
|
19
|
+
*/
|
|
20
|
+
readonly defaultConfig: NoInfer<DeepReadonly<Config>>;
|
|
21
|
+
/**
|
|
22
|
+
* A short list of tags that describe and categorize the linting rule.
|
|
23
|
+
*/
|
|
24
|
+
readonly tags: readonly LintingRuleTag[];
|
|
25
|
+
/**
|
|
26
|
+
* A short description of the linting rule.
|
|
27
|
+
* This is used to display the rule in the UI and to provide a brief overview of what the rule does.
|
|
28
|
+
*/
|
|
29
|
+
readonly description: string;
|
|
30
|
+
}
|
|
10
31
|
/**
|
|
11
32
|
* The base interface for a linting rule, which contains all of its relevant settings.
|
|
12
33
|
* The registry of valid linting rules is stored in {@link LintingRules}.
|
|
@@ -27,26 +48,54 @@ export interface LintingRule<Result extends LintingResult, Metadata extends Merg
|
|
|
27
48
|
readonly processSearchResult: (elements: FlowrSearchElements<Info, Elements>, config: Config, data: {
|
|
28
49
|
normalize: NormalizedAst;
|
|
29
50
|
dataflow: DataflowInformation;
|
|
51
|
+
config: FlowrConfigOptions;
|
|
30
52
|
}) => {
|
|
31
53
|
results: Result[];
|
|
32
54
|
'.meta': Metadata;
|
|
33
55
|
};
|
|
34
56
|
/**
|
|
35
|
-
* A
|
|
36
|
-
* By default, the {@link LintingResult#certainty} is automatically printed alongside this information.
|
|
57
|
+
* A set of functions used to pretty-print the given linting result.
|
|
58
|
+
* By default, the {@link LintingResult#certainty} and whether any {@link LintingResult#quickFix} values are available is automatically printed alongside this information.
|
|
59
|
+
*/
|
|
60
|
+
readonly prettyPrint: {
|
|
61
|
+
[C in LintingPrettyPrintContext]: (result: Result, metadata: Metadata) => string;
|
|
62
|
+
};
|
|
63
|
+
readonly info: LinterRuleInformation<NoInfer<Config>>;
|
|
64
|
+
}
|
|
65
|
+
interface BaseQuickFix {
|
|
66
|
+
/**
|
|
67
|
+
* The type of the quick fix.
|
|
37
68
|
*/
|
|
38
|
-
readonly
|
|
69
|
+
readonly type: string;
|
|
39
70
|
/**
|
|
40
|
-
*
|
|
41
|
-
* The default config is combined with the user config when executing the rule.
|
|
71
|
+
* A short, human-readable description of the quick fix.
|
|
42
72
|
*/
|
|
43
|
-
readonly
|
|
73
|
+
readonly description: string;
|
|
74
|
+
/**
|
|
75
|
+
* The range of the text that should be replaced.
|
|
76
|
+
*/
|
|
77
|
+
readonly range: SourceRange;
|
|
44
78
|
}
|
|
79
|
+
export interface LintQuickFixReplacement extends BaseQuickFix {
|
|
80
|
+
readonly type: 'replace';
|
|
81
|
+
/**
|
|
82
|
+
* The text that should replace the given range.
|
|
83
|
+
*/
|
|
84
|
+
readonly replacement: string;
|
|
85
|
+
}
|
|
86
|
+
export interface LintQuickFixRemove extends BaseQuickFix {
|
|
87
|
+
readonly type: 'remove';
|
|
88
|
+
}
|
|
89
|
+
export type LintQuickFix = LintQuickFixReplacement | LintQuickFixRemove;
|
|
45
90
|
/**
|
|
46
91
|
* A linting result for a single linting rule match.
|
|
47
92
|
*/
|
|
48
93
|
export interface LintingResult {
|
|
49
94
|
readonly certainty: LintingCertainty;
|
|
95
|
+
/**
|
|
96
|
+
* If available, what to do to fix the linting result.
|
|
97
|
+
*/
|
|
98
|
+
readonly quickFix?: LintQuickFix[];
|
|
50
99
|
}
|
|
51
100
|
export interface ConfiguredLintingRule<Name extends LintingRuleNames = LintingRuleNames> {
|
|
52
101
|
readonly name: Name;
|
|
@@ -60,6 +109,17 @@ export interface LintingResults<Name extends LintingRuleNames> {
|
|
|
60
109
|
};
|
|
61
110
|
}
|
|
62
111
|
export declare enum LintingCertainty {
|
|
112
|
+
/**
|
|
113
|
+
* The linting rule cannot say for sure whether the result is correct or not.
|
|
114
|
+
*/
|
|
63
115
|
Maybe = "maybe",
|
|
116
|
+
/**
|
|
117
|
+
* The linting rule is certain that the reported lint is real.
|
|
118
|
+
*/
|
|
64
119
|
Definitely = "definitely"
|
|
65
120
|
}
|
|
121
|
+
export declare enum LintingPrettyPrintContext {
|
|
122
|
+
Query = "query",
|
|
123
|
+
Full = "full"
|
|
124
|
+
}
|
|
125
|
+
export {};
|
package/linter/linter-format.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LintingCertainty = void 0;
|
|
3
|
+
exports.LintingPrettyPrintContext = exports.LintingCertainty = void 0;
|
|
4
4
|
var LintingCertainty;
|
|
5
5
|
(function (LintingCertainty) {
|
|
6
|
+
/**
|
|
7
|
+
* The linting rule cannot say for sure whether the result is correct or not.
|
|
8
|
+
*/
|
|
6
9
|
LintingCertainty["Maybe"] = "maybe";
|
|
10
|
+
/**
|
|
11
|
+
* The linting rule is certain that the reported lint is real.
|
|
12
|
+
*/
|
|
7
13
|
LintingCertainty["Definitely"] = "definitely";
|
|
8
14
|
})(LintingCertainty || (exports.LintingCertainty = LintingCertainty = {}));
|
|
15
|
+
var LintingPrettyPrintContext;
|
|
16
|
+
(function (LintingPrettyPrintContext) {
|
|
17
|
+
LintingPrettyPrintContext["Query"] = "query";
|
|
18
|
+
LintingPrettyPrintContext["Full"] = "full";
|
|
19
|
+
})(LintingPrettyPrintContext || (exports.LintingPrettyPrintContext = LintingPrettyPrintContext = {}));
|
|
9
20
|
//# sourceMappingURL=linter-format.js.map
|