@eagleoutice/flowr 2.2.15 → 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 +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 +12 -10
- package/config.js +26 -42
- 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 +1 -0
- package/control-flow/control-flow-graph.js +4 -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 +19 -1
- package/control-flow/semantic-cfg-guided-visitor.js +23 -3
- 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 +7 -1
- package/dataflow/environments/built-in.js +2 -2
- 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 +9 -6
- 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 +18 -15
- package/dataflow/eval/resolve/resolve.js +20 -18
- 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 +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +15 -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 +3 -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 +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 +1 -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 +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/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 +15 -15
- 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/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
|
@@ -32,6 +32,7 @@ const semantic_cfg_guided_visitor_1 = require("../control-flow/semantic-cfg-guid
|
|
|
32
32
|
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
33
33
|
const edge_1 = require("../dataflow/graph/edge");
|
|
34
34
|
const assert_1 = require("../util/assert");
|
|
35
|
+
const config_1 = require("../config");
|
|
35
36
|
const CfgLongExample = `f <- function(a, b = 3) {
|
|
36
37
|
if(a > b) {
|
|
37
38
|
return(a * b);
|
|
@@ -103,8 +104,8 @@ class CollectNumbersDataflowVisitor extends dfg_cfg_guided_visitor_1.DataflowAwa
|
|
|
103
104
|
}
|
|
104
105
|
class CollectSourcesSemanticVisitor extends semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor {
|
|
105
106
|
sources = [];
|
|
106
|
-
constructor(controlFlow, normalizedAst, dataflow) {
|
|
107
|
-
super({ controlFlow, normalizedAst, dfg: dataflow, defaultVisitingOrder: 'forward' });
|
|
107
|
+
constructor(controlFlow, normalizedAst, dataflow, config) {
|
|
108
|
+
super({ controlFlow, normalizedAst, dfg: dataflow, flowrConfig: config, defaultVisitingOrder: 'forward' });
|
|
108
109
|
}
|
|
109
110
|
onAssignmentCall({ source }) {
|
|
110
111
|
if (source) {
|
|
@@ -117,14 +118,12 @@ class CollectSourcesSemanticVisitor extends semantic_cfg_guided_visitor_1.Semant
|
|
|
117
118
|
}
|
|
118
119
|
async function getText(shell) {
|
|
119
120
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
120
|
-
const types = (0, doc_types_1.
|
|
121
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
121
122
|
rootFolder: path_1.default.resolve('./src'),
|
|
122
|
-
typeName: 'RNode',
|
|
123
123
|
inlineTypes: doc_types_1.mermaidHide
|
|
124
124
|
});
|
|
125
|
-
const testTypes = (0, doc_types_1.
|
|
125
|
+
const testTypes = (0, doc_types_1.getTypesFromFolder)({
|
|
126
126
|
rootFolder: path_1.default.resolve('./test'),
|
|
127
|
-
typeName: 'assertCfg',
|
|
128
127
|
inlineTypes: doc_types_1.mermaidHide
|
|
129
128
|
});
|
|
130
129
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'control flow graph', rVersion: rversion })}
|
|
@@ -500,7 +499,7 @@ Executing it with the CFG and Dataflow of the expression \`x <- 2; 3 -> x; assig
|
|
|
500
499
|
|
|
501
500
|
${await (async () => {
|
|
502
501
|
const res = await (0, doc_cfg_1.getCfg)(shell, 'x <- 2; 3 -> x; assign("x", 42 + 21)');
|
|
503
|
-
const visitor = new CollectSourcesSemanticVisitor(res.info, res.ast, res.dataflow.graph);
|
|
502
|
+
const visitor = new CollectSourcesSemanticVisitor(res.info, res.ast, res.dataflow.graph, config_1.defaultConfigOptions);
|
|
504
503
|
visitor.start();
|
|
505
504
|
const collected = visitor.getSources();
|
|
506
505
|
return collected.map(n => '\n- `' + n + '`').join('');
|
|
@@ -42,12 +42,12 @@ const normalize_for_1 = require("../r-bridge/lang-4.x/ast/parser/main/internal/l
|
|
|
42
42
|
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
43
43
|
const pipeline_executor_1 = require("../core/pipeline-executor");
|
|
44
44
|
const pipeline_1 = require("../core/steps/pipeline/pipeline");
|
|
45
|
+
const config_1 = require("../config");
|
|
45
46
|
async function getText(shell) {
|
|
46
47
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
47
48
|
const sampleCode = 'x <- 1; print(x)';
|
|
48
|
-
const { info, program } = (0, doc_types_1.
|
|
49
|
+
const { info, program } = (0, doc_types_1.getTypesFromFolder)({
|
|
49
50
|
rootFolder: path_1.default.resolve('./src'),
|
|
50
|
-
typeName: shell_1.RShell.name,
|
|
51
51
|
inlineTypes: doc_types_1.mermaidHide
|
|
52
52
|
});
|
|
53
53
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'core', rVersion: rversion })}
|
|
@@ -112,7 +112,7 @@ const result = await executor.allRemainingSteps();
|
|
|
112
112
|
`)}
|
|
113
113
|
|
|
114
114
|
This is, roughly, what the ${(0, doc_types_1.shortLink)('replGetDataflow', info)} function does for the ${(0, doc_cli_option_1.getReplCommand)('dataflow')} REPL command when using the [\`tree-sitter\` engine](${doc_files_1.FlowrWikiBaseRef}/Engines).
|
|
115
|
-
We create a new ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, info)} with the ${(0, doc_types_1.shortLink)('TREE_SITTER_DATAFLOW_PIPELINE', info)} and then use ${(0, doc_types_1.shortLink)(`${pipeline_executor_1.PipelineExecutor.name}::${new pipeline_executor_1.PipelineExecutor(default_pipelines_1.TREE_SITTER_PARSE_PIPELINE, { parser: new tree_sitter_executor_1.TreeSitterExecutor(), request: (0, retriever_1.requestFromInput)('') }).allRemainingSteps.name}`, info)}
|
|
115
|
+
We create a new ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, info)} with the ${(0, doc_types_1.shortLink)('TREE_SITTER_DATAFLOW_PIPELINE', info)} and then use ${(0, doc_types_1.shortLink)(`${pipeline_executor_1.PipelineExecutor.name}::${new pipeline_executor_1.PipelineExecutor(default_pipelines_1.TREE_SITTER_PARSE_PIPELINE, { parser: new tree_sitter_executor_1.TreeSitterExecutor(), request: (0, retriever_1.requestFromInput)('') }, config_1.defaultConfigOptions).allRemainingSteps.name}`, info)}
|
|
116
116
|
to cause the execution of all contained steps (in general, pipelines can be executed step-by-step, but this is usually not required if you just want the result).
|
|
117
117
|
${(0, doc_types_1.shortLink)(retriever_1.requestFromInput.name, info)} is merely a convenience function to create a request object from a code string.
|
|
118
118
|
|
|
@@ -254,7 +254,7 @@ While looking at the mermaid visualization of such an AST is nice and usually su
|
|
|
254
254
|
|
|
255
255
|
Let's have a look at the normalized AST for the sample code \`${sampleCode}\` (please refer to the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST) wiki page for more information):
|
|
256
256
|
|
|
257
|
-
${(0, doc_structure_1.details)('Normalized AST for <code>x <- 1; print(x)</code>', (0, doc_code_1.codeBlock)('json', JSON.stringify((await (0, default_pipelines_1.createNormalizePipeline)(shell, { request: (0, retriever_1.requestFromInput)(sampleCode) }).allRemainingSteps()).normalize.ast, json_1.jsonReplacer, 4)))}
|
|
257
|
+
${(0, doc_structure_1.details)('Normalized AST for <code>x <- 1; print(x)</code>', (0, doc_code_1.codeBlock)('json', JSON.stringify((await (0, default_pipelines_1.createNormalizePipeline)(shell, { request: (0, retriever_1.requestFromInput)(sampleCode) }, config_1.defaultConfigOptions).allRemainingSteps()).normalize.ast, json_1.jsonReplacer, 4)))}
|
|
258
258
|
|
|
259
259
|
This is… a lot! We get the type from the ${(0, doc_types_1.shortLink)('RType', info)} enum, the lexeme, location information, an id, the children of the node, and their parents.
|
|
260
260
|
While the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST) wiki page provides you with information on how to interpret this data, we will focus on how we get it from the
|
|
@@ -275,7 +275,7 @@ For single nodes, we use ${(0, doc_types_1.shortLink)(normalize_single_node_1.no
|
|
|
275
275
|
|
|
276
276
|
The output of just this pass is listed below (using the ${(0, doc_types_1.shortLink)(parser_2.normalizeButNotDecorated.name, info)} function):
|
|
277
277
|
|
|
278
|
-
${(0, doc_structure_1.details)('Ast for <code>x <- 1; print(x)</code> after the first normalization', (0, doc_code_1.codeBlock)('json', JSON.stringify((0, parser_2.normalizeButNotDecorated)((await (0, default_pipelines_1.createParsePipeline)(shell, { request: (0, retriever_1.requestFromInput)(sampleCode) }).allRemainingSteps()).parse), json_1.jsonReplacer, 4)))}
|
|
278
|
+
${(0, doc_structure_1.details)('Ast for <code>x <- 1; print(x)</code> after the first normalization', (0, doc_code_1.codeBlock)('json', JSON.stringify((0, parser_2.normalizeButNotDecorated)((await (0, default_pipelines_1.createParsePipeline)(shell, { request: (0, retriever_1.requestFromInput)(sampleCode) }, config_1.defaultConfigOptions).allRemainingSteps()).parse), json_1.jsonReplacer, 4)))}
|
|
279
279
|
|
|
280
280
|
|
|
281
281
|
#### Decorating the AST
|
|
@@ -38,6 +38,7 @@ const alias_tracking_1 = require("../dataflow/eval/resolve/alias-tracking");
|
|
|
38
38
|
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
39
39
|
const unnamed_call_handling_1 = require("../dataflow/internal/process/functions/call/unnamed-call-handling");
|
|
40
40
|
const environment_builder_1 = require("../../test/functionality/_helper/dataflow/environment-builder");
|
|
41
|
+
const config_1 = require("../config");
|
|
41
42
|
async function subExplanation(shell, { description, code, expectedSubgraph }) {
|
|
42
43
|
expectedSubgraph = await (0, doc_dfg_1.verifyExpectedSubgraph)(shell, code, expectedSubgraph);
|
|
43
44
|
const marks = [];
|
|
@@ -204,9 +205,8 @@ ${(0, doc_structure_1.details)('Example: Simple Function Call (unresolved)', awa
|
|
|
204
205
|
(0, assert_1.guard)(callInfo !== undefined, () => `Could not find call vertex for ${code}`);
|
|
205
206
|
const [callId, callVert] = callInfo;
|
|
206
207
|
const inverseMapReferenceTypes = Object.fromEntries(Object.entries(identifier_1.ReferenceType).map(([k, v]) => [v, k]));
|
|
207
|
-
const identifierType = (0, doc_types_1.
|
|
208
|
+
const identifierType = (0, doc_types_1.getTypesFromFolder)({
|
|
208
209
|
files: [path_1.default.resolve('./src/dataflow/environments/identifier.ts')],
|
|
209
|
-
typeName: 'IdentifierReference',
|
|
210
210
|
inlineTypes: ['ControlDependency']
|
|
211
211
|
});
|
|
212
212
|
return `
|
|
@@ -745,21 +745,21 @@ async function dummyDataflow() {
|
|
|
745
745
|
const result = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
|
|
746
746
|
parser: shell,
|
|
747
747
|
request: (0, retriever_1.requestFromInput)('x <- 1\nx + 1')
|
|
748
|
-
}).allRemainingSteps();
|
|
748
|
+
}, config_1.defaultConfigOptions).allRemainingSteps();
|
|
749
749
|
shell.close();
|
|
750
750
|
return result;
|
|
751
751
|
}
|
|
752
752
|
async function getText(shell) {
|
|
753
753
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
754
754
|
/* we collect type information on the graph */
|
|
755
|
-
const vertexType = (0, doc_types_1.
|
|
755
|
+
const vertexType = (0, doc_types_1.getTypesFromFolder)({
|
|
756
756
|
rootFolder: path_1.default.resolve('./src/'),
|
|
757
|
-
|
|
757
|
+
typeNameForMermaid: 'DataflowGraphVertexInfo',
|
|
758
758
|
inlineTypes: ['MergeableRecord']
|
|
759
759
|
});
|
|
760
|
-
const edgeType = (0, doc_types_1.
|
|
760
|
+
const edgeType = (0, doc_types_1.getTypesFromFolder)({
|
|
761
761
|
files: [path_1.default.resolve('./src/dataflow/graph/edge.ts'), path_1.default.resolve('./src/dataflow/graph/graph.ts'), path_1.default.resolve('./src/dataflow/environments/identifier.ts'), path_1.default.resolve('./src/dataflow/info.ts')],
|
|
762
|
-
|
|
762
|
+
typeNameForMermaid: 'EdgeType',
|
|
763
763
|
inlineTypes: ['MergeableRecord']
|
|
764
764
|
});
|
|
765
765
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'dataflow graph', rVersion: rversion })}
|
|
@@ -807,7 +807,7 @@ The following vertices types exist:
|
|
|
807
807
|
|
|
808
808
|
1. ${(0, doc_data_dfg_util_1.getAllVertices)().map(([k, v], index) => `[\`${k}\`](#${index + 1}-${v.toLowerCase().replace(/\s/g, '-')}-vertex)`).join('\n1. ')}
|
|
809
809
|
|
|
810
|
-
${vertexType.
|
|
810
|
+
${vertexType.mermaid.trim().length > 0 ? (0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', vertexType.mermaid)) : ''}
|
|
811
811
|
|
|
812
812
|
</details>
|
|
813
813
|
|
|
@@ -819,7 +819,7 @@ The following edges types exist, internally we use bitmasks to represent multipl
|
|
|
819
819
|
|
|
820
820
|
1. ${(0, doc_data_dfg_util_1.getAllEdges)().map(([k, v], index) => `[\`${k}\` (${v})](#${index + 1}-${k.toLowerCase().replace(/\s/g, '-')}-edge)`).join('\n1. ')}
|
|
821
821
|
|
|
822
|
-
${edgeType.
|
|
822
|
+
${edgeType.mermaid.trim().length > 0 ? (0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', edgeType.mermaid)) : ''}
|
|
823
823
|
|
|
824
824
|
</details>
|
|
825
825
|
|
|
@@ -1005,7 +1005,7 @@ Retrieving the _types_ of the edge from the print call to its argument returns:
|
|
|
1005
1005
|
${await (async () => {
|
|
1006
1006
|
const dfg = await (0, default_pipelines_1.createDataflowPipeline)(shell, {
|
|
1007
1007
|
request: (0, retriever_1.requestFromInput)('print(x)')
|
|
1008
|
-
}).allRemainingSteps();
|
|
1008
|
+
}, config_1.defaultConfigOptions).allRemainingSteps();
|
|
1009
1009
|
const edge = dfg.dataflow.graph.outgoingEdges(3);
|
|
1010
1010
|
if (edge) {
|
|
1011
1011
|
const wanted = edge.get(1);
|
|
@@ -15,10 +15,9 @@ const doc_cli_option_1 = require("./doc-util/doc-cli-option");
|
|
|
15
15
|
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
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/r-bridge/lang-4.x/tree-sitter/'),
|
|
20
20
|
files: [path_1.default.resolve('./src/config.ts'), path_1.default.resolve('./src/r-bridge/shell.ts'), path_1.default.resolve('./src/r-bridge/shell-executor.ts')],
|
|
21
|
-
typeName: 'FlowrConfigOptions',
|
|
22
21
|
inlineTypes: doc_types_1.mermaidHide
|
|
23
22
|
});
|
|
24
23
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'engines', rVersion: rversion })}
|
|
@@ -24,14 +24,20 @@ There are several ways to generate mermaid diagrams based on the input data that
|
|
|
24
24
|
|
|
25
25
|
${qAndA('How do I create new wiki pages?', `
|
|
26
26
|
To create an automatically generated wiki page, you can follow these steps:
|
|
27
|
-
-
|
|
27
|
+
- Create a new file in \`src/documentation\` with a name like \`print-my-page-wiki.ts\`.
|
|
28
28
|
- Add a new wiki generation script to the ${(0, doc_files_1.getFilePathMd)('../../package.json')}. You can copy one of the existing ones of the form \`"wiki:my-page": "ts-node src/documentation/print-my-page-wiki.ts"\`.
|
|
29
29
|
- Add the wiki generation script to the \`broken-links-and-wiki.yml\` GitHub workflow file to enable automatic generation through the CI. You can copy one of the existing ones of the form \`update_page wiki/"My page" wiki:my-page\`.
|
|
30
30
|
|
|
31
31
|
You can test your page by piping the wiki generation script to a file. For example, you can run the following command:
|
|
32
32
|
${(0, doc_code_1.codeBlock)('shell', 'npm run --silent wiki:my-page > __my-page.md')}
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
Remember not to commit this file, as it's only meant for testing.
|
|
35
|
+
`)}
|
|
36
|
+
|
|
37
|
+
${qAndA('Why can\'t I pass arguments when running flowR with npm?', `
|
|
38
|
+
With \`npm\` you have to pass arguments in a specific way. The \`--\` operator is used to separate the \`npm\` arguments from the script arguments. For example, if you want to run \`flowR\` with the \`--help\` argument, you can use the following command:
|
|
39
|
+
${(0, doc_code_1.codeBlock)('shell', 'npm run flowR -- --help')}
|
|
40
|
+
`)}
|
|
35
41
|
|
|
36
42
|
## 🇷 R FAQ
|
|
37
43
|
|
|
@@ -249,10 +249,9 @@ ${(0, schema_1.describeSchema)(config_1.flowrConfigFileSchema, ansi_1.markdownFo
|
|
|
249
249
|
`;
|
|
250
250
|
}
|
|
251
251
|
function explainWritingCode(shell) {
|
|
252
|
-
const types = (0, doc_types_1.
|
|
252
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
253
253
|
rootFolder: path_1.default.resolve('./src/'),
|
|
254
254
|
files: [path_1.default.resolve('./src/core/pipeline-executor.ts'), path_1.default.resolve('./src/core/steps/pipeline/default-pipelines.ts')],
|
|
255
|
-
typeName: 'RShell',
|
|
256
255
|
inlineTypes: doc_types_1.mermaidHide
|
|
257
256
|
});
|
|
258
257
|
return `
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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>
|
|
@@ -564,9 +564,8 @@ ${await (0, doc_cfg_1.printCfgCode)(shell, exampleCode, { showCode: false, prefi
|
|
|
564
564
|
functionName: location_map_query_executor_1.executeLocationMapQuery.name,
|
|
565
565
|
functionFile: '../queries/catalog/location-map-query/location-map-query-executor.ts',
|
|
566
566
|
buildExplanation: async (shell) => {
|
|
567
|
-
const types = (0, doc_types_1.
|
|
567
|
+
const types = (0, doc_types_1.getTypesFromFolder)({
|
|
568
568
|
files: [path_1.default.resolve('./src/util/range.ts')],
|
|
569
|
-
typeName: 'SourceRange'
|
|
570
569
|
});
|
|
571
570
|
const exampleCode = 'x + 1\nx * 2';
|
|
572
571
|
return `
|