@eagleoutice/flowr 2.2.14 → 2.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/README.md +210 -6
  2. package/benchmark/slicer.d.ts +3 -1
  3. package/benchmark/slicer.js +8 -5
  4. package/benchmark/summarizer/first-phase/process.d.ts +2 -1
  5. package/benchmark/summarizer/first-phase/process.js +2 -2
  6. package/cli/benchmark-app.d.ts +1 -0
  7. package/cli/benchmark-app.js +4 -1
  8. package/cli/benchmark-helper-app.d.ts +1 -0
  9. package/cli/benchmark-helper-app.js +7 -8
  10. package/cli/common/options.js +2 -0
  11. package/cli/export-quads-app.js +2 -1
  12. package/cli/flowr.js +58 -57
  13. package/cli/repl/commands/repl-cfg.js +13 -13
  14. package/cli/repl/commands/repl-commands.js +3 -3
  15. package/cli/repl/commands/repl-dataflow.js +10 -10
  16. package/cli/repl/commands/repl-execute.d.ts +2 -3
  17. package/cli/repl/commands/repl-execute.js +5 -4
  18. package/cli/repl/commands/repl-lineage.js +4 -4
  19. package/cli/repl/commands/repl-main.d.ts +12 -1
  20. package/cli/repl/commands/repl-normalize.js +6 -6
  21. package/cli/repl/commands/repl-parse.js +2 -2
  22. package/cli/repl/commands/repl-query.js +9 -9
  23. package/cli/repl/commands/repl-version.js +1 -1
  24. package/cli/repl/core.d.ts +5 -2
  25. package/cli/repl/core.js +10 -8
  26. package/cli/repl/server/connection.d.ts +3 -1
  27. package/cli/repl/server/connection.js +7 -5
  28. package/cli/repl/server/server.d.ts +3 -2
  29. package/cli/repl/server/server.js +4 -2
  30. package/cli/script-core/statistics-core.d.ts +2 -1
  31. package/cli/script-core/statistics-core.js +2 -2
  32. package/cli/script-core/statistics-helper-core.d.ts +2 -1
  33. package/cli/script-core/statistics-helper-core.js +5 -4
  34. package/cli/slicer-app.js +4 -2
  35. package/cli/statistics-app.js +2 -1
  36. package/cli/statistics-helper-app.js +2 -1
  37. package/config.d.ts +12 -10
  38. package/config.js +27 -43
  39. package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
  40. package/control-flow/cfg-dead-code.d.ts +4 -0
  41. package/control-flow/cfg-dead-code.js +124 -0
  42. package/control-flow/cfg-simplification.d.ts +19 -6
  43. package/control-flow/cfg-simplification.js +23 -19
  44. package/control-flow/control-flow-graph.d.ts +3 -1
  45. package/control-flow/control-flow-graph.js +5 -0
  46. package/control-flow/dfg-cfg-guided-visitor.d.ts +9 -7
  47. package/control-flow/dfg-cfg-guided-visitor.js +16 -5
  48. package/control-flow/extract-cfg.d.ts +4 -2
  49. package/control-flow/extract-cfg.js +63 -59
  50. package/control-flow/semantic-cfg-guided-visitor.d.ts +36 -9
  51. package/control-flow/semantic-cfg-guided-visitor.js +73 -20
  52. package/control-flow/simple-visitor.d.ts +4 -0
  53. package/control-flow/simple-visitor.js +14 -0
  54. package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
  55. package/core/pipeline-executor.d.ts +4 -1
  56. package/core/pipeline-executor.js +6 -5
  57. package/core/steps/all/core/10-normalize.d.ts +2 -0
  58. package/core/steps/all/core/10-normalize.js +1 -1
  59. package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
  60. package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
  61. package/core/steps/all/core/20-dataflow.d.ts +2 -1
  62. package/core/steps/all/core/20-dataflow.js +2 -2
  63. package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
  64. package/core/steps/all/static-slicing/00-slice.js +2 -2
  65. package/core/steps/pipeline/default-pipelines.d.ts +32 -31
  66. package/core/steps/pipeline/default-pipelines.js +8 -8
  67. package/core/steps/pipeline-step.d.ts +2 -1
  68. package/dataflow/environments/built-in-config.d.ts +4 -3
  69. package/dataflow/environments/built-in.d.ts +16 -1
  70. package/dataflow/environments/built-in.js +11 -5
  71. package/dataflow/environments/default-builtin-config.js +5 -3
  72. package/dataflow/environments/define.d.ts +2 -1
  73. package/dataflow/environments/define.js +4 -5
  74. package/dataflow/environments/remove.d.ts +6 -0
  75. package/dataflow/environments/remove.js +29 -0
  76. package/dataflow/environments/resolve-by-name.d.ts +0 -36
  77. package/dataflow/environments/resolve-by-name.js +0 -240
  78. package/dataflow/eval/resolve/alias-tracking.d.ts +92 -0
  79. package/dataflow/eval/resolve/alias-tracking.js +352 -0
  80. package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
  81. package/dataflow/eval/resolve/resolve-argument.js +118 -0
  82. package/dataflow/eval/resolve/resolve.d.ts +37 -0
  83. package/dataflow/eval/resolve/resolve.js +95 -0
  84. package/dataflow/eval/values/general.d.ts +27 -0
  85. package/dataflow/eval/values/general.js +73 -0
  86. package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
  87. package/dataflow/eval/values/intervals/interval-constants.js +27 -0
  88. package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
  89. package/dataflow/eval/values/logical/logical-constants.js +31 -0
  90. package/dataflow/eval/values/r-value.d.ts +58 -0
  91. package/dataflow/eval/values/r-value.js +90 -0
  92. package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
  93. package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
  94. package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
  95. package/dataflow/eval/values/sets/set-constants.js +34 -0
  96. package/dataflow/eval/values/string/string-constants.d.ts +8 -0
  97. package/dataflow/eval/values/string/string-constants.js +45 -0
  98. package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
  99. package/dataflow/eval/values/vectors/vector-constants.js +35 -0
  100. package/dataflow/extractor.d.ts +2 -1
  101. package/dataflow/extractor.js +2 -1
  102. package/dataflow/graph/unknown-replacement.d.ts +11 -0
  103. package/dataflow/graph/unknown-replacement.js +12 -0
  104. package/dataflow/graph/unknown-side-effect.d.ts +7 -0
  105. package/dataflow/graph/unknown-side-effect.js +13 -0
  106. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
  107. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +8 -5
  108. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
  109. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +15 -13
  110. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +20 -18
  111. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
  112. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
  113. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -4
  114. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
  115. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +11 -5
  116. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +5 -3
  117. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +26 -29
  118. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
  119. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +23 -0
  120. package/dataflow/internal/process/functions/call/common.js +1 -1
  121. package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
  122. package/dataflow/internal/process/functions/process-parameter.js +1 -1
  123. package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
  124. package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
  125. package/dataflow/processor.d.ts +5 -0
  126. package/documentation/doc-util/doc-cfg.js +4 -3
  127. package/documentation/doc-util/doc-code.d.ts +1 -1
  128. package/documentation/doc-util/doc-dfg.js +3 -2
  129. package/documentation/doc-util/doc-functions.d.ts +24 -0
  130. package/documentation/doc-util/doc-functions.js +65 -0
  131. package/documentation/doc-util/doc-normalized-ast.js +3 -2
  132. package/documentation/doc-util/doc-print.d.ts +5 -0
  133. package/documentation/doc-util/doc-print.js +36 -0
  134. package/documentation/doc-util/doc-query.d.ts +6 -3
  135. package/documentation/doc-util/doc-query.js +6 -3
  136. package/documentation/doc-util/doc-repl.js +2 -1
  137. package/documentation/doc-util/doc-search.js +3 -2
  138. package/documentation/doc-util/doc-types.d.ts +28 -6
  139. package/documentation/doc-util/doc-types.js +89 -45
  140. package/documentation/print-cfg-wiki.js +10 -11
  141. package/documentation/print-core-wiki.js +5 -5
  142. package/documentation/print-dataflow-graph-wiki.js +14 -13
  143. package/documentation/print-engines-wiki.js +2 -3
  144. package/documentation/print-faq-wiki.js +8 -2
  145. package/documentation/print-interface-wiki.js +1 -2
  146. package/documentation/print-linter-issue.d.ts +1 -0
  147. package/documentation/print-linter-issue.js +71 -0
  148. package/documentation/print-linter-wiki.js +219 -34
  149. package/documentation/print-linting-and-testing-wiki.js +2 -4
  150. package/documentation/print-normalized-ast-wiki.js +3 -3
  151. package/documentation/print-query-wiki.js +81 -2
  152. package/documentation/print-readme.js +24 -1
  153. package/documentation/print-search-wiki.js +1 -2
  154. package/linter/linter-executor.d.ts +3 -1
  155. package/linter/linter-executor.js +3 -2
  156. package/linter/linter-format.d.ts +67 -7
  157. package/linter/linter-format.js +12 -1
  158. package/linter/linter-rules.d.ts +155 -16
  159. package/linter/linter-rules.js +12 -4
  160. package/linter/linter-tags.d.ts +80 -0
  161. package/linter/linter-tags.js +85 -0
  162. package/linter/rules/absolute-path.d.ts +71 -0
  163. package/linter/rules/absolute-path.js +177 -0
  164. package/linter/rules/deprecated-functions.d.ts +43 -0
  165. package/linter/rules/deprecated-functions.js +58 -0
  166. package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
  167. package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
  168. package/linter/rules/naming-convention.d.ts +71 -0
  169. package/linter/rules/naming-convention.js +164 -0
  170. package/linter/rules/seeded-randomness.d.ts +65 -0
  171. package/linter/rules/seeded-randomness.js +122 -0
  172. package/linter/rules/unused-definition.d.ts +41 -0
  173. package/linter/rules/unused-definition.js +105 -0
  174. package/package.json +4 -1
  175. package/queries/base-query-format.d.ts +2 -0
  176. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
  177. package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
  178. package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
  179. package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
  180. package/queries/catalog/config-query/config-query-executor.js +2 -3
  181. package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +3 -0
  182. package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
  183. package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
  184. package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
  185. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
  186. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
  187. package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -115
  188. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
  189. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
  190. package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
  191. package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
  192. package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
  193. package/queries/catalog/linter-query/linter-query-executor.js +2 -2
  194. package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
  195. package/queries/catalog/linter-query/linter-query-format.js +17 -12
  196. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
  197. package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
  198. package/queries/catalog/project-query/project-query-format.d.ts +1 -1
  199. package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
  200. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +4 -4
  201. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -2
  202. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
  203. package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
  204. package/queries/catalog/search-query/search-query-executor.js +2 -2
  205. package/queries/catalog/search-query/search-query-format.d.ts +1 -1
  206. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  207. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
  208. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
  209. package/queries/query.d.ts +75 -15
  210. package/queries/query.js +2 -0
  211. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
  212. package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
  213. package/r-bridge/lang-4.x/convert-values.js +2 -1
  214. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
  215. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
  216. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
  217. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +18 -9
  218. package/r-bridge/shell.d.ts +3 -2
  219. package/r-bridge/shell.js +4 -5
  220. package/search/flowr-search-builder.d.ts +6 -2
  221. package/search/flowr-search-builder.js +7 -0
  222. package/search/flowr-search-filters.d.ts +32 -8
  223. package/search/flowr-search-filters.js +42 -15
  224. package/search/flowr-search.d.ts +4 -0
  225. package/search/search-executor/search-enrichers.d.ts +7 -3
  226. package/search/search-executor/search-enrichers.js +32 -20
  227. package/search/search-executor/search-generators.js +1 -1
  228. package/search/search-executor/search-transformer.d.ts +2 -0
  229. package/search/search-executor/search-transformer.js +10 -1
  230. package/slicing/criterion/parse.d.ts +8 -0
  231. package/slicing/criterion/parse.js +20 -0
  232. package/slicing/static/static-slicer.d.ts +1 -1
  233. package/slicing/static/static-slicer.js +2 -3
  234. package/statistics/statistics.d.ts +3 -1
  235. package/statistics/statistics.js +5 -4
  236. package/util/containers.d.ts +12 -9
  237. package/util/containers.js +12 -9
  238. package/util/objects.d.ts +5 -4
  239. package/util/range.d.ts +5 -1
  240. package/util/range.js +11 -3
  241. package/util/text/strings.d.ts +6 -0
  242. package/util/text/strings.js +35 -0
  243. package/util/version.js +1 -1
  244. package/linter/rules/1-deprecated-functions.d.ts +0 -34
  245. package/linter/rules/1-deprecated-functions.js +0 -54
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ABSOLUTE_PATH = void 0;
7
+ const linter_format_1 = require("../linter-format");
8
+ const objects_1 = require("../../util/objects");
9
+ const flowr_search_builder_1 = require("../../search/flowr-search-builder");
10
+ const range_1 = require("../../util/range");
11
+ const dfg_1 = require("../../util/mermaid/dfg");
12
+ const linter_tags_1 = require("../linter-tags");
13
+ const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
14
+ const strings_1 = require("../../util/text/strings");
15
+ const r_string_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-string");
16
+ const assert_1 = require("../../util/assert");
17
+ const read_functions_1 = require("../../queries/catalog/dependencies-query/function-info/read-functions");
18
+ const write_functions_1 = require("../../queries/catalog/dependencies-query/function-info/write-functions");
19
+ const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
20
+ const source_functions_1 = require("../../queries/catalog/dependencies-query/function-info/source-functions");
21
+ const vertex_1 = require("../../dataflow/graph/vertex");
22
+ const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format");
23
+ const resolve_argument_1 = require("../../dataflow/eval/resolve/resolve-argument");
24
+ const path_1 = __importDefault(require("path"));
25
+ function inferWd(file, wd) {
26
+ if (wd === '@script') {
27
+ // we can use the script path as the working directory
28
+ return file;
29
+ }
30
+ else if (wd === '@home') {
31
+ // we can use the home directory as the working directory
32
+ return process.env.HOME || process.env.USERPROFILE || '';
33
+ }
34
+ else {
35
+ return wd;
36
+ }
37
+ }
38
+ // this can be improved by respecting raw strings and supporting more scenarios
39
+ function buildQuickFix(str, filePath, wd) {
40
+ if (!wd || !(0, r_string_1.isRString)(str)) {
41
+ return undefined;
42
+ }
43
+ return [{
44
+ type: 'replace',
45
+ range: str.location,
46
+ description: `Replace with a relative path to \`${filePath}\``,
47
+ replacement: str.content.quotes + '.' + path_1.default.sep + path_1.default.relative(wd, filePath) + str.content.quotes
48
+ }];
49
+ }
50
+ /** return all strings constructable by these functions */
51
+ const PathFunctions = {
52
+ 'file.path': (df, vtx, config) => {
53
+ const fsep = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, df, vtx, undefined, 'fsep', true);
54
+ // in the future we can access `.Platform$file.sep` here
55
+ const sepValues = new Array(...fsep?.values()?.flatMap(s => [...s].filter(assert_1.isNotUndefined)) ?? [path_1.default.sep]);
56
+ if (sepValues.some(s => s === dependencies_query_format_1.Unknown || (0, assert_1.isUndefined)(s))) {
57
+ // if we have no fsep, we cannot construct a path
58
+ return undefined;
59
+ }
60
+ const args = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, df, vtx, 'unnamed', undefined, true);
61
+ const argValues = args ? Array.from(args.values()).flatMap(v => [...v]) : [];
62
+ if (!argValues || argValues.length === 0 || argValues.some(v => v === dependencies_query_format_1.Unknown || (0, assert_1.isUndefined)(v))) {
63
+ // if we have no arguments, we cannot construct a path
64
+ return undefined;
65
+ }
66
+ const results = [];
67
+ for (const val of sepValues) {
68
+ results.push(argValues.join(val));
69
+ }
70
+ return results;
71
+ }
72
+ };
73
+ exports.ABSOLUTE_PATH = {
74
+ /* this can be done better once we have types */
75
+ createSearch: (config) => {
76
+ let q;
77
+ if (config.include.allStrings) {
78
+ q = flowr_search_builder_1.Q.all().filter(type_1.RType.String);
79
+ }
80
+ else {
81
+ q = flowr_search_builder_1.Q.fromQuery({
82
+ type: 'dependencies',
83
+ // we use the dependencies query to give us all functions that take a file path as input
84
+ ignoreDefaultFunctions: true,
85
+ readFunctions: read_functions_1.ReadFunctions.concat(write_functions_1.WriteFunctions, source_functions_1.SourceFunctions, config.additionalPathFunctions),
86
+ });
87
+ }
88
+ if (config.include.constructed) {
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 */
91
+ }
92
+ return q.unique();
93
+ },
94
+ processSearchResult: (elements, config, data) => {
95
+ const metadata = {
96
+ totalConsidered: 0,
97
+ totalUnknown: 0
98
+ };
99
+ const regex = config.absolutePathRegex ? new RegExp(config.absolutePathRegex) : undefined;
100
+ return {
101
+ results: elements.getElements().flatMap(element => {
102
+ metadata.totalConsidered++;
103
+ const node = element.node;
104
+ const wd = inferWd(node.info.file, config.useAsWd);
105
+ if ((0, r_string_1.isRString)(node)) {
106
+ if (node.content.str.length >= 3 && (0, strings_1.isAbsolutePath)(node.content.str, regex)) {
107
+ return [{
108
+ certainty: linter_format_1.LintingCertainty.Maybe,
109
+ filePath: node.content.str,
110
+ range: node.info.fullRange ?? node.location,
111
+ quickFix: buildQuickFix(node, node.content.str, wd)
112
+ }];
113
+ }
114
+ else {
115
+ return [];
116
+ }
117
+ }
118
+ else if (element.queryResult) {
119
+ const result = element.queryResult;
120
+ const mappedStrings = result.readData.filter(r => r.source !== dependencies_query_format_1.Unknown && (0, strings_1.isAbsolutePath)(r.source, regex)).map(r => {
121
+ const elem = data.normalize.idMap.get(r.nodeId);
122
+ return {
123
+ certainty: linter_format_1.LintingCertainty.Definitely,
124
+ filePath: r.source,
125
+ range: elem?.info.fullRange ?? elem?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
126
+ quickFix: buildQuickFix(elem, r.source, wd)
127
+ };
128
+ });
129
+ if (mappedStrings.length > 0) {
130
+ return mappedStrings;
131
+ }
132
+ else if (result.readData.every(r => r.source !== dependencies_query_format_1.Unknown)) {
133
+ // if we have no absolute paths, but all paths are known, we can return an empty array
134
+ return [];
135
+ }
136
+ }
137
+ else {
138
+ const dfNode = data.dataflow.graph.getVertex(node.info.id);
139
+ if ((0, vertex_1.isFunctionCallVertex)(dfNode)) {
140
+ const handler = PathFunctions[dfNode.name ?? ''];
141
+ const strings = handler ? handler(data.dataflow.graph, dfNode, data.config) : [];
142
+ if (strings) {
143
+ return strings.filter(s => (0, strings_1.isAbsolutePath)(s, regex)).map(str => ({
144
+ certainty: linter_format_1.LintingCertainty.Maybe,
145
+ filePath: str,
146
+ range: node.info.fullRange ?? node.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1)
147
+ }));
148
+ }
149
+ }
150
+ // check whether the df node is a function call that returns a file path
151
+ }
152
+ metadata.totalUnknown++;
153
+ return undefined;
154
+ }).filter(assert_1.isNotUndefined).map(r => (0, objects_1.compactRecord)(r)),
155
+ '.meta': metadata
156
+ };
157
+ },
158
+ prettyPrint: {
159
+ [linter_format_1.LintingPrettyPrintContext.Query]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)}`,
160
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)} is not absolute`
161
+ },
162
+ info: {
163
+ name: 'Absolute Paths',
164
+ description: 'Checks whether file paths are absolute.',
165
+ tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.QuickFix],
166
+ defaultConfig: {
167
+ include: {
168
+ constructed: true,
169
+ allStrings: false
170
+ },
171
+ additionalPathFunctions: [],
172
+ absolutePathRegex: undefined,
173
+ useAsWd: '@script'
174
+ }
175
+ }
176
+ };
177
+ //# sourceMappingURL=absolute-path.js.map
@@ -0,0 +1,43 @@
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
+ import { LintingRuleTag } from '../linter-tags';
7
+ export interface DeprecatedFunctionsResult extends LintingResult {
8
+ function: string;
9
+ range: SourceRange;
10
+ }
11
+ export interface DeprecatedFunctionsConfig extends MergeableRecord {
12
+ /**
13
+ * The list of function names that should be marked as deprecated.
14
+ */
15
+ deprecatedFunctions: string[];
16
+ }
17
+ export interface DeprecatedFunctionsMetadata extends MergeableRecord {
18
+ totalDeprecatedCalls: number;
19
+ totalDeprecatedFunctionDefinitions: number;
20
+ }
21
+ export declare const DEPRECATED_FUNCTIONS: {
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
+ 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
+ results: {
25
+ certainty: LintingCertainty.Definitely;
26
+ function: Identifier;
27
+ range: SourceRange;
28
+ }[];
29
+ '.meta': DeprecatedFunctionsMetadata;
30
+ };
31
+ readonly prettyPrint: {
32
+ readonly query: (result: DeprecatedFunctionsResult) => string;
33
+ readonly full: (result: DeprecatedFunctionsResult) => string;
34
+ };
35
+ readonly info: {
36
+ readonly name: "Deprecated Functions";
37
+ readonly tags: readonly [LintingRuleTag.Deprecated, LintingRuleTag.Smell, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
38
+ readonly description: "Marks deprecated functions that should not be used anymore.";
39
+ readonly defaultConfig: {
40
+ 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"];
41
+ };
42
+ };
43
+ };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.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
+ const flowr_search_filters_1 = require("../../search/flowr-search-filters");
9
+ const linter_tags_1 = require("../linter-tags");
10
+ exports.DEPRECATED_FUNCTIONS = {
11
+ createSearch: (config) => flowr_search_builder_1.Q.all()
12
+ .with(search_enrichers_1.Enrichment.CallTargets, { onlyBuiltin: true })
13
+ .filter({
14
+ name: flowr_search_filters_1.FlowrFilter.MatchesEnrichment,
15
+ args: {
16
+ enrichment: search_enrichers_1.Enrichment.CallTargets,
17
+ test: (0, flowr_search_filters_1.testFunctionsIgnoringPackage)(config.deprecatedFunctions)
18
+ }
19
+ }),
20
+ processSearchResult: (elements) => {
21
+ const metadata = {
22
+ totalDeprecatedCalls: 0,
23
+ totalDeprecatedFunctionDefinitions: 0
24
+ };
25
+ return {
26
+ results: elements.getElements()
27
+ .flatMap(element => {
28
+ metadata.totalDeprecatedCalls++;
29
+ return (0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.CallTargets).targets.map(target => {
30
+ metadata.totalDeprecatedFunctionDefinitions++;
31
+ return {
32
+ range: element.node.info.fullRange,
33
+ target: target
34
+ };
35
+ });
36
+ })
37
+ .map(element => ({
38
+ certainty: linter_format_1.LintingCertainty.Definitely,
39
+ function: element.target,
40
+ range: element.range
41
+ })),
42
+ '.meta': metadata
43
+ };
44
+ },
45
+ prettyPrint: {
46
+ [linter_format_1.LintingPrettyPrintContext.Query]: result => `Function \`${result.function}\` at ${(0, dfg_1.formatRange)(result.range)}`,
47
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Function \`${result.function}\` called at ${(0, dfg_1.formatRange)(result.range)} is deprecated`
48
+ },
49
+ info: {
50
+ name: 'Deprecated Functions',
51
+ tags: [linter_tags_1.LintingRuleTag.Deprecated, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
52
+ description: 'Marks deprecated functions that should not be used anymore.',
53
+ defaultConfig: {
54
+ 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',]
55
+ }
56
+ }
57
+ };
58
+ //# sourceMappingURL=deprecated-functions.js.map
@@ -4,6 +4,7 @@ import type { SourceRange } from '../../util/range';
4
4
  import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
5
  import type { FlowrSearchElementFromQuery } from '../../search/flowr-search';
6
6
  import type { FunctionInfo } from '../../queries/catalog/dependencies-query/function-info/function-info';
7
+ import { LintingRuleTag } from '../linter-tags';
7
8
  export interface FilePathValidityResult extends LintingResult {
8
9
  filePath: string;
9
10
  range: SourceRange;
@@ -30,19 +31,28 @@ export interface FilePathValidityMetadata extends MergeableRecord {
30
31
  totalWritesBeforeAlways: number;
31
32
  totalValid: number;
32
33
  }
33
- export declare const R2_FILE_PATH_VALIDITY: {
34
+ export declare const FILE_PATH_VALIDITY: {
34
35
  readonly createSearch: (config: FilePathValidityConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], ParentInformation, import("../../search/flowr-search").FlowrSearchElements<ParentInformation, FlowrSearchElementFromQuery<ParentInformation>[]>>;
35
36
  readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<ParentInformation, FlowrSearchElementFromQuery<ParentInformation>[]>, config: FilePathValidityConfig, data: {
36
37
  normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
37
38
  dataflow: import("../../dataflow/info").DataflowInformation;
39
+ config: import("../../config").FlowrConfigOptions;
38
40
  }) => {
39
41
  results: FilePathValidityResult[];
40
42
  ".meta": FilePathValidityMetadata;
41
43
  };
42
- readonly prettyPrint: (result: FilePathValidityResult) => string;
43
- readonly defaultConfig: {
44
- readonly additionalReadFunctions: [];
45
- readonly additionalWriteFunctions: [];
46
- readonly includeUnknown: false;
44
+ readonly info: {
45
+ readonly name: "File Path Validity";
46
+ readonly description: "Checks whether file paths used in read and write operations are valid and point to existing files.";
47
+ readonly tags: readonly [LintingRuleTag.Robustness, LintingRuleTag.Reproducibility, LintingRuleTag.Bug];
48
+ readonly defaultConfig: {
49
+ readonly additionalReadFunctions: readonly [];
50
+ readonly additionalWriteFunctions: readonly [];
51
+ readonly includeUnknown: false;
52
+ };
53
+ };
54
+ readonly prettyPrint: {
55
+ readonly query: (result: FilePathValidityResult) => string;
56
+ readonly full: (result: FilePathValidityResult) => string;
47
57
  };
48
58
  };
@@ -1,19 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.R2_FILE_PATH_VALIDITY = void 0;
3
+ exports.FILE_PATH_VALIDITY = void 0;
4
4
  const linter_format_1 = require("../linter-format");
5
5
  const flowr_search_builder_1 = require("../../search/flowr-search-builder");
6
6
  const dfg_1 = require("../../util/mermaid/dfg");
7
7
  const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format");
8
8
  const built_in_source_1 = require("../../dataflow/internal/process/functions/call/built-in/built-in-source");
9
9
  const logic_1 = require("../../util/logic");
10
- const config_1 = require("../../config");
11
10
  const retriever_1 = require("../../r-bridge/retriever");
12
11
  const read_functions_1 = require("../../queries/catalog/dependencies-query/function-info/read-functions");
13
12
  const write_functions_1 = require("../../queries/catalog/dependencies-query/function-info/write-functions");
14
13
  const extract_cfg_1 = require("../../control-flow/extract-cfg");
15
14
  const happens_before_1 = require("../../control-flow/happens-before");
16
- exports.R2_FILE_PATH_VALIDITY = {
15
+ const linter_tags_1 = require("../linter-tags");
16
+ exports.FILE_PATH_VALIDITY = {
17
17
  createSearch: (config) => flowr_search_builder_1.Q.fromQuery({
18
18
  type: 'dependencies',
19
19
  // we only want to check read and write functions, so we explicitly clear all others
@@ -53,14 +53,14 @@ exports.R2_FILE_PATH_VALIDITY = {
53
53
  }
54
54
  }
55
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));
56
+ const writesToFile = results.writtenData.filter(r => samePath(r.destination, matchingRead.source, data.config.solver.resolveSource?.ignoreCapitalization));
57
57
  const writesBefore = writesToFile.map(w => (0, happens_before_1.happensBefore)(cfg, w.nodeId, element.node.info.id));
58
58
  if (writesBefore.some(w => w === logic_1.Ternary.Always)) {
59
59
  metadata.totalWritesBeforeAlways++;
60
60
  return [];
61
61
  }
62
62
  // check if the file exists!
63
- const paths = (0, built_in_source_1.findSource)(matchingRead.source, {
63
+ const paths = (0, built_in_source_1.findSource)(data.config.solver.resolveSource, matchingRead.source, {
64
64
  referenceChain: element.node.info.file ? [(0, retriever_1.requestFromInput)(`file://${element.node.info.file}`)] : []
65
65
  });
66
66
  if (paths && paths.length) {
@@ -76,18 +76,26 @@ exports.R2_FILE_PATH_VALIDITY = {
76
76
  '.meta': metadata
77
77
  };
78
78
  },
79
- prettyPrint: result => `Path ${result.filePath} at ${(0, dfg_1.formatRange)(result.range)}`,
80
- defaultConfig: {
81
- additionalReadFunctions: [],
82
- additionalWriteFunctions: [],
83
- includeUnknown: false
79
+ info: {
80
+ name: 'File Path Validity',
81
+ description: 'Checks whether file paths used in read and write operations are valid and point to existing files.',
82
+ tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility, linter_tags_1.LintingRuleTag.Bug],
83
+ defaultConfig: {
84
+ additionalReadFunctions: [],
85
+ additionalWriteFunctions: [],
86
+ includeUnknown: false
87
+ }
88
+ },
89
+ prettyPrint: {
90
+ [linter_format_1.LintingPrettyPrintContext.Query]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)}`,
91
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)} does not point to a valid file`
84
92
  }
85
93
  };
86
- function samePath(a, b) {
87
- if ((0, config_1.getConfig)().solver.resolveSource?.ignoreCapitalization === true) {
94
+ function samePath(a, b, ignoreCapitalization) {
95
+ if (ignoreCapitalization === true) {
88
96
  a = a.toLowerCase();
89
97
  b = b.toLowerCase();
90
98
  }
91
99
  return a === b;
92
100
  }
93
- //# sourceMappingURL=2-file-path-validity.js.map
101
+ //# sourceMappingURL=file-path-validity.js.map
@@ -0,0 +1,71 @@
1
+ import type { DataflowGraph } from '../../dataflow/graph/graph';
2
+ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
3
+ import type { MergeableRecord } from '../../util/objects';
4
+ import type { SourceRange } from '../../util/range';
5
+ import type { LintQuickFixReplacement, LintingResult } from '../linter-format';
6
+ import { LintingCertainty } from '../linter-format';
7
+ import { LintingRuleTag } from '../linter-tags';
8
+ export declare enum CasingConvention {
9
+ CamelCase = "camelCase",
10
+ PascalCase = "PascalCase",
11
+ SnakeCase = "snake_case",
12
+ ConstantCase = "CONSTANT_CASE",
13
+ CamelSnakeCase = "camel_Snake_Case",
14
+ PascalSnakeCase = "Pascal_Snake_Case",
15
+ Unknown = "unknown"
16
+ }
17
+ export interface NamingConventionResult extends LintingResult {
18
+ name: string;
19
+ detectedCasing: CasingConvention;
20
+ range: SourceRange;
21
+ }
22
+ /**
23
+ * It is planned to have a config like ESLint
24
+ */
25
+ export interface NamingConventionConfig extends MergeableRecord {
26
+ caseing: CasingConvention | 'auto';
27
+ }
28
+ export interface NamingConventionMetadata extends MergeableRecord {
29
+ /** number of symbols matching the casing convetion */
30
+ numMatches: number;
31
+ /** number of symbols breaking the casing convetion */
32
+ numBreak: number;
33
+ }
34
+ export declare function detectCasing(identifier: string): CasingConvention;
35
+ export declare function getMostUsedCasing(symbols: {
36
+ detectedCasing: CasingConvention;
37
+ }[]): CasingConvention;
38
+ export declare function fixCasing(identifier: string, convention: CasingConvention): string;
39
+ export declare function createNamingConventionQuickFixes(graph: DataflowGraph, nodeId: NodeId, replacement: string, conv: CasingConvention): LintQuickFixReplacement[] | undefined;
40
+ export declare const NAMING_CONVENTION: {
41
+ readonly createSearch: (_config: NamingConventionConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["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>[]>>;
42
+ 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: NamingConventionConfig, data: {
43
+ normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
44
+ dataflow: import("../../dataflow/info").DataflowInformation;
45
+ config: import("../../config").FlowrConfigOptions;
46
+ }) => {
47
+ results: {
48
+ quickFix: LintQuickFixReplacement[] | undefined;
49
+ certainty: LintingCertainty;
50
+ detectedCasing: CasingConvention;
51
+ name: string;
52
+ range: SourceRange;
53
+ }[];
54
+ '.meta': {
55
+ numMatches: number;
56
+ numBreak: number;
57
+ };
58
+ };
59
+ readonly prettyPrint: {
60
+ readonly query: (result: NamingConventionResult) => string;
61
+ readonly full: (result: NamingConventionResult) => string;
62
+ };
63
+ readonly info: {
64
+ readonly name: "Naming Convention";
65
+ readonly description: "Checks wether the symbols conform to a certain naming convention";
66
+ readonly tags: readonly [LintingRuleTag.Style, LintingRuleTag.QuickFix];
67
+ readonly defaultConfig: {
68
+ readonly caseing: CasingConvention.PascalCase;
69
+ };
70
+ };
71
+ };
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NAMING_CONVENTION = exports.CasingConvention = void 0;
4
+ exports.detectCasing = detectCasing;
5
+ exports.getMostUsedCasing = getMostUsedCasing;
6
+ exports.fixCasing = fixCasing;
7
+ exports.createNamingConventionQuickFixes = createNamingConventionQuickFixes;
8
+ const vertex_1 = require("../../dataflow/graph/vertex");
9
+ const dfg_get_symbol_refs_1 = require("../../dataflow/origin/dfg-get-symbol-refs");
10
+ const flowr_search_builder_1 = require("../../search/flowr-search-builder");
11
+ const assert_1 = require("../../util/assert");
12
+ const dfg_1 = require("../../util/mermaid/dfg");
13
+ const linter_format_1 = require("../linter-format");
14
+ const linter_tags_1 = require("../linter-tags");
15
+ var CasingConvention;
16
+ (function (CasingConvention) {
17
+ CasingConvention["CamelCase"] = "camelCase";
18
+ CasingConvention["PascalCase"] = "PascalCase";
19
+ CasingConvention["SnakeCase"] = "snake_case";
20
+ CasingConvention["ConstantCase"] = "CONSTANT_CASE";
21
+ CasingConvention["CamelSnakeCase"] = "camel_Snake_Case";
22
+ CasingConvention["PascalSnakeCase"] = "Pascal_Snake_Case";
23
+ CasingConvention["Unknown"] = "unknown";
24
+ })(CasingConvention || (exports.CasingConvention = CasingConvention = {}));
25
+ function detectCasing(identifier) {
26
+ if (identifier.trim() === '') {
27
+ return CasingConvention.Unknown;
28
+ }
29
+ const upper = identifier.toUpperCase();
30
+ const lower = identifier.toLowerCase();
31
+ const isAllUpper = identifier === upper;
32
+ const isAllLower = identifier === lower;
33
+ if (identifier.includes('_')) {
34
+ if (isAllUpper) { // CONSTANT_CASE
35
+ return CasingConvention.ConstantCase;
36
+ }
37
+ else if (isAllLower) { // snake_case
38
+ return CasingConvention.SnakeCase;
39
+ }
40
+ // Returns true if the letter after an _ is uppercase
41
+ function expectUpperAfterScore(identifier) {
42
+ for (let i = 0; i < identifier.length - 1; i++) {
43
+ if (identifier[i] === '_') {
44
+ if (identifier[i + 1] !== upper[i + 1]) {
45
+ return false;
46
+ }
47
+ }
48
+ }
49
+ return true;
50
+ }
51
+ if (identifier[0] === lower[0] && expectUpperAfterScore(identifier)) { // camel_Snake_Case
52
+ return CasingConvention.CamelSnakeCase;
53
+ }
54
+ else if (identifier[0] === upper[0] && expectUpperAfterScore(identifier)) { // Pascal_Snake_Case
55
+ return CasingConvention.PascalSnakeCase;
56
+ }
57
+ }
58
+ else {
59
+ if (identifier[0] === lower[0]) { // camelCase
60
+ return CasingConvention.CamelCase;
61
+ }
62
+ else if (identifier[0] === upper[0]) { // PascalCase
63
+ return CasingConvention.PascalCase;
64
+ }
65
+ }
66
+ return CasingConvention.Unknown;
67
+ }
68
+ function getMostUsedCasing(symbols) {
69
+ const map = new Map();
70
+ for (const symbol of symbols) {
71
+ const o = map.get(symbol.detectedCasing) ?? 0;
72
+ map.set(symbol.detectedCasing, o + 1);
73
+ }
74
+ return [...map].reduce((p, c) => p[1] > c[1] ? p : c)[0];
75
+ }
76
+ function fixCasing(identifier, convention) {
77
+ const tokens = identifier.split(/(?=[A-Z])|_/).map(s => s.toLowerCase());
78
+ const firstUp = (s) => `${s[0].toUpperCase()}${s.substring(1)}`;
79
+ switch (convention) {
80
+ case CasingConvention.CamelCase: // camelCase
81
+ return `${tokens[0]}${tokens.slice(1).map(firstUp).join('')}`;
82
+ case CasingConvention.PascalCase: // PascalCase
83
+ return tokens.map(firstUp).join('');
84
+ case CasingConvention.SnakeCase: // snake_case
85
+ return tokens.join('_');
86
+ case CasingConvention.ConstantCase: // CONSTANT_CASE
87
+ return tokens.map(s => s.toUpperCase()).join('_');
88
+ case CasingConvention.CamelSnakeCase: // camel_Snake_Case
89
+ return `${tokens[0]}_${tokens.slice(1).map(firstUp).join('_')}`;
90
+ case CasingConvention.PascalSnakeCase: // Pascal_Snake_Case
91
+ return tokens.map(firstUp).join('_');
92
+ case CasingConvention.Unknown:
93
+ return identifier;
94
+ default:
95
+ (0, assert_1.assertUnreachable)(convention);
96
+ }
97
+ }
98
+ function createNamingConventionQuickFixes(graph, nodeId, replacement, conv) {
99
+ const refs = (0, dfg_get_symbol_refs_1.getAllRefsToSymbol)(graph, nodeId);
100
+ const idMap = graph.idMap;
101
+ if (refs === undefined || idMap === undefined) {
102
+ return undefined;
103
+ }
104
+ const result = [];
105
+ for (const ref of refs) {
106
+ const node = idMap.get(ref);
107
+ if (node === undefined) {
108
+ continue;
109
+ }
110
+ const range = node.info.fullRange;
111
+ if (range) {
112
+ // In case of a function call we only need to include the name, not the '()'
113
+ range[3] = range[1] + node.lexeme.length - 1;
114
+ result.push({
115
+ type: 'replace',
116
+ replacement: replacement,
117
+ description: `Rename to match naming convention ${conv}`,
118
+ range: range
119
+ });
120
+ }
121
+ }
122
+ return result.length === 0 ?
123
+ undefined : // We sort so that when applied in order the fixes will start from the end of the line to avoid conflicts
124
+ result.sort((a, b) => a.range[0] == b.range[0] ? b.range[1] - a.range[1] : b.range[0] - a.range[0]);
125
+ }
126
+ exports.NAMING_CONVENTION = {
127
+ createSearch: (_config) => flowr_search_builder_1.Q.all().filter(vertex_1.VertexType.VariableDefinition),
128
+ processSearchResult: (elements, config, data) => {
129
+ const symbols = elements.getElements()
130
+ .map(m => ({
131
+ certainty: linter_format_1.LintingCertainty.Definitely,
132
+ detectedCasing: detectCasing(m.node.lexeme),
133
+ name: m.node.lexeme,
134
+ range: m.node.info.fullRange,
135
+ id: m.node.info.id
136
+ }));
137
+ const casing = config.caseing === 'auto' ? getMostUsedCasing(symbols) : config.caseing;
138
+ const results = symbols.filter(m => m.detectedCasing !== casing)
139
+ .map(({ id, ...m }) => ({
140
+ ...m,
141
+ quickFix: createNamingConventionQuickFixes(data.dataflow.graph, id, fixCasing(m.name, casing), casing)
142
+ }));
143
+ return {
144
+ results: results,
145
+ '.meta': {
146
+ numMatches: symbols.length - results.length,
147
+ numBreak: results.length
148
+ }
149
+ };
150
+ },
151
+ prettyPrint: {
152
+ [linter_format_1.LintingPrettyPrintContext.Query]: result => `Identifier '${result.name}' at ${(0, dfg_1.formatRange)(result.range)} (${result.detectedCasing})`,
153
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Identifier '${result.name}' at ${(0, dfg_1.formatRange)(result.range)} follows wrong convention: ${result.detectedCasing}`
154
+ },
155
+ info: {
156
+ name: 'Naming Convention',
157
+ description: 'Checks wether the symbols conform to a certain naming convention',
158
+ tags: [linter_tags_1.LintingRuleTag.Style, linter_tags_1.LintingRuleTag.QuickFix],
159
+ defaultConfig: {
160
+ caseing: CasingConvention.PascalCase
161
+ }
162
+ }
163
+ };
164
+ //# sourceMappingURL=naming-convention.js.map