@eagleoutice/flowr 2.2.13 → 2.2.14

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 (77) hide show
  1. package/README.md +4 -4
  2. package/cli/repl/commands/repl-cfg.d.ts +2 -2
  3. package/cli/repl/commands/repl-cfg.js +4 -4
  4. package/cli/repl/commands/repl-commands.js +2 -2
  5. package/cli/repl/server/connection.js +1 -1
  6. package/cli/script-core/statistics-helper-core.js +1 -1
  7. package/control-flow/extract-cfg.d.ts +2 -2
  8. package/control-flow/extract-cfg.js +10 -10
  9. package/documentation/doc-util/doc-cfg.d.ts +1 -1
  10. package/documentation/doc-util/doc-cfg.js +3 -3
  11. package/documentation/print-cfg-wiki.js +25 -25
  12. package/documentation/print-linter-wiki.d.ts +1 -0
  13. package/documentation/print-linter-wiki.js +76 -0
  14. package/linter/linter-executor.d.ts +9 -0
  15. package/linter/linter-executor.js +26 -0
  16. package/linter/linter-format.d.ts +65 -0
  17. package/linter/linter-format.js +9 -0
  18. package/linter/linter-rules.d.ts +42 -0
  19. package/linter/linter-rules.js +14 -0
  20. package/linter/rules/1-deprecated-functions.d.ts +34 -0
  21. package/linter/rules/1-deprecated-functions.js +54 -0
  22. package/linter/rules/2-file-path-validity.d.ts +48 -0
  23. package/linter/rules/2-file-path-validity.js +93 -0
  24. package/package.json +2 -1
  25. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  26. package/queries/catalog/call-context-query/call-context-query-format.d.ts +2 -2
  27. package/queries/catalog/call-context-query/call-context-query-format.js +5 -1
  28. package/queries/catalog/cluster-query/cluster-query-format.d.ts +2 -0
  29. package/queries/catalog/cluster-query/cluster-query-format.js +5 -1
  30. package/queries/catalog/config-query/config-query-format.d.ts +1 -0
  31. package/queries/catalog/config-query/config-query-format.js +2 -1
  32. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -0
  33. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -1
  34. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +2 -0
  35. package/queries/catalog/dataflow-query/dataflow-query-format.js +9 -1
  36. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -0
  37. package/queries/catalog/dependencies-query/dependencies-query-format.js +10 -1
  38. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -0
  39. package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -1
  40. package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -0
  41. package/queries/catalog/id-map-query/id-map-query-format.js +2 -1
  42. package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -0
  43. package/queries/catalog/lineage-query/lineage-query-format.js +5 -1
  44. package/queries/catalog/linter-query/linter-query-executor.d.ts +3 -0
  45. package/queries/catalog/linter-query/linter-query-executor.js +28 -0
  46. package/queries/catalog/linter-query/linter-query-format.d.ts +80 -0
  47. package/queries/catalog/linter-query/linter-query-format.js +43 -0
  48. package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -0
  49. package/queries/catalog/location-map-query/location-map-query-format.js +2 -1
  50. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -0
  51. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -1
  52. package/queries/catalog/origin-query/origin-query-format.d.ts +2 -0
  53. package/queries/catalog/origin-query/origin-query-format.js +5 -1
  54. package/queries/catalog/project-query/project-query-executor.js +1 -1
  55. package/queries/catalog/project-query/project-query-format.d.ts +1 -0
  56. package/queries/catalog/project-query/project-query-format.js +2 -1
  57. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -0
  58. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -1
  59. package/queries/catalog/search-query/search-query-format.d.ts +1 -0
  60. package/queries/catalog/search-query/search-query-format.js +5 -1
  61. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +2 -0
  62. package/queries/catalog/static-slice-query/static-slice-query-format.js +9 -1
  63. package/queries/query.d.ts +83 -1
  64. package/queries/query.js +2 -0
  65. package/r-bridge/retriever.js +1 -1
  66. package/search/flowr-search-builder.d.ts +31 -2
  67. package/search/flowr-search-builder.js +30 -0
  68. package/search/flowr-search.d.ts +7 -1
  69. package/search/search-executor/search-enrichers.d.ts +73 -0
  70. package/search/search-executor/search-enrichers.js +98 -0
  71. package/search/search-executor/search-generators.d.ts +6 -1
  72. package/search/search-executor/search-generators.js +21 -1
  73. package/search/search-executor/search-mappers.d.ts +19 -0
  74. package/search/search-executor/search-mappers.js +21 -0
  75. package/search/search-executor/search-transformer.d.ts +12 -0
  76. package/search/search-executor/search-transformer.js +11 -1
  77. package/util/version.js +1 -1
