@eagleoutice/flowr 2.2.16 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +35 -19
  2. package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
  3. package/abstract-interpretation/data-frame/absint-info.js +31 -0
  4. package/abstract-interpretation/data-frame/absint-visitor.d.ts +59 -0
  5. package/abstract-interpretation/data-frame/absint-visitor.js +173 -0
  6. package/abstract-interpretation/data-frame/domain.d.ts +107 -0
  7. package/abstract-interpretation/data-frame/domain.js +315 -0
  8. package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
  9. package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
  10. package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
  11. package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
  12. package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
  13. package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
  14. package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
  15. package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
  16. package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
  17. package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
  18. package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
  19. package/abstract-interpretation/data-frame/resolve-args.js +118 -0
  20. package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
  21. package/abstract-interpretation/data-frame/semantics.js +366 -0
  22. package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
  23. package/abstract-interpretation/data-frame/shape-inference.js +117 -0
  24. package/benchmark/slicer.d.ts +15 -1
  25. package/benchmark/slicer.js +135 -0
  26. package/benchmark/stats/print.js +123 -45
  27. package/benchmark/stats/size-of.d.ts +7 -0
  28. package/benchmark/stats/size-of.js +1 -0
  29. package/benchmark/stats/stats.d.ts +30 -1
  30. package/benchmark/stats/stats.js +4 -2
  31. package/benchmark/summarizer/data.d.ts +33 -2
  32. package/benchmark/summarizer/first-phase/input.js +5 -1
  33. package/benchmark/summarizer/first-phase/process.js +47 -1
  34. package/benchmark/summarizer/second-phase/process.js +101 -3
  35. package/cli/benchmark-app.d.ts +1 -0
  36. package/cli/benchmark-app.js +1 -0
  37. package/cli/benchmark-helper-app.d.ts +1 -0
  38. package/cli/benchmark-helper-app.js +8 -2
  39. package/cli/common/options.js +2 -0
  40. package/config.d.ts +31 -0
  41. package/config.js +21 -1
  42. package/control-flow/control-flow-graph.d.ts +1 -0
  43. package/control-flow/control-flow-graph.js +4 -0
  44. package/control-flow/dfg-cfg-guided-visitor.js +1 -1
  45. package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
  46. package/control-flow/semantic-cfg-guided-visitor.js +1 -1
  47. package/dataflow/environments/built-in.d.ts +5 -3
  48. package/dataflow/environments/built-in.js +3 -1
  49. package/dataflow/eval/resolve/alias-tracking.js +2 -2
  50. package/dataflow/eval/resolve/resolve.d.ts +53 -9
  51. package/dataflow/eval/resolve/resolve.js +132 -38
  52. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
  53. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
  54. package/documentation/doc-util/doc-query.js +10 -0
  55. package/documentation/print-interface-wiki.js +11 -0
  56. package/documentation/print-linter-wiki.js +4 -0
  57. package/documentation/print-query-wiki.js +17 -0
  58. package/linter/linter-rules.d.ts +25 -2
  59. package/linter/linter-rules.js +3 -1
  60. package/linter/rules/absolute-path.d.ts +1 -1
  61. package/linter/rules/dataframe-access-validation.d.ts +53 -0
  62. package/linter/rules/dataframe-access-validation.js +116 -0
  63. package/linter/rules/naming-convention.d.ts +1 -1
  64. package/linter/rules/naming-convention.js +5 -1
  65. package/package.json +2 -2
  66. package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
  67. package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
  68. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
  69. package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
  70. package/queries/query.d.ts +61 -1
  71. package/queries/query.js +2 -0
  72. package/util/files.d.ts +8 -2
  73. package/util/files.js +22 -4
  74. package/util/r-value.d.ts +23 -0
  75. package/util/r-value.js +113 -0
  76. package/util/version.js +1 -1
  77. package/util/cfg/cfg.d.ts +0 -0
  78. package/util/cfg/cfg.js +0 -2
@@ -2,17 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveNode = resolveNode;
4
4
  exports.resolveAsVector = resolveAsVector;
5
+ exports.resolveAsSeq = resolveAsSeq;
6
+ exports.resolveAsPlus = resolveAsPlus;
7
+ exports.resolveAsMinus = resolveAsMinus;
5
8
  const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
6
9
  const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
7
- const assert_1 = require("../../../util/assert");
10
+ const r_value_1 = require("../../../util/r-value");
8
11
  const built_in_1 = require("../../environments/built-in");
9
12
  const dfg_get_origin_1 = require("../../origin/dfg-get-origin");
10
13
  const interval_constants_1 = require("../values/intervals/interval-constants");
11
14
  const logical_constants_1 = require("../values/logical/logical-constants");
12
- const r_value_1 = require("../values/r-value");
15
+ const r_value_2 = require("../values/r-value");
13
16
  const string_constants_1 = require("../values/string/string-constants");
