@eagleoutice/flowr 2.2.16 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -20
- package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
- package/abstract-interpretation/data-frame/absint-info.js +31 -0
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +58 -0
- package/abstract-interpretation/data-frame/absint-visitor.js +171 -0
- package/abstract-interpretation/data-frame/domain.d.ts +107 -0
- package/abstract-interpretation/data-frame/domain.js +315 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
- package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
- package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
- package/abstract-interpretation/data-frame/resolve-args.js +118 -0
- package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
- package/abstract-interpretation/data-frame/semantics.js +363 -0
- package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
- package/abstract-interpretation/data-frame/shape-inference.js +111 -0
- package/benchmark/slicer.d.ts +15 -1
- package/benchmark/slicer.js +137 -0
- package/benchmark/stats/print.js +123 -45
- package/benchmark/stats/size-of.d.ts +7 -0
- package/benchmark/stats/size-of.js +1 -0
- package/benchmark/stats/stats.d.ts +30 -1
- package/benchmark/stats/stats.js +4 -2
- package/benchmark/summarizer/data.d.ts +33 -2
- package/benchmark/summarizer/first-phase/input.js +5 -1
- package/benchmark/summarizer/first-phase/process.js +47 -1
- package/benchmark/summarizer/second-phase/graph.js +1 -1
- package/benchmark/summarizer/second-phase/process.js +102 -4
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +2 -0
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +10 -3
- package/cli/common/options.js +4 -0
- package/cli/repl/commands/repl-query.js +1 -1
- package/cli/repl/server/connection.js +14 -5
- package/config.d.ts +31 -0
- package/config.js +21 -1
- package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
- package/control-flow/basic-cfg-guided-visitor.js +0 -6
- package/control-flow/cfg-simplification.d.ts +6 -0
- package/control-flow/cfg-simplification.js +18 -9
- package/control-flow/control-flow-graph.d.ts +3 -8
- package/control-flow/control-flow-graph.js +5 -6
- package/control-flow/dfg-cfg-guided-visitor.js +1 -1
- package/control-flow/extract-cfg.d.ts +2 -2
- package/control-flow/extract-cfg.js +52 -63
- package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
- package/control-flow/semantic-cfg-guided-visitor.js +1 -1
- package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
- package/core/steps/all/static-slicing/00-slice.js +9 -3
- package/core/steps/pipeline/default-pipelines.d.ts +74 -74
- package/dataflow/environments/built-in.d.ts +7 -5
- package/dataflow/environments/built-in.js +16 -13
- package/dataflow/eval/resolve/alias-tracking.js +2 -2
- package/dataflow/eval/resolve/resolve.d.ts +53 -9
- package/dataflow/eval/resolve/resolve.js +132 -38
- package/dataflow/graph/dataflowgraph-builder.js +2 -2
- package/dataflow/graph/graph.js +1 -1
- package/dataflow/graph/invert-dfg.d.ts +2 -0
- package/dataflow/graph/invert-dfg.js +17 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
- package/documentation/doc-util/doc-query.js +11 -1
- package/documentation/doc-util/doc-search.js +2 -2
- package/documentation/print-cfg-wiki.js +3 -4
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +7 -0
- package/documentation/print-faq-wiki.js +4 -0
- package/documentation/print-interface-wiki.js +11 -0
- package/documentation/print-linter-wiki.js +36 -4
- package/documentation/print-linting-and-testing-wiki.js +13 -1
- package/documentation/print-onboarding-wiki.js +4 -0
- package/documentation/print-query-wiki.js +29 -3
- package/linter/linter-executor.js +1 -2
- package/linter/linter-format.d.ts +26 -4
- package/linter/linter-format.js +25 -6
- package/linter/linter-rules.d.ts +63 -12
- package/linter/linter-rules.js +5 -1
- package/linter/rules/absolute-path.d.ts +4 -7
- package/linter/rules/absolute-path.js +9 -6
- package/linter/rules/dataframe-access-validation.d.ts +55 -0
- package/linter/rules/dataframe-access-validation.js +118 -0
- package/linter/rules/dead-code.d.ts +43 -0
- package/linter/rules/dead-code.js +50 -0
- package/linter/rules/deprecated-functions.d.ts +3 -2
- package/linter/rules/deprecated-functions.js +3 -1
- package/linter/rules/file-path-validity.d.ts +4 -4
- package/linter/rules/file-path-validity.js +8 -6
- package/linter/rules/naming-convention.d.ts +5 -4
- package/linter/rules/naming-convention.js +8 -2
- package/linter/rules/seeded-randomness.d.ts +4 -3
- package/linter/rules/seeded-randomness.js +3 -1
- package/linter/rules/unused-definition.d.ts +2 -0
- package/linter/rules/unused-definition.js +3 -1
- package/package.json +2 -2
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
- package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
- package/queries/catalog/linter-query/linter-query-format.js +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
- package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
- package/queries/catalog/search-query/search-query-executor.js +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
- package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +0 -1
- package/queries/query.d.ts +77 -6
- package/queries/query.js +26 -11
- package/search/flowr-search-builder.d.ts +6 -6
- package/search/flowr-search-executor.d.ts +2 -2
- package/search/flowr-search-executor.js +1 -1
- package/search/flowr-search.d.ts +13 -8
- package/search/flowr-search.js +21 -0
- package/search/search-executor/search-enrichers.d.ts +87 -20
- package/search/search-executor/search-enrichers.js +44 -5
- package/search/search-executor/search-generators.d.ts +4 -4
- package/search/search-executor/search-generators.js +12 -7
- package/search/search-executor/search-mappers.js +3 -2
- package/search/search-executor/search-transformer.d.ts +3 -3
- package/search/search-executor/search-transformer.js +2 -2
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +10 -4
- package/util/collections/arrays.d.ts +2 -0
- package/util/collections/arrays.js +9 -0
- package/util/files.d.ts +8 -2
- package/util/files.js +22 -4
- package/util/mermaid/dfg.js +4 -2
- package/util/r-value.d.ts +23 -0
- package/util/r-value.js +113 -0
- package/util/range.d.ts +1 -0
- package/util/range.js +5 -1
- package/util/version.js +1 -1
- package/util/cfg/cfg.d.ts +0 -0
- package/util/cfg/cfg.js +0 -2
|
@@ -87,7 +87,7 @@ exports.ABSOLUTE_PATH = {
|
|
|
87
87
|
}
|
|
88
88
|
if (config.include.constructed) {
|
|
89
89
|
q = q.merge(flowr_search_builder_1.Q.all().filter(vertex_1.VertexType.FunctionCall).with(search_enrichers_1.Enrichment.CallTargets));
|
|
90
|
-
/* in the future we want to directly check whether this is one of the supported functions */
|
|
90
|
+
/* in the future, we want to directly check whether this is one of the supported functions */
|
|
91
91
|
}
|
|
92
92
|
return q.unique();
|
|
93
93
|
},
|
|
@@ -96,6 +96,7 @@ exports.ABSOLUTE_PATH = {
|
|
|
96
96
|
totalConsidered: 0,
|
|
97
97
|
totalUnknown: 0
|
|
98
98
|
};
|
|
99
|
+
const queryResults = elements.enrichmentContent(search_enrichers_1.Enrichment.QueryData)?.queries;
|
|
99
100
|
const regex = config.absolutePathRegex ? new RegExp(config.absolutePathRegex) : undefined;
|
|
100
101
|
return {
|
|
101
102
|
results: elements.getElements().flatMap(element => {
|
|
@@ -105,7 +106,7 @@ exports.ABSOLUTE_PATH = {
|
|
|
105
106
|
if ((0, r_string_1.isRString)(node)) {
|
|
106
107
|
if (node.content.str.length >= 3 && (0, strings_1.isAbsolutePath)(node.content.str, regex)) {
|
|
107
108
|
return [{
|
|
108
|
-
certainty: linter_format_1.
|
|
109
|
+
certainty: linter_format_1.LintingResultCertainty.Uncertain,
|
|
109
110
|
filePath: node.content.str,
|
|
110
111
|
range: node.info.fullRange ?? node.location,
|
|
111
112
|
quickFix: buildQuickFix(node, node.content.str, wd)
|
|
@@ -115,12 +116,12 @@ exports.ABSOLUTE_PATH = {
|
|
|
115
116
|
return [];
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
|
-
else if (element.
|
|
119
|
-
const result = element.
|
|
119
|
+
else if ((0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.QueryData)) {
|
|
120
|
+
const result = queryResults[(0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.QueryData).query];
|
|
120
121
|
const mappedStrings = result.readData.filter(r => r.source !== dependencies_query_format_1.Unknown && (0, strings_1.isAbsolutePath)(r.source, regex)).map(r => {
|
|
121
122
|
const elem = data.normalize.idMap.get(r.nodeId);
|
|
122
123
|
return {
|
|
123
|
-
certainty: linter_format_1.
|
|
124
|
+
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
124
125
|
filePath: r.source,
|
|
125
126
|
range: elem?.info.fullRange ?? elem?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
|
|
126
127
|
quickFix: buildQuickFix(elem, r.source, wd)
|
|
@@ -141,7 +142,7 @@ exports.ABSOLUTE_PATH = {
|
|
|
141
142
|
const strings = handler ? handler(data.dataflow.graph, dfNode, data.config) : [];
|
|
142
143
|
if (strings) {
|
|
143
144
|
return strings.filter(s => (0, strings_1.isAbsolutePath)(s, regex)).map(str => ({
|
|
144
|
-
certainty: linter_format_1.
|
|
145
|
+
certainty: linter_format_1.LintingResultCertainty.Uncertain,
|
|
145
146
|
filePath: str,
|
|
146
147
|
range: node.info.fullRange ?? node.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1)
|
|
147
148
|
}));
|
|
@@ -163,6 +164,8 @@ exports.ABSOLUTE_PATH = {
|
|
|
163
164
|
name: 'Absolute Paths',
|
|
164
165
|
description: 'Checks whether file paths are absolute.',
|
|
165
166
|
tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.QuickFix],
|
|
167
|
+
// checks all found paths for whether they're absolute to ensure correctness, but doesn't handle non-constant paths so not all will be returned
|
|
168
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
166
169
|
defaultConfig: {
|
|
167
170
|
include: {
|
|
168
171
|
constructed: true,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
2
|
+
import type { FlowrSearchElements } from '../../search/flowr-search';
|
|
3
|
+
import { type MergeableRecord } from '../../util/objects';
|
|
4
|
+
import { type SourceRange } from '../../util/range';
|
|
5
|
+
import type { LintingResult } from '../linter-format';
|
|
6
|
+
import { LintingRuleCertainty } from '../linter-format';
|
|
7
|
+
import { LintingRuleTag } from '../linter-tags';
|
|
8
|
+
export interface DataFrameAccessValidationResult extends LintingResult {
|
|
9
|
+
/** The type of the data frame access ("column" or "row") */
|
|
10
|
+
type: 'column' | 'row';
|
|
11
|
+
/** The name or index of the column or row being accessed in the data frame */
|
|
12
|
+
accessed: string | number;
|
|
13
|
+
/** The name of the function/operation used for the access (e.g. `$`, `[`, `[[`, but also `filter`, `select`, ...) */
|
|
14
|
+
access: string;
|
|
15
|
+
/** The variable/symbol name of the accessed data frame operand (`undefined` if operand is no symbol) */
|
|
16
|
+
operand?: string;
|
|
17
|
+
/** The source range in the code where the access occurs */
|
|
18
|
+
range: SourceRange;
|
|
19
|
+
}
|
|
20
|
+
export interface DataFrameAccessValidationConfig extends MergeableRecord {
|
|
21
|
+
/** Whether data frame shapes should be extracted from loaded external data files, such as CSV files (defaults to the option in the flowR config if `undefined`) */
|
|
22
|
+
readLoadedData?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface DataFrameAccessValidationMetadata extends MergeableRecord {
|
|
25
|
+
/** The number of data frame functions and operations containing inferred column or row accesses */
|
|
26
|
+
numOperations: number;
|
|
27
|
+
/** The number of inferred abstract column or row access operations */
|
|
28
|
+
numAccesses: number;
|
|
29
|
+
/** The total number of inferred accessed columns and rows */
|
|
30
|
+
totalAccessed: number;
|
|
31
|
+
}
|
|
32
|
+
export declare const DATA_FRAME_ACCESS_VALIDATION: {
|
|
33
|
+
readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with"], ParentInformation, FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>>;
|
|
34
|
+
readonly processSearchResult: (elements: FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>, config: DataFrameAccessValidationConfig, data: {
|
|
35
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
36
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
37
|
+
config: import("../../config").FlowrConfigOptions;
|
|
38
|
+
}) => {
|
|
39
|
+
results: DataFrameAccessValidationResult[];
|
|
40
|
+
'.meta': DataFrameAccessValidationMetadata;
|
|
41
|
+
};
|
|
42
|
+
readonly prettyPrint: {
|
|
43
|
+
readonly query: (result: DataFrameAccessValidationResult) => string;
|
|
44
|
+
readonly full: (result: DataFrameAccessValidationResult) => string;
|
|
45
|
+
};
|
|
46
|
+
readonly info: {
|
|
47
|
+
readonly name: "Dataframe Access Validation";
|
|
48
|
+
readonly tags: readonly [LintingRuleTag.Bug, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
|
|
49
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
50
|
+
readonly description: "Validates the existance of accessed columns and rows of dataframes.";
|
|
51
|
+
readonly defaultConfig: {
|
|
52
|
+
readonly readLoadedData: false;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DATA_FRAME_ACCESS_VALIDATION = void 0;
|
|
4
|
+
const absint_info_1 = require("../../abstract-interpretation/data-frame/absint-info");
|
|
5
|
+
const domain_1 = require("../../abstract-interpretation/data-frame/domain");
|
|
6
|
+
const shape_inference_1 = require("../../abstract-interpretation/data-frame/shape-inference");
|
|
7
|
+
const config_1 = require("../../config");
|
|
8
|
+
const extract_cfg_1 = require("../../control-flow/extract-cfg");
|
|
9
|
+
const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
|
|
10
|
+
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
|
|
11
|
+
const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
|
|
12
|
+
const dfg_1 = require("../../util/mermaid/dfg");
|
|
13
|
+
const range_1 = require("../../util/range");
|
|
14
|
+
const linter_format_1 = require("../linter-format");
|
|
15
|
+
const linter_tags_1 = require("../linter-tags");
|
|
16
|
+
;
|
|
17
|
+
;
|
|
18
|
+
exports.DATA_FRAME_ACCESS_VALIDATION = {
|
|
19
|
+
createSearch: () => flowr_search_builder_1.Q.all().with(search_enrichers_1.Enrichment.CallTargets, { onlyBuiltin: true }),
|
|
20
|
+
processSearchResult: (elements, config, data) => {
|
|
21
|
+
const flowrConfig = (0, config_1.amendConfig)(data.config, flowrConfig => {
|
|
22
|
+
if (config.readLoadedData !== undefined) {
|
|
23
|
+
flowrConfig.abstractInterpretation.dataFrame.readLoadedData.readExternalFiles = config.readLoadedData;
|
|
24
|
+
}
|
|
25
|
+
return flowrConfig;
|
|
26
|
+
});
|
|
27
|
+
const cfg = (0, extract_cfg_1.extractCfg)(data.normalize, flowrConfig, data.dataflow.graph);
|
|
28
|
+
(0, shape_inference_1.inferDataFrameShapes)(cfg, data.dataflow.graph, data.normalize, flowrConfig);
|
|
29
|
+
const accessOperations = getAccessOperations(elements);
|
|
30
|
+
const accesses = [];
|
|
31
|
+
for (const [nodeId, operations] of accessOperations) {
|
|
32
|
+
const access = { nodeId };
|
|
33
|
+
for (const operation of operations) {
|
|
34
|
+
access.operand ??= operation.operand;
|
|
35
|
+
access.operandShape ??= (0, shape_inference_1.resolveIdToDataFrameShape)(operation.operand, data.dataflow.graph);
|
|
36
|
+
if (operation.operation === 'accessCols' && operation.columns !== undefined) {
|
|
37
|
+
access.accessedCols ??= [];
|
|
38
|
+
access.accessedCols.push(...operation.columns);
|
|
39
|
+
}
|
|
40
|
+
else if (operation.operation === 'accessRows' && operation.rows !== undefined) {
|
|
41
|
+
access.accessedRows ??= [];
|
|
42
|
+
access.accessedRows.push(...operation.rows);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
accesses.push(access);
|
|
46
|
+
}
|
|
47
|
+
const operations = accessOperations.entries().flatMap(([, operations]) => operations).toArray();
|
|
48
|
+
const metadata = {
|
|
49
|
+
numOperations: accessOperations.size,
|
|
50
|
+
numAccesses: operations.length,
|
|
51
|
+
totalAccessed: operations
|
|
52
|
+
.map(operation => operation.operation === 'accessCols' ? operation.columns?.length ?? 0 : operation.rows?.length ?? 0)
|
|
53
|
+
.reduce((a, b) => a + b, 0)
|
|
54
|
+
};
|
|
55
|
+
const results = accesses
|
|
56
|
+
.flatMap(access => findInvalidDataFrameAccesses(access)
|
|
57
|
+
.map(accessed => ({ nodeId: access.nodeId, operand: access.operand, ...accessed })))
|
|
58
|
+
.map(({ nodeId, operand, ...accessed }) => ({
|
|
59
|
+
...accessed,
|
|
60
|
+
node: data.normalize.idMap.get(nodeId),
|
|
61
|
+
operand: operand !== undefined ? data.normalize.idMap.get(operand) : undefined,
|
|
62
|
+
}))
|
|
63
|
+
.map(({ node, operand, ...accessed }) => ({
|
|
64
|
+
...accessed,
|
|
65
|
+
access: node?.lexeme ?? '???',
|
|
66
|
+
...(operand?.type === type_1.RType.Symbol ? { operand: operand.content } : {}),
|
|
67
|
+
range: node?.info.fullRange ?? node?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
|
|
68
|
+
certainty: linter_format_1.LintingResultCertainty.Certain
|
|
69
|
+
}));
|
|
70
|
+
return { results, '.meta': metadata };
|
|
71
|
+
},
|
|
72
|
+
prettyPrint: {
|
|
73
|
+
[linter_format_1.LintingPrettyPrintContext.Query]: result => `Access of ${result.type} ` +
|
|
74
|
+
(typeof result.accessed === 'string' ? `"${result.accessed}"` : result.accessed) + ' ' +
|
|
75
|
+
(result.operand !== undefined ? `of \`${result.operand}\`` : `at \`${result.access}\``) + ` at ${(0, dfg_1.formatRange)(result.range)}`,
|
|
76
|
+
[linter_format_1.LintingPrettyPrintContext.Full]: result => `Accessed ${result.type} ` +
|
|
77
|
+
(typeof result.accessed === 'string' ? `"${result.accessed}"` : result.accessed) + ' does not exist ' +
|
|
78
|
+
(result.operand !== undefined ? `in \`${result.operand}\`` : `at \`${result.access}\``) + ` at ${(0, dfg_1.formatRange)(result.range)}`
|
|
79
|
+
},
|
|
80
|
+
info: {
|
|
81
|
+
name: 'Dataframe Access Validation',
|
|
82
|
+
tags: [linter_tags_1.LintingRuleTag.Bug, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
|
|
83
|
+
// this rule is unable to detect all cases of dataframe access, but sufficiently ensures returned results are valid
|
|
84
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
85
|
+
description: 'Validates the existance of accessed columns and rows of dataframes.',
|
|
86
|
+
defaultConfig: { readLoadedData: false }
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
function getAccessOperations(elements) {
|
|
90
|
+
return new Map(elements.getElements()
|
|
91
|
+
.map(element => element.node)
|
|
92
|
+
.filter(absint_info_1.hasDataFrameExpressionInfo)
|
|
93
|
+
.map(node => [node.info.id, node.info.dataFrame.operations
|
|
94
|
+
.filter(({ operation }) => operation === 'accessCols' || operation === 'accessRows')
|
|
95
|
+
.map(({ operation, operand, type: _type, options: _options, ...args }) => ({ operation, operand, ...args }))
|
|
96
|
+
])
|
|
97
|
+
.filter(([, operations]) => operations.length > 0));
|
|
98
|
+
}
|
|
99
|
+
function findInvalidDataFrameAccesses({ operandShape, accessedCols, accessedRows }) {
|
|
100
|
+
const invalidAccesses = [];
|
|
101
|
+
if (operandShape !== undefined) {
|
|
102
|
+
for (const row of accessedRows ?? []) {
|
|
103
|
+
if (!(0, domain_1.satisfiesLeqInterval)(operandShape.rows, row)) {
|
|
104
|
+
invalidAccesses.push({ type: 'row', accessed: row });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const col of accessedCols ?? []) {
|
|
108
|
+
if (typeof col === 'string' && !(0, domain_1.satisfiesColsNames)(operandShape.colnames, col)) {
|
|
109
|
+
invalidAccesses.push({ type: 'column', accessed: col });
|
|
110
|
+
}
|
|
111
|
+
else if (typeof col === 'number' && !(0, domain_1.satisfiesLeqInterval)(operandShape.cols, col)) {
|
|
112
|
+
invalidAccesses.push({ type: 'column', accessed: col });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return invalidAccesses;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=dataframe-access-validation.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LintingResultCertainty, type LintingResult, LintingRuleCertainty } from '../linter-format';
|
|
2
|
+
import type { SourceRange } from '../../util/range';
|
|
3
|
+
import type { MergeableRecord } from '../../util/objects';
|
|
4
|
+
import { LintingRuleTag } from '../linter-tags';
|
|
5
|
+
import { type CfgSimplificationPassName } from '../../control-flow/cfg-simplification';
|
|
6
|
+
export interface DeadCodeResult extends LintingResult {
|
|
7
|
+
range: SourceRange;
|
|
8
|
+
}
|
|
9
|
+
export interface DeadCodeConfig extends MergeableRecord {
|
|
10
|
+
/**
|
|
11
|
+
* The simplification passes that should be run on the extracted CFG.
|
|
12
|
+
* Defaults to the entries of {@link DefaultCfgSimplificationOrder} and `analyze-dead-code`.
|
|
13
|
+
*/
|
|
14
|
+
simplificationPasses?: CfgSimplificationPassName[];
|
|
15
|
+
}
|
|
16
|
+
export interface DeadCodeMetadata extends MergeableRecord {
|
|
17
|
+
consideredNodes: number;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEAD_CODE: {
|
|
20
|
+
readonly createSearch: (config: DeadCodeConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
21
|
+
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: DeadCodeConfig, _data: {
|
|
22
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
23
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
24
|
+
config: import("../../config").FlowrConfigOptions;
|
|
25
|
+
}) => {
|
|
26
|
+
results: {
|
|
27
|
+
certainty: LintingResultCertainty.Certain;
|
|
28
|
+
range: SourceRange;
|
|
29
|
+
}[];
|
|
30
|
+
'.meta': DeadCodeMetadata;
|
|
31
|
+
};
|
|
32
|
+
readonly prettyPrint: {
|
|
33
|
+
readonly query: (result: DeadCodeResult) => string;
|
|
34
|
+
readonly full: (result: DeadCodeResult) => string;
|
|
35
|
+
};
|
|
36
|
+
readonly info: {
|
|
37
|
+
readonly name: "Dead Code";
|
|
38
|
+
readonly tags: readonly [LintingRuleTag.Smell, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
|
|
39
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
40
|
+
readonly description: "Marks areas of code that are never reached during execution.";
|
|
41
|
+
readonly defaultConfig: {};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEAD_CODE = void 0;
|
|
4
|
+
const linter_format_1 = require("../linter-format");
|
|
5
|
+
const range_1 = require("../../util/range");
|
|
6
|
+
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
|
|
7
|
+
const dfg_1 = require("../../util/mermaid/dfg");
|
|
8
|
+
const linter_tags_1 = require("../linter-tags");
|
|
9
|
+
const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
|
|
10
|
+
const assert_1 = require("../../util/assert");
|
|
11
|
+
const cfg_simplification_1 = require("../../control-flow/cfg-simplification");
|
|
12
|
+
exports.DEAD_CODE = {
|
|
13
|
+
createSearch: (config) => flowr_search_builder_1.Q.all().with(search_enrichers_1.Enrichment.CfgInformation, {
|
|
14
|
+
checkReachable: true,
|
|
15
|
+
simplificationPasses: config.simplificationPasses ?? [...cfg_simplification_1.DefaultCfgSimplificationOrder, 'analyze-dead-code']
|
|
16
|
+
}),
|
|
17
|
+
processSearchResult: (elements, _config, _data) => {
|
|
18
|
+
const meta = {
|
|
19
|
+
consideredNodes: 0
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
results: (0, range_1.combineRanges)(...new Set(elements.getElements()
|
|
23
|
+
.filter(element => {
|
|
24
|
+
meta.consideredNodes++;
|
|
25
|
+
const cfgInformation = (0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.CfgInformation);
|
|
26
|
+
return cfgInformation.isRoot && !cfgInformation.isReachable;
|
|
27
|
+
})
|
|
28
|
+
.map(element => element.node.info.fullRange ?? element.node.location)
|
|
29
|
+
.filter(assert_1.isNotUndefined)))
|
|
30
|
+
.map(range => ({
|
|
31
|
+
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
32
|
+
range
|
|
33
|
+
})),
|
|
34
|
+
'.meta': meta
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
prettyPrint: {
|
|
38
|
+
[linter_format_1.LintingPrettyPrintContext.Query]: result => `Code at ${(0, dfg_1.formatRange)(result.range)}`,
|
|
39
|
+
[linter_format_1.LintingPrettyPrintContext.Full]: result => `Code at ${(0, dfg_1.formatRange)(result.range)} can never be executed`,
|
|
40
|
+
},
|
|
41
|
+
info: {
|
|
42
|
+
name: 'Dead Code',
|
|
43
|
+
tags: [linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
|
|
44
|
+
// our limited dead code analysis causes complex cases of dead code not to be included in the linting result, but deadness is properly investigated for returned results
|
|
45
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
46
|
+
description: 'Marks areas of code that are never reached during execution.',
|
|
47
|
+
defaultConfig: {}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=dead-code.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LintingResult } from '../linter-format';
|
|
2
|
-
import {
|
|
2
|
+
import { LintingResultCertainty, LintingRuleCertainty } from '../linter-format';
|
|
3
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
4
4
|
import type { SourceRange } from '../../util/range';
|
|
5
5
|
import type { Identifier } from '../../dataflow/environments/identifier';
|
|
@@ -22,7 +22,7 @@ export declare const DEPRECATED_FUNCTIONS: {
|
|
|
22
22
|
readonly createSearch: (config: DeprecatedFunctionsConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with", "filter"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, [] | import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
23
23
|
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>) => {
|
|
24
24
|
results: {
|
|
25
|
-
certainty:
|
|
25
|
+
certainty: LintingResultCertainty.Certain;
|
|
26
26
|
function: Identifier;
|
|
27
27
|
range: SourceRange;
|
|
28
28
|
}[];
|
|
@@ -35,6 +35,7 @@ export declare const DEPRECATED_FUNCTIONS: {
|
|
|
35
35
|
readonly info: {
|
|
36
36
|
readonly name: "Deprecated Functions";
|
|
37
37
|
readonly tags: readonly [LintingRuleTag.Deprecated, LintingRuleTag.Smell, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
|
|
38
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
38
39
|
readonly description: "Marks deprecated functions that should not be used anymore.";
|
|
39
40
|
readonly defaultConfig: {
|
|
40
41
|
readonly deprecatedFunctions: readonly ["all_equal", "arrange_all", "distinct_all", "filter_all", "group_by_all", "summarise_all", "mutate_all", "select_all", "vars", "all_vars", "id", "failwith", "select_vars", "rename_vars", "select_var", "current_vars", "bench_tbls", "compare_tbls", "compare_tbls2", "eval_tbls", "eval_tbls2", "location", "changes", "combine", "do", "funs", "add_count_", "add_tally_", "arrange_", "count_", "distinct_", "do_", "filter_", "funs_", "group_by_", "group_indices_", "mutate_", "tally_", "transmute_", "rename_", "rename_vars_", "select_", "select_vars_", "slice_", "summarise_", "summarize_", "summarise_each", "src_local", "tbl_df", "add_rownames", "group_nest", "group_split", "with_groups", "nest_by", "progress_estimated", "recode", "sample_n", "top_n", "transmute", "fct_explicit_na", "aes_", "aes_auto", "annotation_logticks", "is.Coord", "coord_flip", "coord_map", "is.facet", "fortify", "is.ggproto", "guide_train", "is.ggplot", "qplot", "is.theme", "gg_dep", "liply", "isplit2", "list_along", "cross", "invoke", "at_depth", "prepend", "rerun", "splice", "`%@%`", "rbernoulli", "rdunif", "when", "update_list", "map_raw", "accumulate", "reduce_right", "flatten", "map_dfr", "as_vector", "transpose", "melt_delim", "melt_fwf", "melt_table", "read_table2", "str_interp", "as_tibble", "data_frame", "tibble_", "data_frame_", "lst_", "as_data_frame", "as.tibble", "frame_data", "trunc_mat", "is.tibble", "tidy_names", "set_tidy_names", "repair_names", "extract_numeric", "complete_", "drop_na_", "expand_", "crossing_", "nesting_", "extract_", "fill_", "gather_", "nest_", "separate_rows_", "separate_", "spread_", "unite_", "unnest_", "extract", "gather", "nest_legacy", "separate_rows", "separate", "spread"];
|
|
@@ -35,7 +35,7 @@ exports.DEPRECATED_FUNCTIONS = {
|
|
|
35
35
|
});
|
|
36
36
|
})
|
|
37
37
|
.map(element => ({
|
|
38
|
-
certainty: linter_format_1.
|
|
38
|
+
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
39
39
|
function: element.target,
|
|
40
40
|
range: element.range
|
|
41
41
|
})),
|
|
@@ -49,6 +49,8 @@ exports.DEPRECATED_FUNCTIONS = {
|
|
|
49
49
|
info: {
|
|
50
50
|
name: 'Deprecated Functions',
|
|
51
51
|
tags: [linter_tags_1.LintingRuleTag.Deprecated, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
|
|
52
|
+
// ensures all deprecated functions found are actually deprecated through its limited config, but doesn't find all deprecated functions since the config is pre-crawled
|
|
53
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
52
54
|
description: 'Marks deprecated functions that should not be used anymore.',
|
|
53
55
|
defaultConfig: {
|
|
54
56
|
deprecatedFunctions: ['all_equal', 'arrange_all', 'distinct_all', 'filter_all', 'group_by_all', 'summarise_all', 'mutate_all', 'select_all', 'vars', 'all_vars', 'id', 'failwith', 'select_vars', 'rename_vars', 'select_var', 'current_vars', 'bench_tbls', 'compare_tbls', 'compare_tbls2', 'eval_tbls', 'eval_tbls2', 'location', 'changes', 'combine', 'do', 'funs', 'add_count_', 'add_tally_', 'arrange_', 'count_', 'distinct_', 'do_', 'filter_', 'funs_', 'group_by_', 'group_indices_', 'mutate_', 'tally_', 'transmute_', 'rename_', 'rename_vars_', 'select_', 'select_vars_', 'slice_', 'summarise_', 'summarize_', 'summarise_each', 'src_local', 'tbl_df', 'add_rownames', 'group_nest', 'group_split', 'with_groups', 'nest_by', 'progress_estimated', 'recode', 'sample_n', 'top_n', 'transmute', 'fct_explicit_na', 'aes_', 'aes_auto', 'annotation_logticks', 'is.Coord', 'coord_flip', 'coord_map', 'is.facet', 'fortify', 'is.ggproto', 'guide_train', 'is.ggplot', 'qplot', 'is.theme', 'gg_dep', 'liply', 'isplit2', 'list_along', 'cross', 'invoke', 'at_depth', 'prepend', 'rerun', 'splice', '`%@%`', 'rbernoulli', 'rdunif', 'when', 'update_list', 'map_raw', 'accumulate', 'reduce_right', 'flatten', 'map_dfr', 'as_vector', 'transpose', 'melt_delim', 'melt_fwf', 'melt_table', 'read_table2', 'str_interp', 'as_tibble', 'data_frame', 'tibble_', 'data_frame_', 'lst_', 'as_data_frame', 'as.tibble', 'frame_data', 'trunc_mat', 'is.tibble', 'tidy_names', 'set_tidy_names', 'repair_names', 'extract_numeric', 'complete_', 'drop_na_', 'expand_', 'crossing_', 'nesting_', 'extract_', 'fill_', 'gather_', 'nest_', 'separate_rows_', 'separate_', 'spread_', 'unite_', 'unnest_', 'extract', 'gather', 'nest_legacy', 'separate_rows', 'separate', 'spread',]
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { LintingResult } from '../linter-format';
|
|
2
|
+
import { LintingRuleCertainty } from '../linter-format';
|
|
2
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
3
4
|
import type { SourceRange } from '../../util/range';
|
|
4
|
-
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
|
-
import type { FlowrSearchElementFromQuery } from '../../search/flowr-search';
|
|
6
5
|
import type { FunctionInfo } from '../../queries/catalog/dependencies-query/function-info/function-info';
|
|
7
6
|
import { LintingRuleTag } from '../linter-tags';
|
|
8
7
|
export interface FilePathValidityResult extends LintingResult {
|
|
@@ -32,8 +31,8 @@ export interface FilePathValidityMetadata extends MergeableRecord {
|
|
|
32
31
|
totalValid: number;
|
|
33
32
|
}
|
|
34
33
|
export declare const FILE_PATH_VALIDITY: {
|
|
35
|
-
readonly createSearch: (config: FilePathValidityConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], ParentInformation, import("../../search/flowr-search").FlowrSearchElements<ParentInformation,
|
|
36
|
-
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<ParentInformation,
|
|
34
|
+
readonly createSearch: (config: FilePathValidityConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", ["with"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
35
|
+
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: FilePathValidityConfig, data: {
|
|
37
36
|
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
38
37
|
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
39
38
|
config: import("../../config").FlowrConfigOptions;
|
|
@@ -44,6 +43,7 @@ export declare const FILE_PATH_VALIDITY: {
|
|
|
44
43
|
readonly info: {
|
|
45
44
|
readonly name: "File Path Validity";
|
|
46
45
|
readonly description: "Checks whether file paths used in read and write operations are valid and point to existing files.";
|
|
46
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
47
47
|
readonly tags: readonly [LintingRuleTag.Robustness, LintingRuleTag.Reproducibility, LintingRuleTag.Bug];
|
|
48
48
|
readonly defaultConfig: {
|
|
49
49
|
readonly additionalReadFunctions: readonly [];
|
|
@@ -10,9 +10,9 @@ const logic_1 = require("../../util/logic");
|
|
|
10
10
|
const retriever_1 = require("../../r-bridge/retriever");
|
|
11
11
|
const read_functions_1 = require("../../queries/catalog/dependencies-query/function-info/read-functions");
|
|
12
12
|
const write_functions_1 = require("../../queries/catalog/dependencies-query/function-info/write-functions");
|
|
13
|
-
const extract_cfg_1 = require("../../control-flow/extract-cfg");
|
|
14
13
|
const happens_before_1 = require("../../control-flow/happens-before");
|
|
15
14
|
const linter_tags_1 = require("../linter-tags");
|
|
15
|
+
const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
|
|
16
16
|
exports.FILE_PATH_VALIDITY = {
|
|
17
17
|
createSearch: (config) => flowr_search_builder_1.Q.fromQuery({
|
|
18
18
|
type: 'dependencies',
|
|
@@ -20,9 +20,9 @@ exports.FILE_PATH_VALIDITY = {
|
|
|
20
20
|
ignoreDefaultFunctions: true,
|
|
21
21
|
readFunctions: read_functions_1.ReadFunctions.concat(config.additionalReadFunctions),
|
|
22
22
|
writeFunctions: write_functions_1.WriteFunctions.concat(config.additionalWriteFunctions)
|
|
23
|
-
}),
|
|
23
|
+
}).with(search_enrichers_1.Enrichment.CfgInformation),
|
|
24
24
|
processSearchResult: (elements, config, data) => {
|
|
25
|
-
const cfg =
|
|
25
|
+
const cfg = elements.enrichmentContent(search_enrichers_1.Enrichment.CfgInformation).cfg.graph;
|
|
26
26
|
const metadata = {
|
|
27
27
|
totalReads: 0,
|
|
28
28
|
totalUnknown: 0,
|
|
@@ -31,7 +31,7 @@ exports.FILE_PATH_VALIDITY = {
|
|
|
31
31
|
};
|
|
32
32
|
return {
|
|
33
33
|
results: elements.getElements().flatMap(element => {
|
|
34
|
-
const results =
|
|
34
|
+
const results = elements.enrichmentContent(search_enrichers_1.Enrichment.QueryData).queries['dependencies'];
|
|
35
35
|
const matchingRead = results.readData.find(r => r.nodeId == element.node.info.id);
|
|
36
36
|
if (!matchingRead) {
|
|
37
37
|
return [];
|
|
@@ -45,7 +45,7 @@ exports.FILE_PATH_VALIDITY = {
|
|
|
45
45
|
return [{
|
|
46
46
|
range,
|
|
47
47
|
filePath: dependencies_query_format_1.Unknown,
|
|
48
|
-
certainty: linter_format_1.
|
|
48
|
+
certainty: linter_format_1.LintingResultCertainty.Uncertain
|
|
49
49
|
}];
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
@@ -70,7 +70,7 @@ exports.FILE_PATH_VALIDITY = {
|
|
|
70
70
|
return [{
|
|
71
71
|
range,
|
|
72
72
|
filePath: matchingRead.source,
|
|
73
|
-
certainty: writesBefore && writesBefore.length && writesBefore.every(w => w === logic_1.Ternary.Maybe) ? linter_format_1.
|
|
73
|
+
certainty: writesBefore && writesBefore.length && writesBefore.every(w => w === logic_1.Ternary.Maybe) ? linter_format_1.LintingResultCertainty.Uncertain : linter_format_1.LintingResultCertainty.Certain
|
|
74
74
|
}];
|
|
75
75
|
}),
|
|
76
76
|
'.meta': metadata
|
|
@@ -79,6 +79,8 @@ exports.FILE_PATH_VALIDITY = {
|
|
|
79
79
|
info: {
|
|
80
80
|
name: 'File Path Validity',
|
|
81
81
|
description: 'Checks whether file paths used in read and write operations are valid and point to existing files.',
|
|
82
|
+
// checks all found paths for whether they're valid to ensure correctness, but doesn't handle non-constant paths so not all will be returned
|
|
83
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
82
84
|
tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility, linter_tags_1.LintingRuleTag.Bug],
|
|
83
85
|
defaultConfig: {
|
|
84
86
|
additionalReadFunctions: [],
|
|
@@ -2,8 +2,8 @@ import type { DataflowGraph } from '../../dataflow/graph/graph';
|
|
|
2
2
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
4
4
|
import type { SourceRange } from '../../util/range';
|
|
5
|
-
import type {
|
|
6
|
-
import {
|
|
5
|
+
import type { LintingResult, LintQuickFixReplacement } from '../linter-format';
|
|
6
|
+
import { LintingResultCertainty, LintingRuleCertainty } from '../linter-format';
|
|
7
7
|
import { LintingRuleTag } from '../linter-tags';
|
|
8
8
|
export declare enum CasingConvention {
|
|
9
9
|
CamelCase = "camelCase",
|
|
@@ -46,7 +46,7 @@ export declare const NAMING_CONVENTION: {
|
|
|
46
46
|
}) => {
|
|
47
47
|
results: {
|
|
48
48
|
quickFix: LintQuickFixReplacement[] | undefined;
|
|
49
|
-
certainty:
|
|
49
|
+
certainty: LintingResultCertainty;
|
|
50
50
|
detectedCasing: CasingConvention;
|
|
51
51
|
name: string;
|
|
52
52
|
range: SourceRange;
|
|
@@ -62,10 +62,11 @@ export declare const NAMING_CONVENTION: {
|
|
|
62
62
|
};
|
|
63
63
|
readonly info: {
|
|
64
64
|
readonly name: "Naming Convention";
|
|
65
|
+
readonly certainty: LintingRuleCertainty.OverApproximative;
|
|
65
66
|
readonly description: "Checks wether the symbols conform to a certain naming convention";
|
|
66
67
|
readonly tags: readonly [LintingRuleTag.Style, LintingRuleTag.QuickFix];
|
|
67
68
|
readonly defaultConfig: {
|
|
68
|
-
readonly caseing:
|
|
69
|
+
readonly caseing: "auto";
|
|
69
70
|
};
|
|
70
71
|
};
|
|
71
72
|
};
|
|
@@ -66,11 +66,15 @@ function detectCasing(identifier) {
|
|
|
66
66
|
return CasingConvention.Unknown;
|
|
67
67
|
}
|
|
68
68
|
function getMostUsedCasing(symbols) {
|
|
69
|
+
if (symbols.length === 0) {
|
|
70
|
+
return CasingConvention.Unknown;
|
|
71
|
+
}
|
|
69
72
|
const map = new Map();
|
|
70
73
|
for (const symbol of symbols) {
|
|
71
74
|
const o = map.get(symbol.detectedCasing) ?? 0;
|
|
72
75
|
map.set(symbol.detectedCasing, o + 1);
|
|
73
76
|
}
|
|
77
|
+
// Return element with most occurances
|
|
74
78
|
return [...map].reduce((p, c) => p[1] > c[1] ? p : c)[0];
|
|
75
79
|
}
|
|
76
80
|
function fixCasing(identifier, convention) {
|
|
@@ -128,7 +132,7 @@ exports.NAMING_CONVENTION = {
|
|
|
128
132
|
processSearchResult: (elements, config, data) => {
|
|
129
133
|
const symbols = elements.getElements()
|
|
130
134
|
.map(m => ({
|
|
131
|
-
certainty: linter_format_1.
|
|
135
|
+
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
132
136
|
detectedCasing: detectCasing(m.node.lexeme),
|
|
133
137
|
name: m.node.lexeme,
|
|
134
138
|
range: m.node.info.fullRange,
|
|
@@ -154,10 +158,12 @@ exports.NAMING_CONVENTION = {
|
|
|
154
158
|
},
|
|
155
159
|
info: {
|
|
156
160
|
name: 'Naming Convention',
|
|
161
|
+
// detects casing heuristically so correctness is not ensured using default config, but checks all identifiers in the code for naming convention match
|
|
162
|
+
certainty: linter_format_1.LintingRuleCertainty.OverApproximative,
|
|
157
163
|
description: 'Checks wether the symbols conform to a certain naming convention',
|
|
158
164
|
tags: [linter_tags_1.LintingRuleTag.Style, linter_tags_1.LintingRuleTag.QuickFix],
|
|
159
165
|
defaultConfig: {
|
|
160
|
-
caseing:
|
|
166
|
+
caseing: 'auto'
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
169
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LintingResult } from '../linter-format';
|
|
2
|
-
import {
|
|
2
|
+
import { LintingResultCertainty, LintingRuleCertainty } from '../linter-format';
|
|
3
3
|
import type { SourceRange } from '../../util/range';
|
|
4
4
|
import type { MergeableRecord } from '../../util/objects';
|
|
5
5
|
import type { Identifier } from '../../dataflow/environments/identifier';
|
|
@@ -30,14 +30,14 @@ export interface SeededRandomnessMeta extends MergeableRecord {
|
|
|
30
30
|
callsWithNonConstantProducers: number;
|
|
31
31
|
}
|
|
32
32
|
export declare const SEEDED_RANDOMNESS: {
|
|
33
|
-
readonly createSearch: (config: SeededRandomnessConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with", "filter", "with"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/
|
|
33
|
+
readonly createSearch: (config: SeededRandomnessConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with", "filter", "with"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
34
34
|
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: SeededRandomnessConfig, { dataflow }: {
|
|
35
35
|
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
36
36
|
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
37
37
|
config: import("../../config").FlowrConfigOptions;
|
|
38
38
|
}) => {
|
|
39
39
|
results: {
|
|
40
|
-
certainty:
|
|
40
|
+
certainty: LintingResultCertainty.Certain;
|
|
41
41
|
function: Identifier;
|
|
42
42
|
range: SourceRange;
|
|
43
43
|
}[];
|
|
@@ -55,6 +55,7 @@ export declare const SEEDED_RANDOMNESS: {
|
|
|
55
55
|
readonly randomnessConsumers: readonly ["jitter", "sample", "sample.int", "arima.sim", "kmeans", "princomp", "rcauchy", "rchisq", "rexp", "rgamma", "rgeom", "rlnorm", "rlogis", "rmultinom", "rnbinom", "rnorm", "rpois", "runif", "pointLabel", "some", "rbernoulli", "rdunif", "generateSeedVectors"];
|
|
56
56
|
};
|
|
57
57
|
readonly tags: readonly [LintingRuleTag.Robustness, LintingRuleTag.Reproducibility];
|
|
58
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
58
59
|
readonly name: "Seeded Randomness";
|
|
59
60
|
readonly description: "Checks whether randomness-based function calls are preceded by a random seed generation function. For consistent reproducibility, functions that use randomness should only be called after a constant random seed is set using a function like `set.seed`.";
|
|
60
61
|
};
|
|
@@ -86,7 +86,7 @@ exports.SEEDED_RANDOMNESS = {
|
|
|
86
86
|
return true;
|
|
87
87
|
})
|
|
88
88
|
.map(element => ({
|
|
89
|
-
certainty: linter_format_1.
|
|
89
|
+
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
90
90
|
function: element.target,
|
|
91
91
|
range: element.range
|
|
92
92
|
})),
|
|
@@ -99,6 +99,8 @@ exports.SEEDED_RANDOMNESS = {
|
|
|
99
99
|
randomnessConsumers: ['jitter', 'sample', 'sample.int', 'arima.sim', 'kmeans', 'princomp', 'rcauchy', 'rchisq', 'rexp', 'rgamma', 'rgeom', 'rlnorm', 'rlogis', 'rmultinom', 'rnbinom', 'rnorm', 'rpois', 'runif', 'pointLabel', 'some', 'rbernoulli', 'rdunif', 'generateSeedVectors'],
|
|
100
100
|
},
|
|
101
101
|
tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility],
|
|
102
|
+
// only finds proper randomness producers and consumers due to its config, but will not find all producers/consumers since not all existing deprecated functions will be in the config
|
|
103
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
102
104
|
name: 'Seeded Randomness',
|
|
103
105
|
description: 'Checks whether randomness-based function calls are preceded by a random seed generation function. For consistent reproducibility, functions that use randomness should only be called after a constant random seed is set using a function like `set.seed`.'
|
|
104
106
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { LintingResult } from '../linter-format';
|
|
2
|
+
import { LintingRuleCertainty } from '../linter-format';
|
|
2
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
3
4
|
import type { SourceRange } from '../../util/range';
|
|
4
5
|
import { LintingRuleTag } from '../linter-tags';
|
|
@@ -34,6 +35,7 @@ export declare const UNUSED_DEFINITION: {
|
|
|
34
35
|
readonly name: "Unused Definitions";
|
|
35
36
|
readonly description: "Checks for unused definitions.";
|
|
36
37
|
readonly tags: readonly [LintingRuleTag.Readability, LintingRuleTag.Smell, LintingRuleTag.QuickFix];
|
|
38
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
37
39
|
readonly defaultConfig: {
|
|
38
40
|
readonly includeFunctionDefinitions: true;
|
|
39
41
|
};
|