@@ -0,0 +1,42 @@
1
+ import type { LintingRule } from './linter-format';
2
+ /**
3
+ * The registry of currently supported linting rules.
4
+ * A linting rule can be executed on a dataflow pipeline result using {@link executeLintingRule}.
5
+ */
6
+ export declare const LintingRules: {
7
+ readonly 'deprecated-functions': {
8
+ readonly createSearch: (_config: import("./rules/1-deprecated-functions").DeprecatedFunctionsConfig) => 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/search-executor/search-enrichers").EnrichedFlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
9
+ 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: import("./rules/1-deprecated-functions").DeprecatedFunctionsConfig) => {
10
+ results: {
11
+ certainty: import("./linter-format").LintingCertainty.Definitely;
12
+ function: import("../dataflow/environments/identifier").Identifier;
13
+ range: import("../util/range").SourceRange;
14
+ }[];
15
+ '.meta': import("./rules/1-deprecated-functions").DeprecatedFunctionsMetadata;
16
+ };
17
+ readonly prettyPrint: (result: import("./rules/1-deprecated-functions").DeprecatedFunctionsResult) => string;
18
+ readonly defaultConfig: {
19
+ readonly 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"];
20
+ };
21
+ };
22
+ readonly 'file-path-validity': {
23
+ readonly createSearch: (config: import("./rules/2-file-path-validity").FilePathValidityConfig) => import("../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], 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").FlowrSearchElementFromQuery<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
24
+ readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElementFromQuery<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: import("./rules/2-file-path-validity").FilePathValidityConfig, data: {
25
+ normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
26
+ dataflow: import("../dataflow/info").DataflowInformation;
27
+ }) => {
28
+ results: import("./rules/2-file-path-validity").FilePathValidityResult[];
29
+ ".meta": import("./rules/2-file-path-validity").FilePathValidityMetadata;
30
+ };
31
+ readonly prettyPrint: (result: import("./rules/2-file-path-validity").FilePathValidityResult) => string;
32
+ readonly defaultConfig: {
33
+ readonly additionalReadFunctions: [];
34
+ readonly additionalWriteFunctions: [];
35
+ readonly includeUnknown: false;
36
+ };
37
+ };
38
+ };
39
+ export type LintingRuleNames = keyof typeof LintingRules;
40
+ export type LintingRuleMetadata<Name extends LintingRuleNames> = typeof LintingRules[Name] extends LintingRule<infer _Result, infer Metadata, infer _Config, infer _Info, infer _Elements> ? Metadata : never;
41
+ export type LintingRuleResult<Name extends LintingRuleNames> = typeof LintingRules[Name] extends LintingRule<infer Result, infer _Metadata, infer _Config, infer _Info, infer _Elements> ? Result : never;
42
+ export type LintingRuleConfig<Name extends LintingRuleNames> = typeof LintingRules[Name] extends LintingRule<infer _Result, infer _Metadata, infer Config, infer _Info, infer _Elements> ? Config : never;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LintingRules = void 0;
4
+ const _1_deprecated_functions_1 = require("./rules/1-deprecated-functions");
5
+ const _2_file_path_validity_1 = require("./rules/2-file-path-validity");
6
+ /**
7
+ * The registry of currently supported linting rules.
8
+ * A linting rule can be executed on a dataflow pipeline result using {@link executeLintingRule}.
9
+ */
10
+ exports.LintingRules = {
11
+ 'deprecated-functions': _1_deprecated_functions_1.R1_DEPRECATED_FUNCTIONS,
12
+ 'file-path-validity': _2_file_path_validity_1.R2_FILE_PATH_VALIDITY
13
+ };
14
+ //# sourceMappingURL=linter-rules.js.map
@@ -0,0 +1,34 @@
1
+ import type { LintingResult } from '../linter-format';
2
+ import { LintingCertainty } from '../linter-format';
3
+ import type { MergeableRecord } from '../../util/objects';
4
+ import type { SourceRange } from '../../util/range';
5
+ import type { Identifier } from '../../dataflow/environments/identifier';
6
+ export interface DeprecatedFunctionsResult extends LintingResult {
7
+ function: string;
8
+ range: SourceRange;
9
+ }
10
+ export interface DeprecatedFunctionsConfig extends MergeableRecord {
11
+ /**
12
+ * The list of function names that should be marked as deprecated.
13
+ */
14
+ deprecatedFunctions: string[];
15
+ }
16
+ export interface DeprecatedFunctionsMetadata extends MergeableRecord {
17
+ totalRelevant: number;
18
+ totalNotDeprecated: number;
19
+ }
20
+ export declare const R1_DEPRECATED_FUNCTIONS: {
21
+ readonly createSearch: (_config: DeprecatedFunctionsConfig) => 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/search-executor/search-enrichers").EnrichedFlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
22
+ 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: DeprecatedFunctionsConfig) => {
23
+ results: {
24
+ certainty: LintingCertainty.Definitely;
25
+ function: Identifier;
26
+ range: SourceRange;
27
+ }[];
28
+ '.meta': DeprecatedFunctionsMetadata;
29
+ };
30
+ readonly prettyPrint: (result: DeprecatedFunctionsResult) => string;
31
+ readonly defaultConfig: {
32
+ readonly 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"];
33
+ };
34
+ };
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.R1_DEPRECATED_FUNCTIONS = void 0;
4
+ const linter_format_1 = require("../linter-format");
5
+ const flowr_search_builder_1 = require("../../search/flowr-search-builder");
6
+ const dfg_1 = require("../../util/mermaid/dfg");
7
+ const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
8
+ exports.R1_DEPRECATED_FUNCTIONS = {
9
+ createSearch: (_config) => flowr_search_builder_1.Q.all().with(search_enrichers_1.Enrichment.CallTargets),
10
+ processSearchResult: (elements, config) => {
11
+ const metadata = {
12
+ totalRelevant: 0,
13
+ totalNotDeprecated: 0
14
+ };
15
+ return {
16
+ results: elements.getElements()
17
+ .flatMap(element => {
18
+ const targets = (0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.CallTargets).targets;
19
+ // if there is a call target that is not built-in (ie a custom function), we don't want to mark it as deprecated
20
+ // eventually we'd want to solve this with an argument to the CallTargets enrichment like satisfiesCallTargets does!
21
+ if (targets.some(t => typeof t !== 'string')) {
22
+ return [];
23
+ }
24
+ return targets.map(target => {
25
+ metadata.totalRelevant++;
26
+ return {
27
+ range: element.node.info.fullRange,
28
+ target: target
29
+ };
30
+ });
31
+ })
32
+ .filter(element => {
33
+ if (config.deprecatedFunctions.includes(element.target)) {
34
+ return true;
35
+ }
36
+ else {
37
+ metadata.totalNotDeprecated++;
38
+ return false;
39
+ }
40
+ })
41
+ .map(element => ({
42
+ certainty: linter_format_1.LintingCertainty.Definitely,
43
+ function: element.target,
44
+ range: element.range
45
+ })),
46
+ '.meta': metadata
47
+ };
48
+ },
49
+ prettyPrint: result => `Function ${result.function} at ${(0, dfg_1.formatRange)(result.range)}`,
50
+ defaultConfig: {
51
+ 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',]
52
+ }
53
+ };
54
+ //# sourceMappingURL=1-deprecated-functions.js.map
@@ -0,0 +1,48 @@
1
+ import type { LintingResult } from '../linter-format';
2
+ import type { MergeableRecord } from '../../util/objects';
3
+ 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
+ import type { FunctionInfo } from '../../queries/catalog/dependencies-query/function-info/function-info';
7
+ export interface FilePathValidityResult extends LintingResult {
8
+ filePath: string;
9
+ range: SourceRange;
10
+ }
11
+ export interface FilePathValidityConfig extends MergeableRecord {
12
+ /**
13
+ * The set of functions that should additionally be considered as reading a file path.
14
+ * Entries in this array use the {@link FunctionInfo} format from the dependencies query.
15
+ */
16
+ additionalReadFunctions: FunctionInfo[];
17
+ /**
18
+ * The set of functions that should additionally be considered as writing to a file path.
19
+ * Entries in this array use the {@link FunctionInfo} format from the dependencies query.
20
+ */
21
+ additionalWriteFunctions: FunctionInfo[];
22
+ /**
23
+ * Whether unknown file paths should be included as linting results.
24
+ */
25
+ includeUnknown: boolean;
26
+ }
27
+ export interface FilePathValidityMetadata extends MergeableRecord {
28
+ totalReads: number;
29
+ totalUnknown: number;
30
+ totalWritesBeforeAlways: number;
31
+ totalValid: number;
32
+ }
33
+ export declare const R2_FILE_PATH_VALIDITY: {
34
+ readonly createSearch: (config: FilePathValidityConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], ParentInformation, import("../../search/flowr-search").FlowrSearchElements<ParentInformation, FlowrSearchElementFromQuery<ParentInformation>[]>>;
35
+ readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<ParentInformation, FlowrSearchElementFromQuery<ParentInformation>[]>, config: FilePathValidityConfig, data: {
36
+ normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
37
+ dataflow: import("../../dataflow/info").DataflowInformation;
38
+ }) => {
39
+ results: FilePathValidityResult[];
40
+ ".meta": FilePathValidityMetadata;
41
+ };
42
+ readonly prettyPrint: (result: FilePathValidityResult) => string;
43
+ readonly defaultConfig: {
44
+ readonly additionalReadFunctions: [];
45
+ readonly additionalWriteFunctions: [];
46
+ readonly includeUnknown: false;
47
+ };
48
+ };
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.R2_FILE_PATH_VALIDITY = void 0;
4
+ const linter_format_1 = require("../linter-format");
5
+ const flowr_search_builder_1 = require("../../search/flowr-search-builder");
6
+ const dfg_1 = require("../../util/mermaid/dfg");
7
+ const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format");
8
+ const built_in_source_1 = require("../../dataflow/internal/process/functions/call/built-in/built-in-source");
9
+ const logic_1 = require("../../util/logic");
10
+ const config_1 = require("../../config");
11
+ const retriever_1 = require("../../r-bridge/retriever");
12
+ const read_functions_1 = require("../../queries/catalog/dependencies-query/function-info/read-functions");
13
+ const write_functions_1 = require("../../queries/catalog/dependencies-query/function-info/write-functions");
14
+ const extract_cfg_1 = require("../../control-flow/extract-cfg");
15
+ const happens_before_1 = require("../../control-flow/happens-before");
16
+ exports.R2_FILE_PATH_VALIDITY = {
17
+ createSearch: (config) => flowr_search_builder_1.Q.fromQuery({
18
+ type: 'dependencies',
19
+ // we only want to check read and write functions, so we explicitly clear all others
20
+ ignoreDefaultFunctions: true,
21
+ readFunctions: read_functions_1.ReadFunctions.concat(config.additionalReadFunctions),
22
+ writeFunctions: write_functions_1.WriteFunctions.concat(config.additionalWriteFunctions)
23
+ }),
24
+ processSearchResult: (elements, config, data) => {
25
+ const cfg = (0, extract_cfg_1.extractSimpleCfg)(data.normalize).graph;
26
+ const metadata = {
27
+ totalReads: 0,
28
+ totalUnknown: 0,
29
+ totalWritesBeforeAlways: 0,
30
+ totalValid: 0
31
+ };
32
+ return {
33
+ results: elements.getElements().flatMap(element => {
34
+ const results = element.queryResult;
35
+ const matchingRead = results.readData.find(r => r.nodeId == element.node.info.id);
36
+ if (!matchingRead) {
37
+ return [];
38
+ }
39
+ metadata.totalReads++;
40
+ const range = element.node.info.fullRange;
41
+ // check if we can't parse the file path statically
42
+ if (matchingRead.source === dependencies_query_format_1.Unknown) {
43
+ metadata.totalUnknown++;
44
+ if (config.includeUnknown) {
45
+ return [{
46
+ range,
47
+ filePath: dependencies_query_format_1.Unknown,
48
+ certainty: linter_format_1.LintingCertainty.Maybe
49
+ }];
50
+ }
51
+ else {
52
+ return [];
53
+ }
54
+ }
55
+ // check if any write to the same file happens before the read, and exclude this case if so
56
+ const writesToFile = results.writtenData.filter(r => samePath(r.destination, matchingRead.source));
57
+ const writesBefore = writesToFile.map(w => (0, happens_before_1.happensBefore)(cfg, w.nodeId, element.node.info.id));
58
+ if (writesBefore.some(w => w === logic_1.Ternary.Always)) {
59
+ metadata.totalWritesBeforeAlways++;
60
+ return [];
61
+ }
62
+ // check if the file exists!
63
+ const paths = (0, built_in_source_1.findSource)(matchingRead.source, {
64
+ referenceChain: element.node.info.file ? [(0, retriever_1.requestFromInput)(`file://${element.node.info.file}`)] : []
65
+ });
66
+ if (paths && paths.length) {
67
+ metadata.totalValid++;
68
+ return [];
69
+ }
70
+ return [{
71
+ range,
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
74
+ }];
75
+ }),
76
+ '.meta': metadata
77
+ };
78
+ },
79
+ prettyPrint: result => `Path ${result.filePath} at ${(0, dfg_1.formatRange)(result.range)}`,
80
+ defaultConfig: {
81
+ additionalReadFunctions: [],
82
+ additionalWriteFunctions: [],
83
+ includeUnknown: false
84
+ }
85
+ };
86
+ function samePath(a, b) {
87
+ if ((0, config_1.getConfig)().solver.resolveSource?.ignoreCapitalization === true) {
88
+ a = a.toLowerCase();
89
+ b = b.toLowerCase();
90
+ }
91
+ return a === b;
92
+ }
93
+ //# sourceMappingURL=2-file-path-validity.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.2.13",
3
+ "version": "2.2.14",
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": {
@@ -37,6 +37,7 @@
37
37
  "wiki:onboarding": "ts-node src/documentation/print-onboarding-wiki.ts",