14
17
  const vector_constants_1 = require("../values/vectors/vector-constants");
15
18
  const alias_tracking_1 = require("./alias-tracking");
19
+ const scalar_consatnts_1 = require("../values/scalar/scalar-consatnts");
16
20
  /**
17
21
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
18
22
  * you want to resolve the value of an identifier / node
@@ -37,59 +41,149 @@ function resolveNode(resolve, a, env, graph, map) {
37
41
  else if (a.type === type_1.RType.Logical) {
38
42
  return a.content.valueOf() ? logical_constants_1.ValueLogicalTrue : logical_constants_1.ValueLogicalFalse;
39
43
  }
40
- else if (a.type === type_1.RType.FunctionCall && env && graph) {
44
+ else if ((a.type === type_1.RType.FunctionCall || a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) && graph) {
41
45
  const origin = (0, dfg_get_origin_1.getOriginInDfg)(graph, a.info.id)?.[0];
42
46
  if (origin === undefined || origin.type !== 3 /* OriginType.BuiltInFunctionOrigin */) {
43
- return r_value_1.Top;
47
+ return r_value_2.Top;
44
48
  }
45
- if (origin.proc in built_in_1.BuiltInEvalHandlerMapper) {
46
- const handler = built_in_1.BuiltInEvalHandlerMapper[origin.proc];
49
+ let builtInName;
50
+ if ((0, built_in_1.isBuiltIn)(origin.proc)) {
51
+ builtInName = origin.proc;
52
+ }
53
+ else if (a.type === type_1.RType.FunctionCall && a.named) {
54
+ builtInName = (0, built_in_1.builtInId)(a.functionName.content);
55
+ }
56
+ else if (a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) {
57
+ builtInName = (0, built_in_1.builtInId)(a.operator);
58
+ }
59
+ else {
60
+ return r_value_2.Top;
61
+ }
62
+ if (Object.prototype.hasOwnProperty.call(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
63
+ const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
47
64
  return handler(resolve, a, env, graph, map);
48
65
  }
49
66
  }
50
- return r_value_1.Top;
67
+ return r_value_2.Top;
51
68
  }
52
69
  /**
53
70
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
54
71
  * you want to resolve the value of an identifier / node
55
72
  *
56
- * This function converts an r-node to a Value Vector {@link vectorFrom}
57
- * It also recursively resolves any symbols, values, function calls (only c), in
58
- * order to construct the value of the vector to resolve by calling {@link resolveIdToValue}
59
- * or {@link resolveNode}
73
+ * This function resolves a vector function call `c` to a {@link ValueVector}
74
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
60
75
  *
61
- * @param a - Node of the vector to resolve
62
- * @param env - Environment to use
63
76
  * @param resolve - Variable resolve mode
77
+ * @param node - Node of the vector function to resolve
78
+ * @param env - Environment to use
64
79
  * @param graph - Dataflow graph
65
- * @param map - Idmap of Dataflow Graph
80
+ * @param map - Id map of the dataflow graph
66
81
  * @returns ValueVector or Top
67
82
  */
