@eagleoutice/flowr 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +42 -30
  2. package/abstract-interpretation/data-frame/absint-visitor.d.ts +2 -3
  3. package/abstract-interpretation/data-frame/absint-visitor.js +14 -16
  4. package/abstract-interpretation/data-frame/mappers/function-mapper.js +3 -3
  5. package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
  6. package/abstract-interpretation/data-frame/semantics.js +7 -10
  7. package/abstract-interpretation/data-frame/shape-inference.js +2 -8
  8. package/benchmark/slicer.js +7 -5
  9. package/benchmark/stats/size-of.js +3 -3
  10. package/benchmark/summarizer/second-phase/graph.js +1 -1
  11. package/benchmark/summarizer/second-phase/process.js +1 -1
  12. package/cli/benchmark-app.d.ts +1 -0
  13. package/cli/benchmark-app.js +1 -0
  14. package/cli/benchmark-helper-app.d.ts +1 -0
  15. package/cli/benchmark-helper-app.js +4 -3
  16. package/cli/common/options.js +2 -0
  17. package/cli/repl/commands/repl-query.js +1 -1
  18. package/cli/repl/server/connection.js +14 -5
  19. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  20. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  21. package/control-flow/cfg-simplification.d.ts +6 -0
  22. package/control-flow/cfg-simplification.js +18 -9
  23. package/control-flow/control-flow-graph.d.ts +2 -8
  24. package/control-flow/control-flow-graph.js +1 -6
  25. package/control-flow/extract-cfg.d.ts +2 -2
  26. package/control-flow/extract-cfg.js +52 -63
  27. package/core/pipeline-executor.js +0 -8
  28. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  29. package/core/steps/all/static-slicing/00-slice.js +9 -3
  30. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  31. package/dataflow/environments/append.js +1 -1
  32. package/dataflow/environments/built-in-config.d.ts +12 -4
  33. package/dataflow/environments/built-in-config.js +23 -82
  34. package/dataflow/environments/built-in.d.ts +40 -6
  35. package/dataflow/environments/built-in.js +119 -23
  36. package/dataflow/environments/clone.d.ts +3 -2
  37. package/dataflow/environments/clone.js +6 -5
  38. package/dataflow/environments/define.js +1 -2
  39. package/dataflow/environments/diff.js +1 -3
  40. package/dataflow/environments/environment.d.ts +18 -24
  41. package/dataflow/environments/environment.js +25 -37
  42. package/dataflow/environments/overwrite.d.ts +1 -1
  43. package/dataflow/environments/overwrite.js +1 -1
  44. package/dataflow/environments/remove.d.ts +2 -2
  45. package/dataflow/environments/remove.js +3 -4
  46. package/dataflow/environments/resolve-by-name.d.ts +3 -3
  47. package/dataflow/environments/resolve-by-name.js +4 -5
  48. package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
  49. package/dataflow/eval/resolve/alias-tracking.js +12 -12
  50. package/dataflow/eval/resolve/resolve.js +1 -1
  51. package/dataflow/extractor.js +6 -1
  52. package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
  53. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  54. package/dataflow/graph/graph.d.ts +2 -1
  55. package/dataflow/graph/graph.js +6 -2
  56. package/dataflow/graph/invert-dfg.d.ts +2 -0
  57. package/dataflow/graph/invert-dfg.js +17 -0
  58. package/dataflow/info.d.ts +1 -1
  59. package/dataflow/internal/linker.js +9 -9
  60. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
  61. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
  62. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
  63. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -7
  64. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
  65. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
  66. package/dataflow/processor.d.ts +5 -1
  67. package/documentation/doc-util/doc-env.js +1 -2
  68. package/documentation/doc-util/doc-query.js +1 -1
  69. package/documentation/doc-util/doc-search.js +2 -2
  70. package/documentation/print-cfg-wiki.js +3 -4
  71. package/documentation/print-core-wiki.js +2 -2
  72. package/documentation/print-dataflow-graph-wiki.js +7 -0
  73. package/documentation/print-faq-wiki.js +4 -0
  74. package/documentation/print-linter-wiki.js +32 -4
  75. package/documentation/print-linting-and-testing-wiki.js +13 -1
  76. package/documentation/print-onboarding-wiki.js +4 -0
  77. package/documentation/print-query-wiki.js +12 -3
  78. package/linter/linter-executor.js +1 -2
  79. package/linter/linter-format.d.ts +26 -4
  80. package/linter/linter-format.js +25 -6
  81. package/linter/linter-rules.d.ts +40 -12
  82. package/linter/linter-rules.js +3 -1
  83. package/linter/rules/absolute-path.d.ts +4 -7
  84. package/linter/rules/absolute-path.js +9 -6
  85. package/linter/rules/dataframe-access-validation.d.ts +3 -1
  86. package/linter/rules/dataframe-access-validation.js +3 -1
  87. package/linter/rules/dead-code.d.ts +43 -0
  88. package/linter/rules/dead-code.js +50 -0
  89. package/linter/rules/deprecated-functions.d.ts +3 -2
  90. package/linter/rules/deprecated-functions.js +3 -1
  91. package/linter/rules/file-path-validity.d.ts +4 -4
  92. package/linter/rules/file-path-validity.js +8 -6
  93. package/linter/rules/naming-convention.d.ts +4 -3
  94. package/linter/rules/naming-convention.js +3 -1
  95. package/linter/rules/seeded-randomness.d.ts +4 -3
  96. package/linter/rules/seeded-randomness.js +3 -1
  97. package/linter/rules/unused-definition.d.ts +2 -0
  98. package/linter/rules/unused-definition.js +3 -1
  99. package/package.json +1 -1
  100. package/queries/base-query-format.d.ts +2 -0
  101. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +7 -7
  102. package/queries/catalog/dependencies-query/dependencies-query-executor.js +24 -1
  103. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
  104. package/queries/catalog/dependencies-query/function-info/read-functions.js +5 -2
  105. package/queries/catalog/dependencies-query/function-info/write-functions.js +6 -0
  106. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  107. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  108. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  109. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  110. package/queries/catalog/search-query/search-query-executor.js +1 -1
  111. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  112. package/queries/catalog/static-slice-query/static-slice-query-executor.js +3 -2
  113. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  114. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  115. package/queries/query-print.d.ts +1 -1
  116. package/queries/query-print.js +0 -1
  117. package/queries/query.d.ts +16 -5
  118. package/queries/query.js +24 -11
  119. package/search/flowr-search-builder.d.ts +6 -6
  120. package/search/flowr-search-executor.d.ts +2 -2
  121. package/search/flowr-search-executor.js +1 -1
  122. package/search/flowr-search.d.ts +13 -8
  123. package/search/flowr-search.js +21 -0
  124. package/search/search-executor/search-enrichers.d.ts +87 -20
  125. package/search/search-executor/search-enrichers.js +44 -5
  126. package/search/search-executor/search-generators.d.ts +4 -4
  127. package/search/search-executor/search-generators.js +12 -7
  128. package/search/search-executor/search-mappers.js +3 -2
  129. package/search/search-executor/search-transformer.d.ts +3 -3
  130. package/search/search-executor/search-transformer.js +2 -2
  131. package/slicing/static/fingerprint.js +1 -2
  132. package/slicing/static/slice-call.d.ts +2 -1
  133. package/slicing/static/slice-call.js +3 -3
  134. package/slicing/static/static-slicer.d.ts +6 -5
  135. package/slicing/static/static-slicer.js +13 -7
  136. package/util/collections/arrays.d.ts +2 -0
  137. package/util/collections/arrays.js +9 -0
  138. package/util/containers.d.ts +1 -0
  139. package/util/containers.js +1 -0
  140. package/util/json.js +1 -4
  141. package/util/mermaid/dfg.js +5 -4
  142. package/util/prefix.d.ts +1 -1
  143. package/util/range.d.ts +1 -0
  144. package/util/range.js +5 -1
  145. package/util/version.js +1 -1