38
38
  "wiki:faq": "ts-node src/documentation/print-faq-wiki.ts",
39
39
  "wiki:cfg": "ts-node src/documentation/print-cfg-wiki.ts",
40
+ "wiki:linter": "ts-node src/documentation/print-linter-wiki.ts",
40
41
  "gen:readme": "ts-node src/documentation/print-readme.ts",
41
42
  "build": "tsc --project .",
42
43
  "build-dev": "npm run build && npm run build:copy-wasm",
@@ -180,7 +180,7 @@ function executeCallContextQueries({ dataflow: { graph }, ast }, queries) {
180
180
  const { promotedQueries, requiresCfg } = promoteQueryCallNames(queries);
181
181
  let cfg = undefined;
182
182
  if (requiresCfg) {
183
- cfg = (0, extract_cfg_1.extractCFG)(ast, graph, []);
183
+ cfg = (0, extract_cfg_1.extractCfg)(ast, graph, []);
184
184
  }
185
185
  const queriesWhichWantAliases = promotedQueries.filter(q => q.includeAliases);
186
186
  for (const [nodeId, info] of graph.vertices(true)) {
@@ -56,7 +56,7 @@ export interface DefaultCallContextQueryFormat<RegexType extends RegExp | string
56
56
  * For now, this uses the static Control-Flow-Graph produced by flowR as the FD over-approximation is still not stable (see #1005).
57
57
  * In short, this means that we are unable to detect origins over function call boundaries but plan on being more precise in the future.
58
58
  */
59
- interface LinkToLastCall<CallName extends RegExp | string = RegExp | string> extends BaseQueryFormat {
59
+ export interface LinkToLastCall<CallName extends RegExp | string = RegExp | string> extends BaseQueryFormat {
60
60
  readonly type: 'link-to-last-call';
61
61
  /** Regex regarding the function name of the last call. Similar to {@link DefaultCallContextQueryFormat#callName}, strings are interpreted as a `RegExp`. */
62
62
  readonly callName: CallName;
@@ -110,5 +110,5 @@ export declare const CallContextQueryDefinition: {
110
110
  readonly executor: typeof executeCallContextQueries;
111
111
  readonly asciiSummarizer: (formatter: OutputFormatter, processed: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>, queryResults: BaseQueryResult, result: string[]) => boolean;
112
112
  readonly schema: Joi.ObjectSchema<any>;
113
+ readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
113
114
  };
114
- export {};
@@ -39,6 +39,10 @@ exports.CallContextQueryDefinition = {
39
39
  includeUndefinedFiles: joi_1.default.boolean().optional().description('If `fileFilter` is set, but a nodes `file` attribute is `undefined`, should we include it in the results? Defaults to `true`.')
40
40
  }).optional().description('Filter that, when set, a node\'s file attribute must match to be considered'),
41
41
  linkTo: joi_1.default.alternatives(CallContextQueryLinkTo, joi_1.default.array().items(CallContextQueryLinkTo)).optional().description('Links the current call to the last call of the given kind. This way, you can link a call like `points` to the latest graphics plot etc.')
42
- }).description('Call context query used to find calls in the dataflow graph')
42
+ }).description('Call context query used to find calls in the dataflow graph'),
43
+ flattenInvolvedNodes: (queryResults) => {
44
+ const out = queryResults;
45
+ return Object.values(out.kinds).flatMap(({ subkinds }) => Object.values(subkinds).flatMap(subkinds => subkinds.map(subkind => subkind.id)));
46
+ }
43
47
  };