68
- function resolveAsVector(resolve, a, env, graph, map) {
69
- (0, assert_1.guard)(a.type === type_1.RType.FunctionCall);
70
- const values = [];
71
- for (const arg of a.arguments) {
72
- if (arg === r_function_call_1.EmptyArgument) {
73
- continue;
74
- }
75
- if (arg.value === undefined) {
76
- return r_value_1.Top;
77
- }
78
- if (arg.value.type === type_1.RType.Symbol) {
79
- const value = (0, alias_tracking_1.resolveIdToValue)(arg.info.id, { environment: env, idMap: map, graph: graph, full: true, resolve });
80
- if ((0, r_value_1.isTop)(value)) {
81
- return r_value_1.Top;
82
- }
83
- values.push(value);
84
- }
85
- else {
86
- const val = resolveNode(resolve, arg.value, env, graph, map);
87
- if ((0, r_value_1.isTop)(val)) {
88
- return r_value_1.Top;
89
- }
90
- values.push(val);
91
- }
83
+ function resolveAsVector(resolve, node, environment, graph, idMap) {
84
+ if (node.type !== type_1.RType.FunctionCall) {
85
+ return r_value_2.Top;
92
86
  }
87
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
88
+ const values = node.arguments.map(arg => arg !== r_function_call_1.EmptyArgument ? (0, alias_tracking_1.resolveIdToValue)(arg.value, resolveInfo) : r_value_2.Top);
93
89
  return (0, vector_constants_1.vectorFrom)((0, vector_constants_1.flattenVectorElements)(values));
94
90
  }
91
+ /**
92
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
93
+ * you want to resolve the value of an identifier / node
94
+ *
95
+ * This function resolves a binary sequence operator `:` to a {@link ValueVector} of {@link ValueNumber}s
96
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
97
+ *
98
+ * @param resolve - Variable resolve mode
99
+ * @param operator - Node of the sequence operator to resolve
100
+ * @param env - Environment to use
101
+ * @param graph - Dataflow graph
102
+ * @param map - Id map of the dataflow graph
103
+ * @returns ValueVector of ValueNumbers or Top
104
+ */
105
+ function resolveAsSeq(resolve, operator, environment, graph, idMap) {
106
+ if (operator.type !== type_1.RType.BinaryOp) {
107
+ return r_value_2.Top;
108
+ }
109
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
110
+ const leftArg = (0, alias_tracking_1.resolveIdToValue)(operator.lhs, resolveInfo);
111
+ const rightArg = (0, alias_tracking_1.resolveIdToValue)(operator.rhs, resolveInfo);
112
+ const leftValue = (0, r_value_1.unliftRValue)(leftArg);
113
+ const rightValue = (0, r_value_1.unliftRValue)(rightArg);
114
+ if ((0, r_value_1.isRNumberValue)(leftValue) && (0, r_value_1.isRNumberValue)(rightValue)) {
115
+ return (0, vector_constants_1.vectorFrom)(createNumberSequence(leftValue, rightValue).map(scalar_consatnts_1.liftScalar));
116
+ }
117
+ return r_value_2.Top;
118
+ }
119
+ /**
120
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
121
+ * you want to resolve the value of an identifier / node
122
+ *
123
+ * This function resolves a unary plus operator `+` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
124
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
125
+ *
126
+ * @param resolve - Variable resolve mode
127
+ * @param operator - Node of the plus operator to resolve
128
+ * @param env - Environment to use
129
+ * @param graph - Dataflow graph
130
+ * @param map - Id map of the dataflow graph
131
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
132
+ */
133
+ function resolveAsPlus(resolve, operator, environment, graph, idMap) {
134
+ if (operator.type !== type_1.RType.UnaryOp) {
135
+ return r_value_2.Top;
136
+ }
137
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
138
+ const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
139
+ const argValue = (0, r_value_1.unliftRValue)(arg);
140
+ if ((0, r_value_1.isRNumberValue)(argValue)) {
141
+ return (0, scalar_consatnts_1.liftScalar)(argValue);
142
+ }
143
+ else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
144
+ return (0, vector_constants_1.vectorFrom)(argValue.map(scalar_consatnts_1.liftScalar));
145
+ }
146
+ return r_value_2.Top;
147
+ }
148
+ /**
149
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
150
+ * you want to resolve the value of an identifier / node
151
+ *
152
+ * This function resolves a unary minus operator `-` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
153
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
154
+ *
155
+ * @param resolve - Variable resolve mode
156
+ * @param operator - Node of the minus operator to resolve
157
+ * @param env - Environment to use
158
+ * @param graph - Dataflow graph
159
+ * @param map - Id map of the dataflow graph
160
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
161
+ */
162
+ function resolveAsMinus(resolve, operator, environment, graph, idMap) {
163
+ if (operator.type !== type_1.RType.UnaryOp) {
164
+ return r_value_2.Top;
165
+ }
166
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
167
+ const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
168
+ const argValue = (0, r_value_1.unliftRValue)(arg);
169
+ if ((0, r_value_1.isRNumberValue)(argValue)) {
170
+ return (0, scalar_consatnts_1.liftScalar)({ ...argValue, num: -argValue.num });
171
+ }
172
+ else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
173
+ return (0, vector_constants_1.vectorFrom)(argValue.map(element => (0, scalar_consatnts_1.liftScalar)({ ...element, num: -element.num })));
174
+ }
175
+ return r_value_2.Top;
176
+ }
177
+ function createNumberSequence(start, end) {
178
+ const sequence = [];
179
+ const min = Math.min(start.num, end.num);
180
+ const max = Math.max(start.num, end.num);
181
+ for (let i = min; i <= max; i++) {
182
+ sequence.push({ ...start, num: i });
183
+ }
184
+ if (start > end) {
185
+ sequence.reverse();
186
+ }
187
+ return sequence;
188
+ }
95
189
  //# sourceMappingURL=resolve.js.map
@@ -8,6 +8,7 @@ import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/
8
8
  import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
9
9
  import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
10
10
  import type { NoInfo } from '../../../../../../r-bridge/lang-4.x/ast/model/model';
11
+ export declare function getSourceProvider(): RParseRequestProvider;
11
12
  export declare function setSourceProvider(provider: RParseRequestProvider): void;
12
13
  export declare function inferWdFromScript(option: InferWorkingDirectory, referenceChain: readonly RParseRequest[]): string[];
