@eagleoutice/flowr 2.2.14 → 2.2.16
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 +210 -6
- package/benchmark/slicer.d.ts +3 -1
- package/benchmark/slicer.js +8 -5
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +2 -2
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +4 -1
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +7 -8
- package/cli/common/options.js +2 -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 +3 -3
- 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 +5 -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 +12 -10
- package/config.js +27 -43
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/cfg-dead-code.d.ts +4 -0
- package/control-flow/cfg-dead-code.js +124 -0
- package/control-flow/cfg-simplification.d.ts +19 -6
- package/control-flow/cfg-simplification.js +23 -19
- package/control-flow/control-flow-graph.d.ts +3 -1
- package/control-flow/control-flow-graph.js +5 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +9 -7
- package/control-flow/dfg-cfg-guided-visitor.js +16 -5
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +63 -59
- package/control-flow/semantic-cfg-guided-visitor.d.ts +36 -9
- package/control-flow/semantic-cfg-guided-visitor.js +73 -20
- package/control-flow/simple-visitor.d.ts +4 -0
- package/control-flow/simple-visitor.js +14 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
- 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 +4 -3
- package/dataflow/environments/built-in.d.ts +16 -1
- package/dataflow/environments/built-in.js +11 -5
- package/dataflow/environments/default-builtin-config.js +5 -3
- 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/environments/resolve-by-name.d.ts +0 -36
- package/dataflow/environments/resolve-by-name.js +0 -240
- package/dataflow/eval/resolve/alias-tracking.d.ts +92 -0
- package/dataflow/eval/resolve/alias-tracking.js +352 -0
- 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 +37 -0
- package/dataflow/eval/resolve/resolve.js +95 -0
- package/dataflow/eval/values/general.d.ts +27 -0
- package/dataflow/eval/values/general.js +73 -0
- package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
- package/dataflow/eval/values/intervals/interval-constants.js +27 -0
- package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
- package/dataflow/eval/values/logical/logical-constants.js +31 -0
- package/dataflow/eval/values/r-value.d.ts +58 -0
- package/dataflow/eval/values/r-value.js +90 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
- package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
- package/dataflow/eval/values/sets/set-constants.js +34 -0
- package/dataflow/eval/values/string/string-constants.d.ts +8 -0
- package/dataflow/eval/values/string/string-constants.js +45 -0
- package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
- package/dataflow/eval/values/vectors/vector-constants.js +35 -0
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/graph/unknown-replacement.d.ts +11 -0
- package/dataflow/graph/unknown-replacement.js +12 -0
- package/dataflow/graph/unknown-side-effect.d.ts +7 -0
- package/dataflow/graph/unknown-side-effect.js +13 -0
- 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 +8 -5
- 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 +15 -13
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +20 -18
- 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 +5 -4
- 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 +11 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +26 -29
- 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 +23 -0
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -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.d.ts +6 -3
- package/documentation/doc-util/doc-query.js +6 -3
- 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 +10 -11
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +14 -13
- package/documentation/print-engines-wiki.js +2 -3
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +1 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +219 -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 +81 -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 +155 -16
- package/linter/linter-rules.js +12 -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/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 +164 -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 +4 -1
- 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 +3 -0
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
- 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 -115
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- 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 +17 -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 +4 -4
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
- 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 +75 -15
- 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 +18 -9
- 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 +32 -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/criterion/parse.d.ts +8 -0
- package/slicing/criterion/parse.js +20 -0
- 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/objects.d.ts +5 -4
- 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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const log_1 = require("../../test/functionality/_helper/log");
|
|
7
|
+
const doc_types_1 = require("./doc-util/doc-types");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const linter_tags_1 = require("../linter/linter-tags");
|
|
10
|
+
const doc_general_1 = require("./doc-util/doc-general");
|
|
11
|
+
const doc_files_1 = require("./doc-util/doc-files");
|
|
12
|
+
const linter_rules_1 = require("../linter/linter-rules");
|
|
13
|
+
/* this prints the yaml configuration for the GitHub issue template to request a new linter rule / an update */
|
|
14
|
+
function summarizeIfTooLong(text, maxLength = 52) {
|
|
15
|
+
if (text.length <= maxLength) {
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
return text.slice(0, maxLength - 1) + '…';
|
|
19
|
+
}
|
|
20
|
+
function getText() {
|
|
21
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
22
|
+
rootFolder: path_1.default.resolve('./src/linter/')
|
|
23
|
+
});
|
|
24
|
+
return `
|
|
25
|
+
name: Linting Rule
|
|
26
|
+
description: Suggest either a new linting rule or an improvement to an existing one.
|
|
27
|
+
title: "[Linter]: "
|
|
28
|
+
labels: ["flowr linter"]
|
|
29
|
+
body:
|
|
30
|
+
- type: markdown
|
|
31
|
+
attributes:
|
|
32
|
+
value: |
|
|
33
|
+
Thank you for suggesting a new linting rule or an improvement to an existing one. Please provide as much detail as possible to help us understand your request. See the [Linter Wiki Page](${doc_files_1.FlowrWikiBaseRef}/Linter) for more information.
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: description
|
|
36
|
+
attributes:
|
|
37
|
+
label: Description
|
|
38
|
+
description: |
|
|
39
|
+
Please provide a detailed description of the linting rule you are suggesting or the improvement you would like to see. Include examples if possible.
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
- type: dropdown
|
|
43
|
+
id: linting-rule
|
|
44
|
+
attributes:
|
|
45
|
+
label: Linting Rule
|
|
46
|
+
description: |
|
|
47
|
+
Select the linting rule that you are suggesting or improving. If it is a new rule, select "New Rule".
|
|
48
|
+
options:
|
|
49
|
+
- New Rule
|
|
50
|
+
${(0, doc_general_1.prefixLines)(Object.keys(linter_rules_1.LintingRules).sort().map(name => {
|
|
51
|
+
const rule = linter_rules_1.LintingRules[name];
|
|
52
|
+
return `- ${rule.info.name}`;
|
|
53
|
+
}).join('\n'), ' ')}
|
|
54
|
+
default: 0
|
|
55
|
+
- type: checkboxes
|
|
56
|
+
id: tags
|
|
57
|
+
attributes:
|
|
58
|
+
label: Meta Information
|
|
59
|
+
description: Select any tags that you think apply to the linting rule you are suggesting. If you try to suggest a new linting rule, please only select those that you think apply after your suggestions.
|
|
60
|
+
options:
|
|
61
|
+
${(0, doc_general_1.prefixLines)(Object.entries(linter_tags_1.LintingRuleTag).map(([name]) => {
|
|
62
|
+
return `- label: '**${name}**: ${summarizeIfTooLong((0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, types.info).replaceAll(/\n/g, ' ').replaceAll('\'', '\\\'').trim())}'\n required: false`;
|
|
63
|
+
}).join('\n'), ' ')}
|
|
64
|
+
`.trim();
|
|
65
|
+
}
|
|
66
|
+
/** if we run this script, we want a Markdown representation of the capabilities */
|
|
67
|
+
if (require.main === module) {
|
|
68
|
+
(0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
|
|
69
|
+
console.log(getText());
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=print-linter-issue.js.map
|
|
@@ -12,48 +12,147 @@ 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
|
+
function rule(shell, name, configType, ruleType, testfile, example, types) {
|
|
112
|
+
const rule = linter_rules_1.LintingRules[name];
|
|
113
|
+
const tags = rule.info.tags.toSorted((a, b) => {
|
|
114
|
+
// sort but specials first
|
|
115
|
+
if (a === b) {
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
if (SpecialTagColors[a] && SpecialTagColors[b]) {
|
|
119
|
+
return SpecialTagColors[b].localeCompare(SpecialTagColors[a]);
|
|
120
|
+
}
|
|
121
|
+
else if (SpecialTagColors[a]) {
|
|
122
|
+
return -1;
|
|
123
|
+
}
|
|
124
|
+
else if (SpecialTagColors[b]) {
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
return a.localeCompare(b);
|
|
128
|
+
}).map(t => makeTagBadge(t, types)).join(' ');
|
|
129
|
+
if (format === 'short') {
|
|
130
|
+
ruleExplanations.set(name, () => Promise.resolve(`
|
|
131
|
+
**[${rule.info.name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name}):** ${rule.info.description} [see ${(0, doc_types_1.shortLinkFile)(ruleType, types)}]\\
|
|
132
|
+
${tags}
|
|
34
133
|
|
|
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}
|
|
134
|
+
`.trim()));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
ruleExplanations.set(name, async () => `
|
|
47
138
|
|
|
48
|
-
|
|
139
|
+
${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linter', rVersion })}
|
|
140
|
+
${(0, doc_structure_1.section)(rule.info.name + ` <sup>[<a href="${doc_files_1.FlowrWikiBaseRef}/Linter">overview</a>]</sup>`, 2, name)}
|
|
49
141
|
|
|
50
|
-
|
|
142
|
+
${tags}
|
|
143
|
+
|
|
144
|
+
${rule.info.description}\\
|
|
145
|
+
_This linting rule is implemented in ${(0, doc_types_1.shortLinkFile)(ruleType, types)}._
|
|
51
146
|
|
|
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
147
|
|
|
54
|
-
|
|
148
|
+
### Configuration
|
|
55
149
|
|
|
56
|
-
|
|
150
|
+
Linting rules can be configured by passing a configuration object to the linter query as shown in the example below.
|
|
151
|
+
The \`${name}\` rule accepts the following configuration options:
|
|
152
|
+
|
|
153
|
+
${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')}
|
|
154
|
+
|
|
155
|
+
### Examples
|
|
57
156
|
|
|
58
157
|
${(0, doc_code_1.codeBlock)('r', example)}
|
|
59
158
|
|
|
@@ -61,16 +160,102 @@ The linting query can be used to run this rule on the above example:
|
|
|
61
160
|
|
|
62
161
|
${await (0, doc_query_1.showQuery)(shell, example, [{ type: 'linter', rules: [{ name, config: {} }] }], { collapseQuery: true })}
|
|
63
162
|
|
|
64
|
-
|
|
65
|
-
|
|
163
|
+
${buildSamplesFromLinterTestCases(shell, `${testfile}.test.ts`)}
|
|
164
|
+
|
|
165
|
+
`.trim());
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return ruleExplanations;
|
|
169
|
+
}
|
|
170
|
+
function getAllLintingRulesWitTag(tag) {
|
|
171
|
+
return Object.entries(linter_rules_1.LintingRules).filter(([_, rule]) => rule.info.tags.includes(tag)).map(([name]) => name);
|
|
172
|
+
}
|
|
173
|
+
function linkToRule(name) {
|
|
174
|
+
return `[${name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name})`;
|
|
175
|
+
}
|
|
176
|
+
async function getTextMainPage(shell, tagTypes, rVersion) {
|
|
177
|
+
const rules = registerRules(rVersion, shell, tagTypes.info);
|
|
178
|
+
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linter', rVersion })}
|
|
179
|
+
|
|
180
|
+
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).
|
|
181
|
+
For example:
|
|
182
|
+
|
|
183
|
+
${await (async () => {
|
|
184
|
+
const code = 'read.csv("/root/x.txt")';
|
|
185
|
+
const res = await (0, doc_query_1.showQuery)(shell, code, [{ type: 'linter' }], { showCode: false, collapseQuery: true, collapseResult: false });
|
|
186
|
+
return await (0, doc_repl_1.documentReplSession)(shell, [{
|
|
187
|
+
command: `:query @linter ${JSON.stringify(code)}`,
|
|
188
|
+
description: `
|
|
189
|
+
The linter will analyze the code and return any issues found.
|
|
190
|
+
Formatted more nicely, this returns:
|
|
191
|
+
|
|
192
|
+
${res}
|
|
193
|
+
`
|
|
194
|
+
}]);
|
|
195
|
+
})()}
|
|
196
|
+
|
|
197
|
+
${(0, doc_structure_1.section)('Linting Rules', 2, 'linting-rules')}
|
|
198
|
+
|
|
199
|
+
The following linting rules are available:
|
|
200
|
+
|
|
201
|
+
${await (async () => {
|
|
202
|
+
let result = '';
|
|
203
|
+
for (const k of Object.keys(linter_rules_1.LintingRules).sort()) {
|
|
204
|
+
const rule = rules.get(k);
|
|
205
|
+
(0, assert_1.guard)(rule !== undefined, `Linting rule ${k} is not documented!`);
|
|
206
|
+
result += '\n\n' + await rule();
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
})()}
|
|
210
|
+
|
|
211
|
+
${(0, doc_structure_1.section)('Tags', 2, 'tags')}
|
|
212
|
+
|
|
213
|
+
We use tags to categorize linting rules. The following tags are available:
|
|
214
|
+
|
|
215
|
+
| Tag/Badge   | Description |
|
|
216
|
+
| --- | :-- |
|
|
217
|
+
${Object.entries(linter_tags_1.LintingRuleTag).map(([name, tag]) => {
|
|
218
|
+
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_'}) | `;
|
|
219
|
+
}).join('\n')}
|
|
220
|
+
|
|
221
|
+
`.trim();
|
|
222
|
+
}
|
|
223
|
+
async function getRulesPages(shell, tagTypes, rVersion) {
|
|
224
|
+
const rules = registerRules(rVersion, shell, tagTypes.info, 'long');
|
|
225
|
+
const result = {};
|
|
226
|
+
for (const [name, rule] of rules) {
|
|
227
|
+
const filepath = path_1.default.resolve('./wiki', `lint-${name}.md`);
|
|
228
|
+
result[filepath] = await rule();
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
/** Maps file-names to their content, the 'main' file is named 'main' */
|
|
233
|
+
async function getTexts(shell) {
|
|
234
|
+
const rVersion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
235
|
+
const tagTypes = (0, doc_types_1.getTypesFromFolder)({
|
|
236
|
+
rootFolder: path_1.default.resolve('./src/linter/'),
|
|
237
|
+
inlineTypes: doc_types_1.mermaidHide
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
'main': await getTextMainPage(shell, tagTypes, rVersion),
|
|
241
|
+
...await getRulesPages(shell, tagTypes, rVersion)
|
|
242
|
+
};
|
|
66
243
|
}
|
|
244
|
+
/* As an intermediary solution to changing the wiki system, we make this script generate separate files for each linter rule using fixed paths */
|
|
67
245
|
if (require.main === module) {
|
|
68
246
|
(0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
|
|
69
247
|
const shell = new shell_1.RShell();
|
|
70
|
-
void
|
|
71
|
-
console.log(
|
|
248
|
+
void (getTexts(shell).then(data => {
|
|
249
|
+
console.log(data['main']);
|
|
250
|
+
for (const [file, content] of Object.entries(data)) {
|
|
251
|
+
if (file === 'main') {
|
|
252
|
+
continue; // main is printed above
|
|
253
|
+
}
|
|
254
|
+
const filepath = path_1.default.resolve('./wiki', file);
|
|
255
|
+
(0, doc_print_1.writeWikiTo)(content, filepath);
|
|
256
|
+
}
|
|
72
257
|
}).finally(() => {
|
|
73
258
|
shell.close();
|
|
74
|
-
});
|
|
259
|
+
}));
|
|
75
260
|
}
|
|
76
261
|
//# 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>
|
|
@@ -34,6 +34,8 @@ const flowr_search_builder_1 = require("../search/flowr-search-builder");
|
|
|
34
34
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
35
35
|
const doc_types_1 = require("./doc-util/doc-types");
|
|
36
36
|
const path_1 = __importDefault(require("path"));
|
|
37
|
+
const control_flow_query_executor_1 = require("../queries/catalog/control-flow-query/control-flow-query-executor");
|
|
38
|
+
const doc_cfg_1 = require("./doc-util/doc-cfg");
|
|
37
39
|
(0, doc_query_1.registerQueryDocumentation)('call-context', {
|
|
38
40
|
name: 'Call-Context Query',
|
|
39
41
|
type: 'active',
|
|
@@ -477,6 +479,84 @@ Here, \`resolveValue\` tells the dependency query to resolve the value of this a
|
|
|
477
479
|
`;
|
|
478
480
|
}
|
|
479
481
|
});
|
|
482
|
+
(0, doc_query_1.registerQueryDocumentation)('linter', {
|
|
483
|
+
name: 'Linter Query',
|
|
484
|
+
type: 'active',
|
|
485
|
+
shortDescription: 'Lints a given R script for common issues.',
|
|
486
|
+
functionName: dependencies_query_executor_1.executeDependenciesQuery.name,
|
|
487
|
+
functionFile: '../queries/catalog/linter-query/linter-query-executor.ts',
|
|
488
|
+
buildExplanation: async (shell) => {
|
|
489
|
+
const exampleCode = 'read.csv("i_do_not_exist.csv")';
|
|
490
|
+
return `
|
|
491
|
+
This query lints a given R script for common issues, such as missing files, unused variables, and more.
|
|
492
|
+
|
|
493
|
+
In other words, if you have a script simply reading: \`${exampleCode}\`, the following query returns all smells detected:
|
|
494
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
495
|
+
type: 'linter'
|
|
496
|
+
}], { showCode: false, collapseQuery: true })}
|
|
497
|
+
|
|
498
|
+
You can also configure which rules to apply and what settings to use for these rules.
|
|
499
|
+
We welcome any feedback and suggestions for new rules on this (consider opening a [new issue](${doc_issue_1.NewIssueUrl})).
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
(0, doc_query_1.registerQueryDocumentation)('control-flow', {
|
|
504
|
+
name: 'Control-Flow Query',
|
|
505
|
+
type: 'active',
|
|
506
|
+
shortDescription: 'Provides the control-flow of the program.',
|
|
507
|
+
functionName: control_flow_query_executor_1.executeControlFlowQuery.name,
|
|
508
|
+
functionFile: '../queries/catalog/control-flow-query/control-flow-query-executor.ts',
|
|
509
|
+
buildExplanation: async (shell) => {
|
|
510
|
+
const exampleCode = 'if(TRUE) 1 else 2';
|
|
511
|
+
return `
|
|
512
|
+
This control-flow query provides you access to the control flow graph.
|
|
513
|
+
|
|
514
|
+
In other words, if you have a script simply reading: \`${exampleCode}\`, the following query returns the CFG:
|
|
515
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
516
|
+
type: 'control-flow'
|
|
517
|
+
}], { showCode: false, collapseQuery: true, collapseResult: true })}
|
|
518
|
+
|
|
519
|
+
You can also overwrite the simplification passes to tune the perspective. for example, if you want to have basic blocks:
|
|
520
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
521
|
+
type: 'control-flow',
|
|
522
|
+
config: {
|
|
523
|
+
simplificationPasses: ['unique-cf-sets', 'to-basic-blocks']
|
|
524
|
+
}
|
|
525
|
+
}], { showCode: false, collapseResult: true })}
|
|
526
|
+
|
|
527
|
+
this produces:
|
|
528
|
+
|
|
529
|
+
${await (0, doc_cfg_1.printCfgCode)(shell, exampleCode, { showCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'] })}
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
If, on the other hand, you want to prune dead code edges:
|
|
533
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
534
|
+
type: 'control-flow',
|
|
535
|
+
config: {
|
|
536
|
+
simplificationPasses: ['unique-cf-sets', 'analyze-dead-code']
|
|
537
|
+
}
|
|
538
|
+
}], { showCode: false, collapseResult: true })}
|
|
539
|
+
|
|
540
|
+
this produces:
|
|
541
|
+
|
|
542
|
+
${await (0, doc_cfg_1.printCfgCode)(shell, exampleCode, { showCode: false, prefix: 'flowchart RL\n', simplifications: ['analyze-dead-code'] })}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
Or, completely remove dead code:
|
|
546
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
547
|
+
type: 'control-flow',
|
|
548
|
+
config: {
|
|
549
|
+
simplificationPasses: ['unique-cf-sets', 'analyze-dead-code', 'remove-dead-code']
|
|
550
|
+
}
|
|
551
|
+
}], { showCode: false, collapseResult: true })}
|
|
552
|
+
|
|
553
|
+
this produces:
|
|
554
|
+
|
|
555
|
+
${await (0, doc_cfg_1.printCfgCode)(shell, exampleCode, { showCode: false, prefix: 'flowchart RL\n', simplifications: ['analyze-dead-code', 'remove-dead-code'] })}
|
|
556
|
+
|
|
557
|
+
`;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
480
560
|
(0, doc_query_1.registerQueryDocumentation)('location-map', {
|
|
481
561
|
name: 'Location Map Query',
|
|
482
562
|
type: 'active',
|
|
@@ -484,9 +564,8 @@ Here, \`resolveValue\` tells the dependency query to resolve the value of this a
|
|
|
484
564
|
functionName: location_map_query_executor_1.executeLocationMapQuery.name,
|
|
485
565
|
functionFile: '../queries/catalog/location-map-query/location-map-query-executor.ts',
|
|
486
566
|
buildExplanation: async (shell) => {
|
|
487
|
-
const types = (0, doc_types_1.
|
|
567
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
488
568
|
files: [path_1.default.resolve('./src/util/range.ts')],
|
|
489
|
-
typeName: 'SourceRange'
|
|
490
569
|
});
|
|
491
570
|
const exampleCode = 'x + 1\nx * 2';
|
|
492
571
|
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);
|