44
48
  //# sourceMappingURL=call-context-query-format.js.map
@@ -2,6 +2,7 @@ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
2
  import Joi from 'joi';
3
3
  import type { DataflowGraphClusters } from '../../../dataflow/cluster';
4
4
  import { executeDataflowClusterQuery } from './cluster-query-executor';
5
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
5
6
  /**
6
7
  * Calculates and returns all clusters encountered in the dataflow graph.
7
8
  */
@@ -69,4 +70,5 @@ export declare const ClusterQueryDefinition: {
69
70
  readonly dependencies: readonly ["normalize"];
70
71
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
71
72
  readonly schema: Joi.ObjectSchema<any>;
73
+ readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
72
74
  };
@@ -27,6 +27,10 @@ exports.ClusterQueryDefinition = {
27
27
  },
28
28
  schema: joi_1.default.object({
29
29
  type: joi_1.default.string().valid('dataflow-cluster').required().description('The type of the query.'),
30
- }).description('The cluster query calculates and returns all clusters in the dataflow graph.')
30
+ }).description('The cluster query calculates and returns all clusters in the dataflow graph.'),
31
+ flattenInvolvedNodes: (queryResults) => {
32
+ const out = queryResults;
33
+ return out.clusters.flatMap(({ members }) => members);
34
+ }
31
35
  };