13
14
  /**
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getSourceProvider = getSourceProvider;
6
7
  exports.setSourceProvider = setSourceProvider;
7
8
  exports.inferWdFromScript = inferWdFromScript;
8
9
  exports.findSource = findSource;
@@ -30,6 +31,9 @@ const r_value_1 = require("../../../../../eval/values/r-value");
30
31
  const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
31
32
  const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
32
33
  let sourceProvider = (0, retriever_1.requestProviderFromFile)();
34
+ function getSourceProvider() {
35
+ return sourceProvider;
36
+ }
33
37
  function setSourceProvider(provider) {
34
38
  sourceProvider = provider;
35
39
  }
@@ -17,6 +17,7 @@ const doc_dfg_1 = require("./doc-dfg");
17
17
  const doc_code_1 = require("./doc-code");
18
18
  const time_1 = require("../../util/text/time");
19
19
  const query_print_1 = require("../../queries/query-print");
20
+ const doc_cli_option_1 = require("./doc-cli-option");
20
21
  const config_1 = require("../../config");
21
22
  async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery, addOutput = () => '' } = {}) {
22
23
  const now = performance.now();
@@ -34,6 +35,15 @@ The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing an
34
35
 
35
36
  ${(0, doc_code_1.codeBlock)('json', collapseQuery ? str.split('\n').join(' ').replace(/([{[])\s{2,}/g, '$1 ').replace(/\s{2,}([\]}])/g, ' $1') : str)}
36
37
 
38
+ ${(function () {
39
+ if (queries.length === 1 && Object.keys(queries[0]).length === 1) {
40
+ return `(This query can be shortened to \`@${queries[0].type}\` when used within the REPL command ${(0, doc_cli_option_1.getReplCommand)('query')}).`;
41
+ }
42
+ else {
43
+ return '';
44
+ }
45
+ })()}
46
+
37
47
  ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
38
48
 
39
49
  _Results (prettified and summarized):_
@@ -182,6 +182,7 @@ The following summarizes the configuration options:
182
182
  - \`solver\`: allows to configure how _flowR_ resolves variables and their values (currently we support: ${Object.values(config_1.VariableResolve).map(v => `\`${v}\``).join(', ')}), as well as if pointer analysis should be active.
183
183
  - \`engines\`: allows to configure the engines used by _flowR_ to interact with R code. See the [Engines wiki page](${doc_files_1.FlowrWikiBaseRef}/Engines) for more information.
184
184
  - \`defaultEngine\`: allows to specify the default engine to use for interacting with R code. If not set, an arbitrary engine from the specified list will be used.
185
+ - \`abstractInterpretation\`: allows to configure how _flowR_ performs abstract interpretation, although we currently only support data frame shape inference through abstract interpretation.
185
186
 
186
187
  So you can configure _flowR_ by adding a file like the following:
187
188
 
@@ -214,6 +215,16 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
214
215
  slicer: {
215
216
  threshold: 50
216
217
  }
218
+ },
219
+ abstractInterpretation: {
220
+ dataFrame: {
221
+ maxColNames: 20,
222
+ wideningThreshold: 4,
223
+ readLoadedData: {
224
+ readExternalFiles: true,
225
+ maxReadLines: 1_000_000
226
+ }
227
+ }
217
228
  }
218
229
  }, null, 2))}
219
230
 
@@ -107,6 +107,10 @@ print(x)
107
107
  rule(shell, 'naming-convention', 'NamingConventionConfig', 'NAMING_CONVENTION', 'lint-naming-convention', `
108
108
  myVar <- 42
109
109
  print(myVar)
110
+ `, tagTypes);
111
+ rule(shell, 'dataframe-access-validation', 'DataFrameAccessValidationConfig', 'DATA_FRAME_ACCESS_VALIDATION', 'lint-dataframe-access-validation', `
112
+ df <- data.frame(id = 1:5, name = 6:10)
113
+ df[6, "value"]
110
114
  `, tagTypes);
111
115
  function rule(shell, name, configType, ruleType, testfile, example, types) {
112
116
  const rule = linter_rules_1.LintingRules[name];
@@ -36,6 +36,7 @@ const doc_types_1 = require("./doc-util/doc-types");
36
36
  const path_1 = __importDefault(require("path"));
37
37
  const control_flow_query_executor_1 = require("../queries/catalog/control-flow-query/control-flow-query-executor");
38
38
  const doc_cfg_1 = require("./doc-util/doc-cfg");
39
+ const df_shape_query_executor_1 = require("../queries/catalog/df-shape-query/df-shape-query-executor");
39
40
  (0, doc_query_1.registerQueryDocumentation)('call-context', {
40
41
  name: 'Call-Context Query',
41
42
  type: 'active',
@@ -333,6 +334,22 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
333
334
  This query provides access to the current configuration of the flowR instance. See the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on what the configuration represents.`;
334
335
  }
335
336
  });
337
+ (0, doc_query_1.registerQueryDocumentation)('df-shape', {
338
+ name: 'Dataframe Shape Inference Query',
339
+ type: 'active',
340
+ shortDescription: 'Returns the shapes inferred for all dataframes in the code.',
341
+ functionName: df_shape_query_executor_1.executeDfShapeQuery.name,
342
+ functionFile: '../queries/catalog/df-shape-query/df-shape-query-format.ts',
343
+ buildExplanation: async (shell) => {
344
+ const exampleCode = 'x <- data.frame(a=1:3)\nfilter(x, FALSE)';
345
+ return `
346
+ This query infers all shapes of dataframes within the code. For example, you can use:
347
+ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
348
+ type: 'df-shape'
349
+ }], { showCode: true, collapseQuery: true })}
350
+ `;
351
+ }
352
+ });
336
353
  (0, doc_query_1.registerQueryDocumentation)('compound', {
337
354
  name: 'Compound Query',
338
355
  type: 'virtual',
@@ -89,7 +89,7 @@ export declare const LintingRules: {
89
89
  readonly 'absolute-file-paths': {
90
90
  readonly createSearch: (config: import("./rules/absolute-path").AbsoluteFilePathConfig) => import("../search/flowr-search-builder").FlowrSearchBuilder<"from-query", ["unique"], 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>[]>>;
91
91
  readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, {
92
- readonly query?: "config" | "origin" | "dataflow" | "search" | "call-context" | "control-flow" | "dataflow-lens" | "normalized-ast" | "id-map" | "dataflow-cluster" | "static-slice" | "lineage" | "dependencies" | "location-map" | "happens-before" | "resolve-value" | "project" | "linter" | undefined;
92
+ readonly query?: "config" | "origin" | "dataflow" | "search" | "call-context" | "control-flow" | "dataflow-lens" | "df-shape" | "normalized-ast" | "id-map" | "dataflow-cluster" | "static-slice" | "lineage" | "dependencies" | "location-map" | "happens-before" | "resolve-value" | "project" | "linter" | undefined;
93
93
  readonly queryResult?: import("../queries/base-query-format").BaseQueryResult | undefined;
94
94
  readonly node: import("../r-bridge/lang-4.x/ast/model/nodes/r-expression-list").RExpressionList<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-function-definition").RFunctionDefinition<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-function-call").RNamedFunctionCall<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-function-call").RUnnamedFunctionCall<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-parameter").RParameter<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-argument").RArgument<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-comment").RComment<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-line-directive").RLineDirective<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-for-loop").RForLoop<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop").RRepeatLoop<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-while-loop").RWhileLoop<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-if-then-else").RIfThenElse<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-access").RNamedAccess<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-access").RIndexAccess<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-unary-op").RUnaryOp<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-binary-op").RBinaryOp<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-symbol").RSymbol<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, string> | import("../r-bridge/lang-4.x/ast/model/nodes/r-number").RNumber<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-string").RString<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-logical").RLogical<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-break").RBreak<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-next").RNext<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation> | import("../r-bridge/lang-4.x/ast/model/nodes/r-pipe").RPipe<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>;
95
95
  }[]>, config: import("./rules/absolute-path").AbsoluteFilePathConfig, data: {
@@ -170,7 +170,30 @@ export declare const LintingRules: {
170
170
  readonly description: "Checks wether the symbols conform to a certain naming convention";
171
171
  readonly tags: readonly [import("./linter-tags").LintingRuleTag.Style, import("./linter-tags").LintingRuleTag.QuickFix];
172
172
  readonly defaultConfig: {
173
- readonly caseing: import("./rules/naming-convention").CasingConvention.PascalCase;
173
+ readonly caseing: "auto";
174
+ };
175
+ };
176
+ };
177
+ readonly 'dataframe-access-validation': {
178
+ readonly createSearch: () => 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>[]>>;
179
+ 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/dataframe-access-validation").DataFrameAccessValidationConfig, data: {
180
+ normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
181
+ dataflow: import("../dataflow/info").DataflowInformation;
182
+ config: import("../config").FlowrConfigOptions;
183
+ }) => {
184
+ results: import("./rules/dataframe-access-validation").DataFrameAccessValidationResult[];
185
+ '.meta': import("./rules/dataframe-access-validation").DataFrameAccessValidationMetadata;
186
+ };
187
+ readonly prettyPrint: {
188
+ readonly query: (result: import("./rules/dataframe-access-validation").DataFrameAccessValidationResult) => string;
189
+ readonly full: (result: import("./rules/dataframe-access-validation").DataFrameAccessValidationResult) => string;
190
+ };
191
+ readonly info: {
192
+ readonly name: "Dataframe Access Validation";
193
+ readonly tags: readonly [import("./linter-tags").LintingRuleTag.Bug, import("./linter-tags").LintingRuleTag.Usability, import("./linter-tags").LintingRuleTag.Reproducibility];
194
+ readonly description: "Validates the existance of accessed columns and rows of dataframes.";
195
+ readonly defaultConfig: {
196
+ readonly readLoadedData: false;
174
197
  };
175
198
  };
176
199
  };
@@ -7,6 +7,7 @@ const absolute_path_1 = require("./rules/absolute-path");
7
7
  const unused_definition_1 = require("./rules/unused-definition");
8
8
  const seeded_randomness_1 = require("./rules/seeded-randomness");
9
9
  const naming_convention_1 = require("./rules/naming-convention");
10
+ const dataframe_access_validation_1 = require("./rules/dataframe-access-validation");
10
11
  /**
11
12
  * The registry of currently supported linting rules.
12
13
  * A linting rule can be executed on a dataflow pipeline result using {@link executeLintingRule}.
@@ -17,6 +18,7 @@ exports.LintingRules = {
17
18
  'seeded-randomness': seeded_randomness_1.SEEDED_RANDOMNESS,
18
19
  'absolute-file-paths': absolute_path_1.ABSOLUTE_PATH,
19
20
  'unused-definitions': unused_definition_1.UNUSED_DEFINITION,
20
- 'naming-convention': naming_convention_1.NAMING_CONVENTION
21
+ 'naming-convention': naming_convention_1.NAMING_CONVENTION,
22
+ 'dataframe-access-validation': dataframe_access_validation_1.DATA_FRAME_ACCESS_VALIDATION
21
23
  };
22
24
  //# sourceMappingURL=linter-rules.js.map
@@ -38,7 +38,7 @@ export interface AbsoluteFilePathMetadata extends MergeableRecord {
38
38
  export declare const ABSOLUTE_PATH: {
39
39
  readonly createSearch: (config: AbsoluteFilePathConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", ["unique"], ParentInformation, import("../../search/flowr-search").FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>>;
40
40
  readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<ParentInformation, {
41
- readonly query?: "config" | "origin" | "dataflow" | "search" | "call-context" | "control-flow" | "dataflow-lens" | "normalized-ast" | "id-map" | "dataflow-cluster" | "static-slice" | "lineage" | "dependencies" | "location-map" | "happens-before" | "resolve-value" | "project" | "linter" | undefined;
41
+ readonly query?: "config" | "origin" | "dataflow" | "search" | "call-context" | "control-flow" | "dataflow-lens" | "df-shape" | "normalized-ast" | "id-map" | "dataflow-cluster" | "static-slice" | "lineage" | "dependencies" | "location-map" | "happens-before" | "resolve-value" | "project" | "linter" | undefined;
42
42
  readonly queryResult?: import("../../queries/base-query-format").BaseQueryResult | undefined;
43
43
  readonly node: import("../../r-bridge/lang-4.x/ast/model/nodes/r-expression-list").RExpressionList<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-function-definition").RFunctionDefinition<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call").RNamedFunctionCall<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call").RUnnamedFunctionCall<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-parameter").RParameter<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-argument").RArgument<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-comment").RComment<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-line-directive").RLineDirective<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-for-loop").RForLoop<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop").RRepeatLoop<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-while-loop").RWhileLoop<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-if-then-else").RIfThenElse<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-access").RNamedAccess<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-access").RIndexAccess<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-unary-op").RUnaryOp<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-binary-op").RBinaryOp<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-symbol").RSymbol<ParentInformation, string> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-number").RNumber<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-string").RString<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-logical").RLogical<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-break").RBreak<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-next").RNext<ParentInformation> | import("../../r-bridge/lang-4.x/ast/model/nodes/r-pipe").RPipe<ParentInformation>;
44
44
  }[]>, config: AbsoluteFilePathConfig, data: {
@@ -0,0 +1,53 @@
1
+ import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
2
+ import type { FlowrSearchElements } from '../../search/flowr-search';
3
+ import { type MergeableRecord } from '../../util/objects';
4
+ import { type SourceRange } from '../../util/range';
5
+ import type { LintingResult } from '../linter-format';
6
+ import { LintingRuleTag } from '../linter-tags';
7
+ export interface DataFrameAccessValidationResult extends LintingResult {
8
+ /** The type of the data frame access ("column" or "row") */
9
+ type: 'column' | 'row';
10
+ /** The name or index of the column or row being accessed in the data frame */
11
+ accessed: string | number;
12
+ /** The name of the function/operation used for the access (e.g. `$`, `[`, `[[`, but also `filter`, `select`, ...) */
13
+ access: string;
14
+ /** The variable/symbol name of the accessed data frame operand (`undefined` if operand is no symbol) */
15
+ operand?: string;
16
+ /** The source range in the code where the access occurs */
17
+ range: SourceRange;
18
+ }
19
+ export interface DataFrameAccessValidationConfig extends MergeableRecord {
20
+ /** Whether data frame shapes should be extracted from loaded external data files, such as CSV files (defaults to the option in the flowR config if `undefined`) */
21
+ readLoadedData?: boolean;
22
+ }
23
+ export interface DataFrameAccessValidationMetadata extends MergeableRecord {
24
+ /** The number of data frame functions and operations containing inferred column or row accesses */
25
+ numOperations: number;
26
+ /** The number of inferred abstract column or row access operations */
27
+ numAccesses: number;
28
+ /** The total number of inferred accessed columns and rows */
29
+ totalAccessed: number;
30
+ }
31
+ 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 processSearchResult: (elements: FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>, config: DataFrameAccessValidationConfig, data: {
34
+ normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
35
+ dataflow: import("../../dataflow/info").DataflowInformation;
36
+ config: import("../../config").FlowrConfigOptions;
37
+ }) => {
38
+ results: DataFrameAccessValidationResult[];
39
+ '.meta': DataFrameAccessValidationMetadata;
40
+ };
41
+ readonly prettyPrint: {
42
+ readonly query: (result: DataFrameAccessValidationResult) => string;
43
+ readonly full: (result: DataFrameAccessValidationResult) => string;
44
+ };
45
+ readonly info: {
46
+ readonly name: "Dataframe Access Validation";
47
+ readonly tags: readonly [LintingRuleTag.Bug, LintingRuleTag.Usability, LintingRuleTag.Reproducibility];
48
+ readonly description: "Validates the existance of accessed columns and rows of dataframes.";
49
+ readonly defaultConfig: {
50
+ readonly readLoadedData: false;
51
+ };
52
+ };
53
+ };
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DATA_FRAME_ACCESS_VALIDATION = void 0;
4
+ const absint_info_1 = require("../../abstract-interpretation/data-frame/absint-info");
5
+ const domain_1 = require("../../abstract-interpretation/data-frame/domain");
6
+ const shape_inference_1 = require("../../abstract-interpretation/data-frame/shape-inference");
7
+ const config_1 = require("../../config");
8
+ const extract_cfg_1 = require("../../control-flow/extract-cfg");
9
+ const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
10
+ const flowr_search_builder_1 = require("../../search/flowr-search-builder");
11
+ const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
12
+ const dfg_1 = require("../../util/mermaid/dfg");
13
+ const range_1 = require("../../util/range");
14
+ const linter_format_1 = require("../linter-format");
15
+ const linter_tags_1 = require("../linter-tags");
16
+ ;
17
+ ;
18
+ exports.DATA_FRAME_ACCESS_VALIDATION = {
19
+ createSearch: () => flowr_search_builder_1.Q.all().with(search_enrichers_1.Enrichment.CallTargets, { onlyBuiltin: true }),
20
+ processSearchResult: (elements, config, data) => {
21
+ const flowrConfig = (0, config_1.amendConfig)(data.config, flowrConfig => {
22
+ if (config.readLoadedData !== undefined) {
23
+ flowrConfig.abstractInterpretation.dataFrame.readLoadedData.readExternalFiles = config.readLoadedData;
24
+ }
25
+ return flowrConfig;
26
+ });
27
+ const cfg = (0, extract_cfg_1.extractCfg)(data.normalize, flowrConfig, data.dataflow.graph);
28
+ (0, shape_inference_1.inferDataFrameShapes)(cfg, data.dataflow.graph, data.normalize, flowrConfig);
29
+ const accessOperations = getAccessOperations(elements);
30
+ const accesses = [];
31
+ for (const [nodeId, operations] of accessOperations) {
32
+ const access = { nodeId };
33
+ for (const operation of operations) {
34
+ access.operand ??= operation.operand;
35
+ access.operandShape ??= (0, shape_inference_1.resolveIdToDataFrameShape)(operation.operand, data.dataflow.graph);
36
+ if (operation.operation === 'accessCols' && operation.columns !== undefined) {
37
+ access.accessedCols ??= [];
38
+ access.accessedCols.push(...operation.columns);
39
+ }
40
+ else if (operation.operation === 'accessRows' && operation.rows !== undefined) {
41
+ access.accessedRows ??= [];
42
+ access.accessedRows.push(...operation.rows);
43
+ }
44
+ }
45
+ accesses.push(access);
46
+ }
47
+ const operations = accessOperations.entries().flatMap(([, operations]) => operations).toArray();
48
+ const metadata = {
49
+ numOperations: accessOperations.size,
50
+ numAccesses: operations.length,
51
+ totalAccessed: operations
52
+ .map(operation => operation.operation === 'accessCols' ? operation.columns?.length ?? 0 : operation.rows?.length ?? 0)
53
+ .reduce((a, b) => a + b, 0)
54
+ };
55
+ const results = accesses
56
+ .flatMap(access => findInvalidDataFrameAccesses(access)
57
+ .map(accessed => ({ nodeId: access.nodeId, operand: access.operand, ...accessed })))
58
+ .map(({ nodeId, operand, ...accessed }) => ({
59
+ ...accessed,
60
+ node: data.normalize.idMap.get(nodeId),
61
+ operand: operand !== undefined ? data.normalize.idMap.get(operand) : undefined,
62
+ }))
63
+ .map(({ node, operand, ...accessed }) => ({
64
+ ...accessed,
65
+ access: node?.lexeme ?? '???',
66
+ ...(operand?.type === type_1.RType.Symbol ? { operand: operand.content } : {}),
67
+ range: node?.info.fullRange ?? node?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
68
+ certainty: linter_format_1.LintingCertainty.Definitely
69
+ }));
70
+ return { results, '.meta': metadata };
71
+ },
72
+ prettyPrint: {
73
+ [linter_format_1.LintingPrettyPrintContext.Query]: result => `Access of ${result.type} ` +
74
+ (typeof result.accessed === 'string' ? `"${result.accessed}"` : result.accessed) + ' ' +
75
+ (result.operand !== undefined ? `of \`${result.operand}\`` : `at \`${result.access}\``) + ` at ${(0, dfg_1.formatRange)(result.range)}`,
76
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Accessed ${result.type} ` +
77
+ (typeof result.accessed === 'string' ? `"${result.accessed}"` : result.accessed) + ' does not exist ' +
78
+ (result.operand !== undefined ? `in \`${result.operand}\`` : `at \`${result.access}\``) + ` at ${(0, dfg_1.formatRange)(result.range)}`
79
+ },
80
+ info: {
81
+ name: 'Dataframe Access Validation',
82
+ tags: [linter_tags_1.LintingRuleTag.Bug, linter_tags_1.LintingRuleTag.Usability, linter_tags_1.LintingRuleTag.Reproducibility],
83
+ description: 'Validates the existance of accessed columns and rows of dataframes.',
84
+ defaultConfig: { readLoadedData: false }
85
+ }
86
+ };
87
+ function getAccessOperations(elements) {
88
+ return new Map(elements.getElements()
89
+ .map(element => element.node)
90
+ .filter(absint_info_1.hasDataFrameExpressionInfo)
91
+ .map(node => [node.info.id, node.info.dataFrame.operations
92
+ .filter(({ operation }) => operation === 'accessCols' || operation === 'accessRows')
93
+ .map(({ operation, operand, type: _type, options: _options, ...args }) => ({ operation, operand, ...args }))
94
+ ])
95
+ .filter(([, operations]) => operations.length > 0));
96
+ }
97
+ function findInvalidDataFrameAccesses({ operandShape, accessedCols, accessedRows }) {
98
+ const invalidAccesses = [];
99
+ if (operandShape !== undefined) {
100
+ for (const row of accessedRows ?? []) {
101
+ if (!(0, domain_1.satisfiesLeqInterval)(operandShape.rows, row)) {
102
+ invalidAccesses.push({ type: 'row', accessed: row });
103
+ }
104
+ }
105
+ for (const col of accessedCols ?? []) {
106
+ if (typeof col === 'string' && !(0, domain_1.satisfiesColsNames)(operandShape.colnames, col)) {
107
+ invalidAccesses.push({ type: 'column', accessed: col });
108
+ }
109
+ else if (typeof col === 'number' && !(0, domain_1.satisfiesLeqInterval)(operandShape.cols, col)) {
110
+ invalidAccesses.push({ type: 'column', accessed: col });
111
+ }
112
+ }
113
+ }
114
+ return invalidAccesses;
115
+ }
116
+ //# sourceMappingURL=dataframe-access-validation.js.map
@@ -65,7 +65,7 @@ export declare const NAMING_CONVENTION: {
65
65
  readonly description: "Checks wether the symbols conform to a certain naming convention";
66
66
  readonly tags: readonly [LintingRuleTag.Style, LintingRuleTag.QuickFix];
67
67
  readonly defaultConfig: {
68
- readonly caseing: CasingConvention.PascalCase;
68
+ readonly caseing: "auto";
69
69
  };
70
70
  };
71
71
  };
@@ -66,11 +66,15 @@ function detectCasing(identifier) {
66
66
  return CasingConvention.Unknown;
67
67
  }
68
68
  function getMostUsedCasing(symbols) {
69
+ if (symbols.length === 0) {
70
+ return CasingConvention.Unknown;
71
+ }
69
72
  const map = new Map();
70
73
  for (const symbol of symbols) {
71
74
  const o = map.get(symbol.detectedCasing) ?? 0;
72
75
  map.set(symbol.detectedCasing, o + 1);
73
76
  }
77
+ // Return element with most occurances
74
78
  return [...map].reduce((p, c) => p[1] > c[1] ? p : c)[0];
75
79
  }
76
80
  function fixCasing(identifier, convention) {
@@ -157,7 +161,7 @@ exports.NAMING_CONVENTION = {
157
161
  description: 'Checks wether the symbols conform to a certain naming convention',
158
162
  tags: [linter_tags_1.LintingRuleTag.Style, linter_tags_1.LintingRuleTag.QuickFix],
159
163
  defaultConfig: {
160
- caseing: CasingConvention.PascalCase
164
+ caseing: 'auto'
161
165
  }
162
166
  }
163
167
  };