@@ -3,6 +3,7 @@ import type { FlowrSearchElements } from '../../search/flowr-search';
3
3
  import { type MergeableRecord } from '../../util/objects';
4
4
  import { type SourceRange } from '../../util/range';
5
5
  import type { LintingResult } from '../linter-format';
6
+ import { LintingRuleCertainty } from '../linter-format';
6
7
  import { LintingRuleTag } from '../linter-tags';
7
8
  export interface DataFrameAccessValidationResult extends LintingResult {
8
9
  /** The type of the data frame access ("column" or "row") */
@@ -29,7 +30,7 @@ export interface DataFrameAccessValidationMetadata extends MergeableRecord {
29
30
  totalAccessed: number;
30
31
  }
31
32
  export declare const DATA_FRAME_ACCESS_VALIDATION: {
32
- readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with"], ParentInformation, FlowrSearchElements<ParentInformation, import("../../search/search-executor/search-enrichers").EnrichedFlowrSearchElement<ParentInformation>[]>>;
33
+ readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with"], ParentInformation, FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>>;
33
34
  readonly processSearchResult: (elements: FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>, config: DataFrameAccessValidationConfig, data: {
34
35
  normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
35
36
  dataflow: import("../../dataflow/info").DataflowInformation;
@@ -45,6 +46,7 @@ export declare const DATA_FRAME_ACCESS_VALIDATION: {
45
46
  readonly info: {
46
47
  readonly name: "Dataframe Access Validation";
47
48
  readonly tags: readonly [LintingRuleTag.Bug, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
49
+ readonly certainty: LintingRuleCertainty.BestEffort;
48
50
  readonly description: "Validates the existance of accessed columns and rows of dataframes.";
49
51
  readonly defaultConfig: {
50
52
  readonly readLoadedData: false;
@@ -65,7 +65,7 @@ exports.DATA_FRAME_ACCESS_VALIDATION = {
65
65
  access: node?.lexeme ?? '???',
66
66
  ...(operand?.type === type_1.RType.Symbol ? { operand: operand.content } : {}),
67
67
  range: node?.info.fullRange ?? node?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
68
- certainty: linter_format_1.LintingCertainty.Definitely
68
+ certainty: linter_format_1.LintingResultCertainty.Certain
69
69
  }));
70
70
  return { results, '.meta': metadata };
71
71
  },
@@ -80,6 +80,8 @@ exports.DATA_FRAME_ACCESS_VALIDATION = {
80
80
  info: {
81
81
  name: 'Dataframe Access Validation',
82
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,
83
85
  description: 'Validates the existance of accessed columns and rows of dataframes.',
84
86
  defaultConfig: { readLoadedData: false }
85
87
  }
@@ -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 { LintingCertainty } from '../linter-format';
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: LintingCertainty.Definitely;
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.LintingCertainty.Definitely,
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, FlowrSearchElementFromQuery<ParentInformation>[]>>;
36
- readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<ParentInformation, FlowrSearchElementFromQuery<ParentInformation>[]>, config: FilePathValidityConfig, data: {
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 = (0, extract_cfg_1.extractSimpleCfg)(data.normalize).graph;
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 = element.queryResult;
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.LintingCertainty.Maybe
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.LintingCertainty.Maybe : linter_format_1.LintingCertainty.Definitely
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 { LintQuickFixReplacement, LintingResult } from '../linter-format';
6
- import { LintingCertainty } from '../linter-format';
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: LintingCertainty;
49
+ certainty: LintingResultCertainty;
50
50
  detectedCasing: CasingConvention;
51
51
  name: string;
52
52
  range: SourceRange;
@@ -62,6 +62,7 @@ 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: {
@@ -132,7 +132,7 @@ exports.NAMING_CONVENTION = {
132
132
  processSearchResult: (elements, config, data) => {
133
133
  const symbols = elements.getElements()
134
134
  .map(m => ({
135
- certainty: linter_format_1.LintingCertainty.Definitely,
135
+ certainty: linter_format_1.LintingResultCertainty.Certain,
136
136
  detectedCasing: detectCasing(m.node.lexeme),
137
137
  name: m.node.lexeme,
138
138
  range: m.node.info.fullRange,
@@ -158,6 +158,8 @@ exports.NAMING_CONVENTION = {
158
158
  },
159
159
  info: {
160
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,
161
163
  description: 'Checks wether the symbols conform to a certain naming convention',
162
164
  tags: [linter_tags_1.LintingRuleTag.Style, linter_tags_1.LintingRuleTag.QuickFix],
163
165
  defaultConfig: {
@@ -1,5 +1,5 @@
1
1
  import type { LintingResult } from '../linter-format';
2
- import { LintingCertainty } from '../linter-format';
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/search-executor/search-enrichers").EnrichedFlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
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: LintingCertainty.Definitely;
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.LintingCertainty.Definitely,
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
  };
@@ -80,7 +80,7 @@ exports.UNUSED_DEFINITION = {
80
80
  // found an unused definition
81
81
  const variableName = element.node.lexeme;
82
82
  return [{
83
- certainty: linter_format_1.LintingCertainty.Maybe,
83
+ certainty: linter_format_1.LintingResultCertainty.Uncertain,
84
84
  variableName,
85
85
  range: element.node.info.fullRange ?? element.node.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
86
86
  quickFix: buildQuickFix(element.node, data.dataflow.graph, data.normalize)
@@ -97,6 +97,8 @@ exports.UNUSED_DEFINITION = {
97
97
  name: 'Unused Definitions',
98
98
  description: 'Checks for unused definitions.',
99
99
  tags: [linter_tags_1.LintingRuleTag.Readability, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.QuickFix],
100
+ // our limited analysis causes unused definitions involving complex reflection etc. not to be included in our result, but unused definitions are correctly validated
101
+ certainty: linter_format_1.LintingRuleCertainty.BestEffort,
100
102
  defaultConfig: {
101
103
  includeFunctionDefinitions: true
102
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -1,6 +1,7 @@
1
1
  import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
2
2
  import type { DataflowInformation } from '../dataflow/info';
3
3
  import type { FlowrConfigOptions } from '../config';
4
+ import type { SemVer } from 'semver';
4
5
  export interface BaseQueryFormat {
5
6
  /** used to select the query type :) */
6
7
  readonly type: string;
@@ -13,6 +14,7 @@ export interface BaseQueryResult {
13
14
  readonly '.meta': BaseQueryMeta;
14
15
  }
15
16
  export interface BasicQueryData {
17
+ readonly lib?: Record<string, SemVer>;
16
18
  readonly ast: NormalizedAst;
17
19
  readonly dataflow: DataflowInformation;
18
20
  readonly config: FlowrConfigOptions;
@@ -41,13 +41,7 @@ function satisfiesCallTargets(id, graph, callTarget) {
41
41
  .filter(([, { types }]) => (0, edge_1.edgeIncludesType)(types, edge_1.EdgeType.Calls))
42
42
  .map(([t]) => t);
43
43
  let builtIn = false;
44
- if (callVertex.environment === undefined) {
45
- /* if we have a call with an unbound environment,
46
- * this only happens if we are sure of built-in relations and want to save references
47
- */
48
- builtIn = true;
49
- }
50
- else {
44
+ if (callVertex.environment !== undefined) {
51
45
  /*
52
46
  * for performance and scoping reasons, flowR will not identify the global linkage,
53
47
  * including any potential built-in mapping.
@@ -57,6 +51,12 @@ function satisfiesCallTargets(id, graph, callTarget) {
57
51
  builtIn = true;
58
52
  }
59
53
  }
54
+ else {
55
+ /* if we have a call with an unbound environment,
56
+ * this only happens if we are sure of built-in relations and want to save references
57
+ */
58
+ builtIn = true;
59
+ }
60
60
  switch (callTarget) {
61
61
  case CallTargets.Any:
62
62
  return callTargets;
@@ -15,6 +15,7 @@ const write_functions_1 = require("./function-info/write-functions");
15
15
  const function_info_1 = require("./function-info/function-info");
16
16
  const identify_link_to_last_call_relation_1 = require("../call-context-query/identify-link-to-last-call-relation");
17
17
  const resolve_argument_1 = require("../../../dataflow/eval/resolve/resolve-argument");
18
+ const assert_1 = require("../../../util/assert");
18
19
  function collectNamespaceAccesses(data, libraries) {
19
20
  /* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
20
21
  (0, visitor_1.visitAst)(data.ast.ast, n => {
@@ -40,7 +41,12 @@ function executeDependenciesQuery(data, queries) {
40
41
  const readFunctions = getFunctionsToCheck(query.readFunctions, ignoreDefault, read_functions_1.ReadFunctions);
41
42
  const writeFunctions = getFunctionsToCheck(query.writeFunctions, ignoreDefault, write_functions_1.WriteFunctions);
42
43
  const numberOfFunctions = libraryFunctions.length + sourceFunctions.length + readFunctions.length + writeFunctions.length;
43
- const results = numberOfFunctions === 0 ? { kinds: {}, '.meta': { timing: 0 } } : (0, query_1.executeQueriesOfSameType)(data, ...makeCallContextQuery(libraryFunctions, 'library'), ...makeCallContextQuery(sourceFunctions, 'source'), ...makeCallContextQuery(readFunctions, 'read'), ...makeCallContextQuery(writeFunctions, 'write'));
44
+ const results = numberOfFunctions === 0 ? { kinds: {}, '.meta': { timing: 0 } } : (0, query_1.executeQueriesOfSameType)(data, [
45
+ makeCallContextQuery(libraryFunctions, 'library'),
46
+ makeCallContextQuery(sourceFunctions, 'source'),
47
+ makeCallContextQuery(readFunctions, 'read'),
48
+ makeCallContextQuery(writeFunctions, 'write')
49
+ ].flat());
44
50
  function getLexeme(argument, id) {
45
51
  if ((argument && argument !== dependencies_query_format_1.Unknown) || !id) {
46
52
  return undefined;
@@ -108,6 +114,8 @@ function dropInfoOnLinkedIds(linkedIds) {
108
114
  }
109
115
  return linkedIds.map(id => typeof id === 'object' ? id.id : id);
110
116
  }
117
+ const readOnlyModes = new Set(['r', 'rt', 'rb']);
118
+ const writeOnlyModes = new Set(['w', 'wt', 'wb', 'a', 'at', 'ab']);
111
119
  function getResults(data, results, kind, functions, makeInfo) {
112
120
  const kindEntries = Object.entries(results?.kinds[kind]?.subkinds ?? {});
113
121
  return kindEntries.flatMap(([name, results]) => results.flatMap(({ id, linkedIds }) => {
@@ -123,6 +131,21 @@ function getResults(data, results, kind, functions, makeInfo) {
123
131
  const record = (0, objects_1.compactRecord)(makeInfo(id, vertex, undefined, undefined, dropInfoOnLinkedIds(linkedIds)));
124
132
  return record ? [record] : [];
125
133
  }
134
+ else if (info.ignoreIf === 'mode-only-read' || info.ignoreIf === 'mode-only-write') {
135
+ (0, assert_1.guard)('mode' in (info.additionalArgs ?? {}), 'Need additional argument mode when checking for mode');
136
+ const margs = info.additionalArgs?.mode;
137
+ (0, assert_1.guard)(margs, 'Need additional argument mode when checking for mode');
138
+ const modeArgs = (0, resolve_argument_1.getArgumentStringValue)(data.config.solver.variables, data.dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue);
139
+ const modeValues = modeArgs?.values().flatMap(v => [...v]) ?? [];
140
+ if (info.ignoreIf === 'mode-only-read' && modeValues.every(m => m && readOnlyModes.has(m))) {
141
+ // all modes are read-only, so we can ignore this
142
+ return [];
143
+ }
144
+ else if (info.ignoreIf === 'mode-only-write' && modeValues.every(m => m && writeOnlyModes.has(m))) {
145
+ // all modes are write-only, so we can ignore this
146
+ return [];
147
+ }
148
+ }
126
149
  const results = [];
127
150
  for (const [arg, values] of foundValues.entries()) {
128
151
  for (const value of values) {
@@ -12,13 +12,17 @@ export type DependencyInfoLink = LinkTo<RegExp | string, Omit<FunctionInfo, 'nam
12
12
  when: DependencyInfoLinkConstraint;
13
13
  } | undefined>;
14
14
  export type DependencyInfoLinkAttachedInfo = DependencyInfoLink['attachLinkInfo'];
15
- export interface FunctionInfo {
16
- package?: string;
17
- name: string;
15
+ export interface FunctionArgInfo {
18
16
  /** the index if the argument can be positional, unnamed in case of something like `...`, if the argument must be given with the name, please leave undefined */
19
17
  argIdx?: number | 'unnamed';
20
18
  argName?: string;
21
- linkTo?: DependencyInfoLink[];
22
19
  resolveValue?: boolean | 'library';
23
- ignoreIf?: 'arg-missing';
20
+ }
21
+ export interface FunctionInfo extends FunctionArgInfo {
22
+ package?: string;
23
+ name: string;
24
+ linkTo?: DependencyInfoLink[];
25
+ ignoreIf?: 'arg-missing' | 'mode-only-read' | 'mode-only-write';
26
+ /** additional info on arguments - e.g. for the mode flag */
27
+ additionalArgs?: Record<string, FunctionArgInfo>;
24
28
  }
@@ -10,8 +10,8 @@ exports.ReadFunctions = [
10
10
  { package: 'base', name: 'read.dcf', argIdx: 0, argName: 'file', resolveValue: true },
11
11
  { package: 'base', name: 'scan', argIdx: 0, argName: 'file', resolveValue: true },
12
12
  { package: 'utils', name: 'read.fwf', argIdx: 0, argName: 'file', resolveValue: true },
13
- { package: 'base', name: 'file', argIdx: 1, argName: 'open', resolveValue: true },
14
- { package: 'base', name: 'url', argIdx: 1, argName: 'open', resolveValue: true },
13
+ { package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
14
+ { package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
15
15
  { package: 'base', name: 'load', argIdx: 0, argName: 'file', resolveValue: true },
16
16
  { package: 'base', name: 'gzfile', argIdx: 1, argName: 'open', resolveValue: true },
17
17
  { package: 'base', name: 'bzfile', argIdx: 1, argName: 'open', resolveValue: true },
@@ -22,6 +22,8 @@ exports.ReadFunctions = [
22
22
  { package: 'base', name: 'matrix', argIdx: 0, argName: 'data', resolveValue: true },
23
23
  { package: 'base', name: 'readRDS', argIdx: 0, argName: 'file', resolveValue: true },
24
24
  { package: 'base', name: 'readLines', argIdx: 0, argName: 'con', resolveValue: true },
25
+ { package: 'base', name: 'readChar', argIdx: 0, argName: 'con', resolveValue: true },
26
+ { package: 'base', name: 'readBin', argIdx: 0, argName: 'con', resolveValue: true },
25
27
  { package: 'base', name: 'readRenviron', argIdx: 0, argName: 'path', resolveValue: true },
26
28
  { package: 'readr', name: 'read_csv', argIdx: 0, argName: 'file', resolveValue: true },
27
29
  { package: 'readr', name: 'read_csv2', argIdx: 0, argName: 'file', resolveValue: true },
@@ -97,5 +99,6 @@ exports.ReadFunctions = [
97
99
  { package: 'stats', name: 'read.ftable', argIdx: 0, argName: 'file', resolveValue: true },
98
100
  { package: 'DBI', name: 'dbReadTable', argIdx: 1, argName: 'name', resolveValue: true },
99
101
  { package: 'DBI', name: 'dbReadTableArrow', argIdx: 1, argName: 'name', resolveValue: true },
102
+ { package: 'jsonlite', name: 'read_json', argIdx: 0, argName: 'path', resolveValue: true },
100
103
  ];
101
104
  //# sourceMappingURL=read-functions.js.map
@@ -19,6 +19,11 @@ exports.WriteFunctions = [
19
19
  { package: 'base', name: 'cat', linkTo: OutputRedirects, argName: 'file', resolveValue: true },
20
20
  { package: 'base', name: 'message', linkTo: OutputRedirects, resolveValue: true },
21
21
  { package: 'base', name: 'warning', linkTo: OutputRedirects, resolveValue: true },
22
+ { package: 'base', name: 'writeLines', argIdx: 1, argName: 'con', resolveValue: true },
23
+ { package: 'base', name: 'writeChar', argIdx: 1, argName: 'con', resolveValue: true },
24
+ { package: 'base', name: 'writeBin', argIdx: 1, argName: 'con', resolveValue: true },
25
+ { package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
26
+ { package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
22
27
  { package: 'readr', name: 'write_csv', argIdx: 1, argName: 'file', resolveValue: true },
23
28
  { package: 'readr', name: 'write_csv2', argIdx: 1, argName: 'file', resolveValue: true },
24
29
  { package: 'readr', name: 'write_delim', argIdx: 1, argName: 'file', resolveValue: true },
@@ -83,5 +88,6 @@ exports.WriteFunctions = [
83
88
  { package: 'rasterpdf', name: 'raster_pdf', argIdx: 0, argName: 'filename', resolveValue: true },
84
89
  { package: 'rasterpdf', name: 'agg_pdf', argIdx: 0, argName: 'filename', resolveValue: true },
85
90
  { package: 'highcharter', name: 'hc_exporting', argName: 'filename', resolveValue: true },
91
+ { package: 'jsonlite', name: 'write_json', argIdx: 1, argName: 'path', resolveValue: true },
86
92
  ];
87
93
  //# sourceMappingURL=write-functions.js.map
@@ -33,7 +33,7 @@ exports.LinterQueryDefinition = {
33
33
  function addLintingRuleResult(ruleName, results, result) {
34
34
  const rule = linter_rules_1.LintingRules[ruleName];
35
35
  result.push(` ╰ **${rule.info.name}** (${ruleName}):`);
36
- for (const certainty of [linter_format_1.LintingCertainty.Definitely, linter_format_1.LintingCertainty.Maybe]) {
36
+ for (const certainty of [linter_format_1.LintingResultCertainty.Certain, linter_format_1.LintingResultCertainty.Uncertain]) {
37
37
  const certaintyResults = results.results.filter(r => r.certainty === certainty);
38
38
  if (certaintyResults.length) {
39
39
  result.push(` ╰ ${certainty}:`);