32
36
  //# sourceMappingURL=cluster-query-format.js.map
@@ -13,4 +13,5 @@ export declare const ConfigQueryDefinition: {
13
13
  readonly executor: typeof executeConfigQuery;
14
14
  readonly asciiSummarizer: (formatter: OutputFormatter, _processed: unknown, queryResults: BaseQueryResult, result: string[]) => boolean;
15
15
  readonly schema: Joi.ObjectSchema<any>;
16
+ readonly flattenInvolvedNodes: () => never[];
16
17
  };
@@ -19,6 +19,7 @@ exports.ConfigQueryDefinition = {
19
19
  },
20
20
  schema: joi_1.default.object({
21
21
  type: joi_1.default.string().valid('config').required().description('The type of the query.'),
22
- }).description('The config query retrieves the current configuration of the flowR instance.')
22
+ }).description('The config query retrieves the current configuration of the flowR instance.'),
23
+ flattenInvolvedNodes: () => []
23
24
  };
24
25
  //# sourceMappingURL=config-query-format.js.map
@@ -69,4 +69,5 @@ export declare const DataflowLensQueryDefinition: {
69
69
  readonly dependencies: readonly ["normalize"];
70
70
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
71
71
  readonly schema: Joi.ObjectSchema<any>;
72
+ readonly flattenInvolvedNodes: () => never[];
72
73
  };
@@ -19,6 +19,7 @@ exports.DataflowLensQueryDefinition = {
19
19
  },
20
20
  schema: joi_1.default.object({
21
21
  type: joi_1.default.string().valid('dataflow-lens').required().description('The type of the query.'),
22
- }).description('The dataflow-lens query returns a simplified view on the dataflow graph')
22
+ }).description('The dataflow-lens query returns a simplified view on the dataflow graph'),
23
+ flattenInvolvedNodes: () => []
23
24
  };
24
25
  //# sourceMappingURL=dataflow-lens-query-format.js.map
@@ -2,6 +2,7 @@ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
2
  import type { DataflowGraph } from '../../../dataflow/graph/graph';
3
3
  import { executeDataflowQuery } from './dataflow-query-executor';
4
4
  import Joi from 'joi';
5
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
5
6
  /**
6
7
  * Simple re-returns the dataflow graph of the analysis.
7
8
  */
@@ -69,4 +70,5 @@ export declare const DataflowQueryDefinition: {
69
70
  readonly dependencies: readonly ["normalize"];
70
71
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
71
72
  readonly schema: Joi.ObjectSchema<any>;
73
+ readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
72
74
  };
@@ -19,6 +19,14 @@ exports.DataflowQueryDefinition = {
19
19
  },
20
20
  schema: joi_1.default.object({
21
21
  type: joi_1.default.string().valid('dataflow').required().description('The type of the query.'),
22
- }).description('The dataflow query simply returns the dataflow graph, there is no need to pass it multiple times!')
22
+ }).description('The dataflow query simply returns the dataflow graph, there is no need to pass it multiple times!'),
23
+ flattenInvolvedNodes: queryResults => {
24
+ const flattened = [];
25
+ const out = queryResults;
26
+ for (const id of out.graph.idMap?.keys() ?? []) {
27
+ flattened.push(id);
28
+ }
29
+ return flattened;
30
+ }
23
31
  };
24
32
  //# sourceMappingURL=dataflow-query-format.js.map
@@ -94,4 +94,5 @@ export declare const DependenciesQueryDefinition: {
94
94
  readonly dependencies: readonly ["normalize"];
95
95
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
96
96
  readonly schema: Joi.ObjectSchema<any>;
97
+ readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
97
98
  };
@@ -53,6 +53,15 @@ exports.DependenciesQueryDefinition = {
53
53
  sourceFunctions: functionInfoSchema.description('The set of source functions to search for.'),
54
54
  readFunctions: functionInfoSchema.description('The set of data reading functions to search for.'),
55
55
  writeFunctions: functionInfoSchema.description('The set of data writing functions to search for.'),
56
- }).description('The dependencies query retrieves and returns the set of all dependencies in the dataflow graph, which includes libraries, sourced files, read data, and written data.')
56
+ }).description('The dependencies query retrieves and returns the set of all dependencies in the dataflow graph, which includes libraries, sourced files, read data, and written data.'),
57
+ flattenInvolvedNodes: (queryResults) => {
58
+ const out = queryResults;
59
+ return [
60
+ ...out.libraries.map(library => library.nodeId),
61
+ ...out.sourcedFiles.map(sourced => sourced.nodeId),
62
+ ...out.readData.map(read => read.nodeId),
63
+ ...out.writtenData.map(write => write.nodeId)
64
+ ];
65
+ }
57
66
  };
58
67
  //# sourceMappingURL=dependencies-query-format.js.map
@@ -68,4 +68,5 @@ export declare const HappensBeforeQueryDefinition: {
68
68
  readonly dependencies: readonly ["normalize"];
69
69
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
70
70
  readonly schema: Joi.ObjectSchema<any>;
71
+ readonly flattenInvolvedNodes: () => never[];
71
72
  };
@@ -22,6 +22,7 @@ exports.HappensBeforeQueryDefinition = {
22
22
  type: joi_1.default.string().valid('happens-before').required().description('The type of the query.'),
23
23
  a: joi_1.default.string().required().description('The first slicing criterion.'),
24
24
  b: joi_1.default.string().required().description('The second slicing criterion.')
25
- }).description('Happens-Before tracks whether a always happens before b.')
25
+ }).description('Happens-Before tracks whether a always happens before b.'),
26
+ flattenInvolvedNodes: () => []
26
27
  };
27
28
  //# sourceMappingURL=happens-before-query-format.js.map
@@ -65,4 +65,5 @@ export declare const IdMapQueryDefinition: {
65
65
  readonly dependencies: readonly ["normalize"];
66
66
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
67
67
  readonly schema: Joi.ObjectSchema<any>;
68
+ readonly flattenInvolvedNodes: () => never[];
68
69
  };
@@ -19,6 +19,7 @@ exports.IdMapQueryDefinition = {
19
19
  },
20
20
  schema: joi_1.default.object({
21
21
  type: joi_1.default.string().valid('id-map').required().description('The type of the query.'),
22
- }).description('The id map query retrieves the id map from the normalized AST.')
22
+ }).description('The id map query retrieves the id map from the normalized AST.'),
23
+ flattenInvolvedNodes: () => []
23
24
  };
24
25
  //# sourceMappingURL=id-map-query-format.js.map
@@ -71,4 +71,5 @@ export declare const LineageQueryDefinition: {
71
71
  readonly dependencies: readonly ["normalize"];
72
72
  }>>, queryResults: BaseQueryResult, result: string[]) => true;
73
73
  readonly schema: Joi.ObjectSchema<any>;
74
+ readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
74
75
  };
@@ -22,6 +22,10 @@ exports.LineageQueryDefinition = {
22
22
  schema: joi_1.default.object({
23
23
  type: joi_1.default.string().valid('lineage').required().description('The type of the query.'),
24
24
  criterion: joi_1.default.string().required().description('The slicing criterion of the node to get the lineage of.')
25
- }).description('Lineage query used to find the lineage of a node in the dataflow graph')
25
+ }).description('Lineage query used to find the lineage of a node in the dataflow graph'),
26
+ flattenInvolvedNodes: (queryResults) => {
27
+ const out = queryResults;
28
+ return Object.values(out.lineages).flatMap(lineage => [...lineage]);
29
+ }
26
30
  };
27
31
  //# sourceMappingURL=lineage-query-format.js.map
@@ -0,0 +1,3 @@
1
+ import type { BasicQueryData } from '../../base-query-format';
2
+ import type { LinterQuery, LinterQueryResult } from './linter-query-format';
3
+ export declare function executeLinterQuery({ ast, dataflow }: BasicQueryData, queries: readonly LinterQuery[]): LinterQueryResult;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeLinterQuery = executeLinterQuery;
4
+ const linter_rules_1 = require("../../../linter/linter-rules");
5
+ const log_1 = require("../../../util/log");
6
+ const linter_executor_1 = require("../../../linter/linter-executor");
7
+ function executeLinterQuery({ ast, dataflow }, queries) {
8
+ const flattened = queries.flatMap(q => q.rules ?? Object.keys(linter_rules_1.LintingRules));
9
+ const distinct = new Set(flattened);
10
+ if (distinct.size !== flattened.length) {
11
+ const pretty = [...distinct].filter(r => flattened.indexOf(r) !== flattened.lastIndexOf(r)).map(r => typeof r === 'string' ? r : r.name).join(', ');
12
+ log_1.log.warn(`Linter query collection contains duplicate rules ${pretty}, only linting for each rule once`);
13
+ }
14
+ const results = { results: {} };
15
+ const start = Date.now();
16
+ const input = { normalize: ast, dataflow };
17
+ for (const entry of distinct) {
18
+ const ruleName = typeof entry === 'string' ? entry : entry.name;
19
+ results.results[ruleName] = (0, linter_executor_1.executeLintingRule)(ruleName, input, entry?.config);
20
+ }
21
+ return {
22
+ ...results,
23
+ '.meta': {
24
+ timing: Date.now() - start
25
+ }
26
+ };
27
+ }
28
+ //# sourceMappingURL=linter-query-executor.js.map