@eagleoutice/flowr 2.4.7 → 2.4.8

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 (86) hide show
  1. package/README.md +43 -39
  2. package/abstract-interpretation/data-frame/absint-visitor.js +3 -2
  3. package/benchmark/slicer.js +1 -1
  4. package/benchmark/summarizer/first-phase/process.js +1 -1
  5. package/cli/repl/commands/repl-query.js +11 -2
  6. package/cli/repl/core.d.ts +2 -2
  7. package/cli/repl/core.js +26 -7
  8. package/cli/repl/server/connection.js +3 -1
  9. package/cli/repl/server/messages/message-slice.d.ts +3 -0
  10. package/cli/repl/server/messages/message-slice.js +2 -0
  11. package/control-flow/extract-cfg.d.ts +3 -3
  12. package/control-flow/extract-cfg.js +4 -4
  13. package/control-flow/useless-loop.js +30 -21
  14. package/dataflow/environments/built-in.d.ts +1 -1
  15. package/dataflow/environments/default-builtin-config.d.ts +9 -0
  16. package/dataflow/environments/default-builtin-config.js +21 -21
  17. package/dataflow/environments/environment.js +18 -9
  18. package/dataflow/environments/overwrite.js +2 -2
  19. package/dataflow/extractor.js +1 -1
  20. package/dataflow/graph/diff-dataflow-graph.js +4 -4
  21. package/dataflow/graph/graph.d.ts +3 -3
  22. package/dataflow/graph/graph.js +4 -1
  23. package/dataflow/graph/quads.js +4 -4
  24. package/dataflow/info.js +1 -1
  25. package/dataflow/internal/linker.d.ts +2 -0
  26. package/dataflow/internal/linker.js +18 -1
  27. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -1
  28. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +68 -21
  29. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -2
  30. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +4 -4
  31. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -18
  32. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
  33. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +4 -5
  34. package/dataflow/internal/process/functions/call/common.js +4 -3
  35. package/documentation/doc-util/doc-query.js +6 -2
  36. package/documentation/doc-util/doc-types.d.ts +7 -2
  37. package/documentation/doc-util/doc-types.js +20 -4
  38. package/documentation/print-core-wiki.js +5 -1
  39. package/documentation/print-dataflow-graph-wiki.js +21 -12
  40. package/documentation/print-faq-wiki.js +5 -0
  41. package/documentation/print-interface-wiki.js +2 -0
  42. package/documentation/print-linter-wiki.js +2 -3
  43. package/documentation/print-query-wiki.js +22 -7
  44. package/linter/linter-executor.js +25 -17
  45. package/linter/linter-format.d.ts +10 -1
  46. package/linter/linter-format.js +8 -0
  47. package/linter/linter-rules.d.ts +1 -0
  48. package/linter/rules/absolute-path.js +8 -8
  49. package/linter/rules/dataframe-access-validation.js +1 -1
  50. package/linter/rules/file-path-validity.js +8 -11
  51. package/linter/rules/naming-convention.d.ts +5 -1
  52. package/linter/rules/naming-convention.js +24 -8
  53. package/linter/rules/seeded-randomness.js +2 -2
  54. package/linter/rules/unused-definition.js +1 -1
  55. package/package.json +17 -15
  56. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +5 -1
  57. package/queries/catalog/call-context-query/call-context-query-executor.js +14 -12
  58. package/queries/catalog/call-context-query/call-context-query-format.d.ts +6 -5
  59. package/queries/catalog/call-context-query/call-context-query-format.js +1 -1
  60. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -1
  61. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
  62. package/queries/catalog/config-query/config-query-executor.js +7 -1
  63. package/queries/catalog/config-query/config-query-format.d.ts +7 -0
  64. package/queries/catalog/config-query/config-query-format.js +72 -1
  65. package/queries/catalog/dependencies-query/dependencies-query-executor.js +50 -75
  66. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +50 -26
  67. package/queries/catalog/dependencies-query/dependencies-query-format.js +75 -20
  68. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +2 -2
  69. package/queries/catalog/dependencies-query/function-info/visualize-functions.d.ts +2 -0
  70. package/queries/catalog/dependencies-query/function-info/visualize-functions.js +13 -0
  71. package/queries/catalog/happens-before-query/happens-before-query-executor.js +1 -1
  72. package/queries/catalog/linter-query/linter-query-format.js +4 -0
  73. package/queries/query-print.d.ts +2 -2
  74. package/queries/query-print.js +3 -2
  75. package/queries/query.d.ts +28 -21
  76. package/search/flowr-search-builder.d.ts +1 -1
  77. package/search/flowr-search-builder.js +1 -1
  78. package/search/flowr-search-filters.d.ts +20 -10
  79. package/search/flowr-search-filters.js +19 -3
  80. package/search/search-executor/search-enrichers.d.ts +1 -1
  81. package/search/search-executor/search-enrichers.js +3 -2
  82. package/search/search-executor/search-generators.js +1 -1
  83. package/search/search-executor/search-transformer.js +1 -1
  84. package/util/objects.d.ts +11 -0
  85. package/util/objects.js +26 -0
  86. package/util/version.js +1 -1
@@ -28,7 +28,7 @@ function processIfThenElse(name, args, rootId, data) {
28
28
  logger_1.dataflowLogger.warn(`If-then-else ${rootId} forces exit in condition, skipping rest`);
29
29
  return cond;
30
30
  }
31
- const originalDependency = data.controlDependencies;
31
+ const originalDependency = data.controlDependencies?.slice();
32
32
  // currently we update the cd afterward :sweat:
33
33
  data = { ...data, environment: cond.environment };
34
34
  let then;
@@ -73,21 +73,10 @@ function processIfThenElse(name, args, rootId, data) {
73
73
  const cdTrue = { id: rootId, when: true };
74
74
  const cdFalse = { id: rootId, when: false };
75
75
  // again within an if-then-else we consider all actives to be read
76
- const ingoing = [
77
- ...cond.in,
78
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.in, nextGraph, finalEnvironment, false, cdTrue) : then?.in ?? []),
79
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.in, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.in ?? []),
80
- ...cond.unknownReferences,
81
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.unknownReferences, nextGraph, finalEnvironment, false, cdTrue) : then?.unknownReferences ?? []),
82
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.unknownReferences, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.unknownReferences ?? []),
83
- ];
76
+ const ingoing = cond.in.concat(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.in, nextGraph, finalEnvironment, false, cdTrue) : then?.in ?? [], makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.in, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.in ?? [], cond.unknownReferences, makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.unknownReferences, nextGraph, finalEnvironment, false, cdTrue) : then?.unknownReferences ?? [], makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.unknownReferences, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.unknownReferences ?? []);
84
77
  // we assign all with a maybe marker
85
78
  // we do not merge even if they appear in both branches because the maybe links will refer to different ids
86
- const outgoing = [
87
- ...cond.out,
88
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.out, nextGraph, finalEnvironment, true, cdTrue) : then?.out ?? []),
89
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.out, nextGraph, finalEnvironment, true, cdFalse) : otherwise?.out ?? []),
90
- ];
79
+ const outgoing = cond.out.concat((makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.out, nextGraph, finalEnvironment, true, cdTrue) : then?.out ?? []), (makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.out, nextGraph, finalEnvironment, true, cdFalse) : otherwise?.out ?? []));
91
80
  (0, common_1.patchFunctionCall)({
92
81
  nextGraph,
93
82
  rootId,
@@ -98,10 +87,8 @@ function processIfThenElse(name, args, rootId, data) {
98
87
  });
99
88
  // as an if always evaluates its condition, we add a 'reads'-edge
100
89
  nextGraph.addEdge(name.info.id, cond.entryPoint, edge_1.EdgeType.Reads);
101
- const exitPoints = [
102
- ...(then?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeThenMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: true }] : e.controlDependencies })),
103
- ...(otherwise?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeOtherwiseMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: false }] : e.controlDependencies }))
104
- ];
90
+ const exitPoints = (then?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeThenMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: true }] : e.controlDependencies }))
91
+ .concat((otherwise?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeOtherwiseMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: false }] : e.controlDependencies })));
105
92
  return {
106
93
  unknownReferences: [],
107
94
  in: [{ nodeId: rootId, name: name.content, controlDependencies: originalDependency, type: identifier_1.ReferenceType.Function }, ...ingoing],
@@ -31,6 +31,7 @@ function processRepeatLoop(name, args, rootId, data) {
31
31
  const body = processedArguments[0];
32
32
  (0, assert_1.guard)(body !== undefined, () => `Repeat-Loop ${name.content} has no body, impossible!`);
33
33
  (0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, [])), body.out);
34
+ (0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
34
35
  information.exitPoints = (0, info_1.filterOutLoopExitPoints)(information.exitPoints);
35
36
  return information;
36
37
  }
@@ -65,17 +65,16 @@ function processWhileLoop(name, args, rootId, data) {
65
65
  information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
66
66
  return condition;
67
67
  }
68
- const remainingInputs = (0, linker_1.linkInputs)([
69
- ...(0, environment_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false),
70
- ...(0, environment_1.makeAllMaybe)(body.in, information.graph, information.environment, false)
71
- ], information.environment, [...condition.in, ...condition.unknownReferences], information.graph, true);
68
+ const cdTrue = { id: name.info.id, when: true };
69
+ const remainingInputs = (0, linker_1.linkInputs)((0, environment_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false, cdTrue).concat((0, environment_1.makeAllMaybe)(body.in, information.graph, information.environment, false, cdTrue)), information.environment, condition.in.concat(condition.unknownReferences), information.graph, true);
72
70
  (0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, condition.in)), body.out);
71
+ (0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
73
72
  // as the while-loop always evaluates its condition
74
73
  information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
75
74
  return {
76
75
  unknownReferences: [],
77
76
  in: [{ nodeId: name.info.id, name: name.lexeme, controlDependencies: originalDependency, type: identifier_1.ReferenceType.Function }, ...remainingInputs],
78
- out: [...(0, environment_1.makeAllMaybe)(body.out, information.graph, information.environment, true), ...condition.out],
77
+ out: condition.out.concat((0, environment_1.makeAllMaybe)(body.out, information.graph, information.environment, true, cdTrue)),
79
78
  entryPoint: name.info.id,
80
79
  exitPoints: (0, info_1.filterOutLoopExitPoints)(body.exitPoints),
81
80
  graph: information.graph,
@@ -29,11 +29,12 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
29
29
  }
30
30
  }
31
31
  }
32
- const containedSubflowIn = [...graph.vertices(true)]
32
+ const containedSubflowIn = graph.vertices(true)
33
33
  .filter(([, info]) => (0, vertex_1.isFunctionDefinitionVertex)(info))
34
- .flatMap(([, info]) => info);
34
+ .flatMap(([, info]) => info.subflow.in)
35
+ .toArray();
35
36
  // try to resolve them against the current environment
36
- for (const ref of [...value.in, ...containedSubflowIn.flatMap(n => n.subflow.in)]) {
37
+ for (const ref of value.in.concat(containedSubflowIn)) {
37
38
  if (ref.name) {
38
39
  const resolved = ref.name ? (0, resolve_by_name_1.resolveByName)(ref.name, env, ref.type) ?? [] : [];
39
40
  for (const resolve of resolved) {
@@ -25,7 +25,11 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
25
25
  parser: shell,
26
26
  request: (0, retriever_1.requestFromInput)(code)
27
27
  }, config_1.defaultConfigOptions).allRemainingSteps();
28
- const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
28
+ const results = await Promise.resolve((0, query_1.executeQueries)({
29
+ dataflow: analysis.dataflow,
30
+ ast: analysis.normalize,
31
+ config: (0, config_1.cloneConfig)(config_1.defaultConfigOptions)
32
+ }, queries));
29
33
  const duration = performance.now() - now;
30
34
  const metaInfo = `
31
35
  The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
@@ -48,7 +52,7 @@ ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary
48
52
 
49
53
  _Results (prettified and summarized):_
50
54
 
51
- ${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis)}
55
+ ${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis, queries)}
52
56
 
53
57
  <details> <summary style="color:gray">Show Detailed Results as Json</summary>
54
58
 
@@ -1,8 +1,9 @@
1
1
  import ts from 'typescript';
2
+ export type TypeElementKind = 'interface' | 'type' | 'enum' | 'class' | 'variable';
2
3
  export interface TypeElementInSource {
3
4
  name: string;
4
5
  node: ts.Node;
5
- kind: 'interface' | 'type' | 'enum' | 'class' | 'variable';
6
+ kind: TypeElementKind;
6
7
  extends: string[];
7
8
  generics: string[];
8
9
  filePath: string;
@@ -73,5 +74,9 @@ export declare function printCodeOfElement({ program, info }: FnInfo, name: stri
73
74
  */
74
75
  export declare function shortLink(name: string, hierarchy: readonly TypeElementInSource[], codeStyle?: boolean, realNameWrapper?: string): string;
75
76
  export declare function shortLinkFile(name: string, hierarchy: readonly TypeElementInSource[]): string;
76
- export declare function getDocumentationForType(name: string, hierarchy: TypeElementInSource[], prefix?: string, fuzzy?: boolean): string;
77
+ export interface GetDocumentationForTypeFilters {
78
+ fuzzy?: boolean;
79
+ type?: TypeElementKind;
80
+ }
81
+ export declare function getDocumentationForType(name: string, hierarchy: TypeElementInSource[], prefix?: string, filter?: GetDocumentationForTypeFilters): string;
77
82
  export {};
@@ -32,7 +32,17 @@ const html_hover_over_1 = require("../../util/html-hover-over");
32
32
  const doc_general_1 = require("./doc-general");
33
33
  function getTypeScriptSourceFiles(fileNames) {
34
34
  try {
35
- const program = typescript_1.default.createProgram(fileNames, { target: typescript_1.default.ScriptTarget.ESNext });
35
+ const program = typescript_1.default.createProgram(fileNames, {
36
+ target: typescript_1.default.ScriptTarget.ESNext,
37
+ skipLibCheck: true,
38
+ skipDefaultLibCheck: true,
39
+ allowJs: true,
40
+ checkJs: false,
41
+ strictNullChecks: false,
42
+ noUncheckedIndexedAccess: false,
43
+ noUncheckedSideEffectImports: false,
44
+ noCheck: true
45
+ });
36
46
  return { program, files: fileNames.map(fileName => program.getSourceFile(fileName)).filter(file => !!file) };
37
47
  }
38
48
  catch (err) {
@@ -391,7 +401,7 @@ function fuzzyCompare(a, b) {
391
401
  const bStr = b.toLowerCase().replace(/[^a-z0-9]/g, '-').trim();
392
402
  return aStr === bStr || aStr.includes(bStr) || bStr.includes(aStr);
393
403
  }
394
- function retrieveNode(name, hierarchy, fuzzy = false) {
404
+ function retrieveNode(name, hierarchy, fuzzy = false, type = undefined) {
395
405
  let container = undefined;
396
406
  if (name.includes('::')) {
397
407
  [container, name] = name.split(/:::?/);
@@ -406,6 +416,12 @@ function retrieveNode(name, hierarchy, fuzzy = false) {
406
416
  return undefined;
407
417
  }
408
418
  }
419
+ if (type) {
420
+ node = node.filter(n => n.kind === type);
421
+ if (node.length === 0) {
422
+ return undefined;
423
+ }
424
+ }
409
425
  return [container, name, node[0]];
410
426
  }
411
427
  /**
@@ -440,8 +456,8 @@ function shortLinkFile(name, hierarchy) {
440
456
  const [, , node] = res;
441
457
  return `<a href="${getTypePathLink(node)}">${getTypePathForTypeScript(node)}</a>`;
442
458
  }
443
- function getDocumentationForType(name, hierarchy, prefix = '', fuzzy = false) {
444
- const res = retrieveNode(name, hierarchy, fuzzy);
459
+ function getDocumentationForType(name, hierarchy, prefix = '', filter) {
460
+ const res = retrieveNode(name, hierarchy, filter?.fuzzy, filter?.type);
445
461
  if (!res) {
446
462
  return '';
447
463
  }
@@ -50,6 +50,10 @@ async function getText(shell) {
50
50
  rootFolder: path_1.default.resolve('./src'),
51
51
  inlineTypes: doc_types_1.mermaidHide
52
52
  });
53
+ const testInfo = (0, doc_types_1.getTypesFromFolder)({
54
+ rootFolder: path_1.default.resolve('./test'),
55
+ inlineTypes: doc_types_1.mermaidHide
56
+ }).info;
53
57
  return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'core', rVersion: rversion })}
54
58
 
55
59
  This wiki page provides an overview of the inner workings of _flowR_.
@@ -390,7 +394,7 @@ ${await (0, doc_repl_1.documentReplSession)(shell, [{
390
394
  ### Getting flowR to Talk
391
395
 
392
396
  When using flowR from the CLI, you can use the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')} option to get more information about what flowR is doing.
393
- While coding, however, you can use the ${(0, doc_types_1.shortLink)(log_1.setMinLevelOfAllLogs.name, info)} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
397
+ While coding, however, you can use the ${(0, doc_types_1.shortLink)(log_1.setMinLevelOfAllLogs.name, testInfo)} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
394
398
  In general, you can configure the levels of individual logs, such as the general \`log\` (obtained with ${(0, doc_types_1.shortLink)('getActiveLog', info)}) or the ${(0, doc_types_1.shortLink)('parseLog', info)}.
395
399
  Please note that flowR makes no guarantees that log outputs are persistent across versions, and it is up to the implementors to provide sensible logging.
396
400
  If you are an implementor and want to add logging, please make sure there are no larger runtime impliciations when logging is disabled.
@@ -74,7 +74,7 @@ async function explanation({ shell, name, type, description, code, expectedSubgr
74
74
  <a id='${name.toLowerCase().replaceAll(' ', '-')}'> </a>
75
75
  ### ${index}) ${name}
76
76
 
77
- Type: \`${type}\` (this is the numeric value of the bit-flag encountered when looking at the serialized vertex type)
77
+ Type: \`${type}\` (this is the bit-flag value, e.g., when looking at the serialization)
78
78
 
79
79
  ${await subExplanation(shell, { name, description, code, expectedSubgraph })}
80
80
 
@@ -268,7 +268,7 @@ ${await (async () => {
268
268
  const code = 'foo <- function() 3\nfoo()';
269
269
  const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { exposeResult: true, mark: new Set([6, '6->0', '6->1', '6->3']) });
270
270
  const numberOfEdges = [...info.dataflow.graph.edges()].flatMap(e => [...e[1].keys()]).length;
271
- const callVertex = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
271
+ const callVertex = info.dataflow.graph.vertices(true).find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
272
272
  (0, assert_1.guard)(callVertex !== undefined, () => `Could not find call vertex for ${code}`);
273
273
  const [callId] = callVertex;
274
274
  return `
@@ -367,11 +367,11 @@ ${(0, doc_structure_1.block)({
367
367
  content: `Now you might be asking yourself how to differentiate anonymous and named functions and what you have to keep in mind when working with them?
368
368
 
369
369
  Unnamed functions have an array of signatures which you can use to identify them.
370
- But in short - the \`origin\` attribute of the ${(0, doc_types_1.shortLink)('DataflowGraphVertexFunctionCall', vertexType.info)} is \`${unnamed_call_handling_1.UnnamedFunctionCallOrigin}\`.
370
+ But in short: the \`origin\` attribute of the ${(0, doc_types_1.shortLink)('DataflowGraphVertexFunctionCall', vertexType.info)} is \`${unnamed_call_handling_1.UnnamedFunctionCallOrigin}\`.
371
371
  Please be aware that unnamed functions still have a \`name\` property to give it a unique identifier that can be used for debugging and reference.
372
372
  This name _always_ starts with \`${unnamed_call_handling_1.UnnamedFunctionCallPrefix}\`.
373
373
 
374
- To identify these calls please do not rely on the [Normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST). An expression like \`1 + 1\` will be correctly
374
+ To identify these calls please do not rely on the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST). An expression like \`1 + 1\` will be correctly
375
375
  identified as a syntactical binary operation. Yet, from a dataflow/semantic perspective this is equivalent to \`\` \`+\`(1, 1) \`\` (which is a named function call and marked as such in the dataflow graph).
376
376
  To know which function is called, please rely on the ${linkEdgeName(edge_1.EdgeType.Calls)} edge.
377
377
  `
@@ -458,9 +458,10 @@ vertices of function definitions or not (e.g., \`${new graph_1.DataflowGraph(und
458
458
 
459
459
  ${(0, doc_structure_1.details)('Example: Nested Function Definitions', await (async () => {
460
460
  const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() { g <- function() 3 }', { mark: new Set([9, 6]), exposeResult: true });
461
- const definitions = [...info.dataflow.graph.vertices(true)]
461
+ const definitions = info.dataflow.graph.vertices(true)
462
462
  .filter(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionDefinition)
463
- .map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`);
463
+ .map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`)
464
+ .toArray();
464
465
  return `
465
466
  ${text}
466
467
 
@@ -766,6 +767,7 @@ async function getText(shell) {
766
767
 
767
768
  This page briefly summarizes flowR's dataflow graph, represented by the ${(0, doc_types_1.shortLink)(graph_1.DataflowGraph.name, vertexType.info)} class within the code.
768
769
  In case you want to manually build such a graph (e.g., for testing), you can use the ${(0, doc_types_1.shortLink)(dataflowgraph_builder_1.DataflowGraphBuilder.name, vertexType.info)}.
770
+ If you are interested in which features we support and which features are still to be worked on, please refer to our [capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) page.
769
771
  In summary, we discuss the following topics:
770
772
 
771
773
  - [Vertices](#vertices)
@@ -777,7 +779,7 @@ In summary, we discuss the following topics:
777
779
 
778
780
  Please be aware that the accompanied [dataflow information](#dataflow-information) (${(0, doc_types_1.shortLink)('DataflowInformation', vertexType.info)}) returned by _flowR_ contains things besides the graph,
779
781
  like the entry and exit points of the subgraphs, and currently active references (see [below](#dataflow-information)).
780
- Additionally, you may be interested in the set of [Unknown Side Effects](#unknown-side-effects) marking calls which _flowR_ is unable to handle correctly.
782
+ Additionally, you may be interested in the set of [Unknown Side Effects](#unknown-side-effects), marking calls which _flowR_ is unable to handle correctly.
781
783
 
782
784
  Potentially, you are interested in another perspective that flowR provides, the [control flow graph](${doc_files_1.FlowrWikiBaseRef}/Control%20Flow%20Graph), so please check the correpsonding
783
785
  wiki page if you are unsure.
@@ -829,16 +831,16 @@ From an implementation perspective all of these types are represented by respect
829
831
  The following sections present details on the different types of vertices and edges, including examples and explanations.
830
832
 
831
833
  > [!NOTE]
832
- > Every dataflow vertex holds an \`id\` which links it to the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST).
834
+ > Every dataflow vertex holds an \`id\` which links it to the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST).
833
835
  > So if you want more information about the respective vertex, you can usually access more information
834
836
  > using the <code>${(0, doc_types_1.shortLink)(`${graph_1.DataflowGraph.name}`, vertexType.info, false, 'i')}::idMap</code> linked to the dataflow graph:
835
837
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
836
838
  > In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
837
839
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
838
840
  >
839
- > Please note that not every node in the normalized AST is represented in the dataflow graph.
841
+ > Please note, that not every node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST) is represented in the dataflow graph.
840
842
  > For example, if the node is unreachable in a way that can be detected during the analysis and flowR
841
- > is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
843
+ > is configured to ignore dead code (there are more powerful dead code capabilities with the [CFG](${doc_files_1.FlowrWikiBaseRef}/Control-Flow-Graph)). Likewise, empty argument wrappers do not have a corresponding
842
844
  > dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
843
845
  > For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
844
846
  > some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
@@ -990,7 +992,8 @@ Depending on what you are interested in, there exists a plethora of functions an
990
992
  * ${(0, doc_types_1.shortLink)(identify_link_to_last_call_relation_1.getValueOfArgument.name, vertexType.info)} to get the (syntactical) value of an argument in a function call
991
993
  * ${(0, doc_types_1.shortLink)(dfg_get_origin_1.getOriginInDfg.name, vertexType.info)} to get information about where a read, call, ... comes from (see [below](#dfg-resolving-values))
992
994
 
993
- Some of these functions have been explained in their respective wiki pages. However, some are part of the [Dataflow Graph API](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph%20API) and so we explain them here.
995
+ Some of these functions have been explained in their respective wiki pages. However, some are part of the [Dataflow Graph API](${doc_files_1.FlowrWikiBaseRef}/Dataflow-Graph) and so we explain them here.
996
+ If you are interested in which features we support and which features are still to be worked on, please refer to our [capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) page.
994
997
 
995
998
  ${(0, doc_structure_1.section)('Resolving Values', 3, 'dfg-resolving-values')}
996
999
 
@@ -999,6 +1002,12 @@ These capabilities are exposed by the [resolve value Query](${doc_files_1.FlowrW
999
1002
 
1000
1003
  ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} provides an environment-sensitive (see ${(0, doc_types_1.shortLink)('REnvironmentInformation', vertexType.info)})
1001
1004
  value resolution depending on if the environment is provided.
1005
+ The idea of ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} is to provide a compromise between precision and performance, to
1006
+ be used _during_ and _after_ the core analysis. After the dataflow analysis completes, there are much more expensive queries possible (such as the resolution of the data frame shape, see the [Query API](${doc_files_1.FlowrWikiBaseRef}/Query-API)).
1007
+
1008
+ Additionally, to ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)}, we offer the aforementioned ${(0, doc_types_1.shortLink)(identify_link_to_last_call_relation_1.getValueOfArgument.name, vertexType.info)} to retrieve the value of an argument in a function call.
1009
+ Be aware, that this function is currently not optimized for speed, so if you frequently require the values of multiple arguments of the same function call, you may want to open [an issue](${doc_issue_1.NewIssueUrl}) to request support for resolving
1010
+ multiple arguments at once.
1002
1011
 
1003
1012
  ${(0, doc_structure_1.section)('Assessing Edges', 3, 'dfg-assess-edge')}
1004
1013
 
@@ -1035,7 +1044,7 @@ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, info: vertexTyp
1035
1044
 
1036
1045
  Their respective uses are documented alongside their implementation:
1037
1046
 
1038
- ${['SimpleOrigin', 'FunctionCallOrigin', 'BuiltInFunctionOrigin'].sort().map(key => `- ${(0, doc_types_1.shortLink)(`${key}`, vertexType.info)}\\\n${(0, doc_types_1.getDocumentationForType)(`${key}`, vertexType.info)}`).join('\n')}
1047
+ ${['SimpleOrigin', 'FunctionCallOrigin', 'BuiltInFunctionOrigin'].sort().map(key => `- ${(0, doc_types_1.shortLink)(key, vertexType.info)}\\\n${(0, doc_types_1.getDocumentationForType)(key, vertexType.info, '', { type: 'interface' })}`).join('\n')}
1039
1048
 
1040
1049
  Please note, the current structure of this function is biased by what implementations already exist in flowR.
1041
1050
  Hence, we do not just track definitions and constants, but also the origins of function calls, albeit we do not yet track the origins of values (only resorting to
@@ -15,6 +15,11 @@ ${qAndA('What are test labels and how do they work?', `
15
15
  Tests are labeled based on the *flowR* capabilities that they test for. The list of supported capabilities can be found on the [Capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) wiki page. For more extensive information on test labels, see the [test labels wiki section](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#test-labels).
16
16
  `)}
17
17
 
18
+ ${qAndA('How to get a REPL with debug-info/hot-reload?', `
19
+ To enter the development repl, execute \`npm run main-dev\` in contrast to \`npm run flowr\` this will use an unminified build (keeping debug info)
20
+ and will also watch the source files for changes and automatically recompile them. Please note, that this may have negative performance implications.
21
+ `)}
22
+
18
23
  ${qAndA('How do I generate mermaid diagrams?', `
19
24
  There are several ways to generate mermaid diagrams based on the input data that you want to use.
20
25
  - From the AST (abstract syntax tree): ${(0, doc_files_1.getFilePathMd)('../util/mermaid/ast.ts')}
@@ -116,6 +116,8 @@ which is interpreted as an R&nbsp;expression by default but interpreted as a *co
116
116
  The best command to get started with the REPL is ${(0, doc_cli_option_1.getReplCommand)('help')}.
117
117
  Besides, you can leave the REPL either with the command ${(0, doc_cli_option_1.getReplCommand)('quit')} or by pressing <kbd>CTRL</kbd>+<kbd>C</kbd> twice.
118
118
 
119
+ > [!NOTE]
120
+ > If you develop flowR, you may want to launch the repl using the \`npm run main-dev\` command, this way, you get a non-minified version of flowR with debug information and hot-reloading of source files.
119
121
 
120
122
  <details>
121
123
  <summary>Available Commands</summary>
@@ -28,7 +28,7 @@ const SpecialTagColors = {
28
28
  [linter_tags_1.LintingRuleTag.QuickFix]: 'lightgray'
29
29
  };
30
30
  function makeTagBadge(name, info) {
31
- const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', true).replaceAll('\n', ' ');
31
+ const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', { fuzzy: true }).replaceAll('\n', ' ');
32
32
  return (0, html_hover_over_1.textWithTooltip)(`<a href='#${name}'>![` + name + '](https://img.shields.io/badge/' + name.toLowerCase() + `-${SpecialTagColors[name] ?? 'teal'}) </a>`, doc);
33
33
  }
34
34
  function prettyPrintExpectedOutput(expected) {
@@ -66,7 +66,6 @@ These examples are synthesized from the test cases in: ${(0, doc_files_1.linkFlo
66
66
  }
67
67
  const testName = args[0].getText(report.source);
68
68
  if (report.comments?.some(c => c.includes('@ignore-in-wiki'))) {
69
- console.warn(`Skipping test case for linter rule ${testName} (${testFile}) as it is marked with @ignore-in-wiki`);
70
69
  continue;
71
70
  }
72
71
  // drop any quotes around the test name
@@ -133,7 +132,7 @@ df[6, "value"]
133
132
  }
134
133
  return a.localeCompare(b);
135
134
  }).map(t => makeTagBadge(t, types)).join(' ');
136
- const certaintyDoc = (0, doc_types_1.getDocumentationForType)(`LintingRuleCertainty::${rule.info.certainty}`, types, '', true).replaceAll('\n', ' ');
135
+ const certaintyDoc = (0, doc_types_1.getDocumentationForType)(`LintingRuleCertainty::${rule.info.certainty}`, types, '', { fuzzy: true }).replaceAll('\n', ' ');
137
136
  const certaintyText = `\`${(0, html_hover_over_1.textWithTooltip)(rule.info.certainty, certaintyDoc)}\``;
138
137
  if (format === 'short') {
139
138
  ruleExplanations.set(name, () => Promise.resolve(`
@@ -38,6 +38,7 @@ const control_flow_query_executor_1 = require("../queries/catalog/control-flow-q
38
38
  const doc_cfg_1 = require("./doc-util/doc-cfg");
39
39
  const df_shape_query_executor_1 = require("../queries/catalog/df-shape-query/df-shape-query-executor");
40
40
  const _00_slice_1 = require("../core/steps/all/static-slicing/00-slice");
41
+ const doc_repl_1 = require("./doc-util/doc-repl");
41
42
  (0, doc_query_1.registerQueryDocumentation)('call-context', {
42
43
  name: 'Call-Context Query',
43
44
  type: 'active',
@@ -329,10 +330,26 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
329
330
  shortDescription: 'Returns the current configuration of flowR.',
330
331
  functionName: config_query_executor_1.executeConfigQuery.name,
331
332
  functionFile: '../queries/catalog/config-query/config-query-format.ts',
332
- // eslint-disable-next-line @typescript-eslint/require-await -- no need for async here
333
- buildExplanation: async () => {
333
+ buildExplanation: async (shell) => {
334
334
  return `
335
- 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.`;
335
+ 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.
336
+ Additionally, you can use this query to update the configuration of flowR on-the-fly (please do not rely on this mechanism it is mostly of interest for demonstrations).
337
+ ${await (0, doc_query_1.showQuery)(shell, '', [{
338
+ type: 'config',
339
+ update: {
340
+ ignoreSourceCalls: true
341
+ }
342
+ }], { showCode: false, collapseQuery: true, collapseResult: true })}
343
+
344
+ Please note that, in the repl, a special syntax starting with \`+\` (which should be autocompleted) can be used to update the configuration on the fly:
345
+
346
+ ${await (0, doc_repl_1.documentReplSession)(shell, [
347
+ {
348
+ command: ':query @config +solver.slicer.threshold=10000',
349
+ description: 'Set the slicing threshold to 10,000.'
350
+ }
351
+ ])}
352
+ `;
336
353
  }
337
354
  });
338
355
  (0, doc_query_1.registerQueryDocumentation)('df-shape', {
@@ -495,10 +512,8 @@ In the meantime we offer several properties to overwrite the default behavior (e
495
512
  ${await (0, doc_query_1.showQuery)(shell, longerCode, [{
496
513
  type: 'dependencies',
497
514
  ignoreDefaultFunctions: true,
515
+ enabledCategories: ['library'],
498
516
  libraryFunctions: [{ package: 'base', name: 'print', argIdx: 0, argName: 'library', resolveValue: true }],
499
- sourceFunctions: [],
500
- readFunctions: [],
501
- writeFunctions: []
502
517
  }], { showCode: false, collapseQuery: false, collapseResult: true })}
503
518
 
504
519
  Here, \`resolveValue\` tells the dependency query to resolve the value of this argument in case it is not a constant.
@@ -651,7 +666,7 @@ ${(0, doc_query_1.tocForQueryType)('virtual')}
651
666
 
652
667
  <summary>Detailed Query Format (Automatically Generated)</summary>
653
668
 
654
- Although it is probably better to consult the detailed explanations below, if you want to have a look at the scehma, here is its description:
669
+ Although it is probably better to consult the detailed explanations below, if you want to have a look at the schema, here is its description:
655
670
 
656
671
  ${(0, schema_1.describeSchema)((0, query_1.QueriesSchema)(), ansi_1.markdownFormatter)}
657
672
 
@@ -5,22 +5,30 @@ const linter_rules_1 = require("./linter-rules");
5
5
  const flowr_search_executor_1 = require("../search/flowr-search-executor");
6
6
  const objects_1 = require("../util/objects");
7
7
  function executeLintingRule(ruleName, input, lintingRuleConfig) {
8
- const rule = linter_rules_1.LintingRules[ruleName];
9
- const fullConfig = (0, objects_1.deepMergeObject)(rule.info.defaultConfig, lintingRuleConfig);
10
- const ruleSearch = rule.createSearch(fullConfig, input);
11
- const searchStart = Date.now();
12
- const searchResult = (0, flowr_search_executor_1.runSearch)(ruleSearch, input);
13
- const searchTime = Date.now() - searchStart;
14
- const processStart = Date.now();
15
- const result = rule.processSearchResult(searchResult, fullConfig, input);
16
- const processTime = Date.now() - processStart;
17
- return {
18
- ...result,
19
- '.meta': {
20
- ...result['.meta'],
21
- searchTimeMs: searchTime,
22
- processTimeMs: processTime
23
- }
24
- };
8
+ try {
9
+ const rule = linter_rules_1.LintingRules[ruleName];
10
+ const fullConfig = (0, objects_1.deepMergeObject)(rule.info.defaultConfig, lintingRuleConfig);
11
+ const ruleSearch = rule.createSearch(fullConfig, input);
12
+ const searchStart = Date.now();
13
+ const searchResult = (0, flowr_search_executor_1.runSearch)(ruleSearch, input);
14
+ const searchTime = Date.now() - searchStart;
15
+ const processStart = Date.now();
16
+ const result = rule.processSearchResult(searchResult, fullConfig, input);
17
+ const processTime = Date.now() - processStart;
18
+ return {
19
+ ...result,
20
+ '.meta': {
21
+ ...result['.meta'],
22
+ searchTimeMs: searchTime,
23
+ processTimeMs: processTime
24
+ }
25
+ };
26
+ }
27
+ catch (e) {
28
+ const msg = typeof e === 'string' ? e : e instanceof Error ? e.message : JSON.stringify(e);
29
+ return {
30
+ error: msg
31
+ };
32
+ }
25
33
  }
26
34
  //# sourceMappingURL=linter-executor.js.map
@@ -105,13 +105,22 @@ export interface ConfiguredLintingRule<Name extends LintingRuleNames = LintingRu
105
105
  readonly name: Name;
106
106
  readonly config: DeepPartial<LintingRuleConfig<Name>>;
107
107
  }
108
- export interface LintingResults<Name extends LintingRuleNames> {
108
+ /**
109
+ * For when a linting rule throws an error during execution
110
+ */
111
+ export interface LintingResultsError {
112
+ readonly error: string;
113
+ }
114
+ export interface LintingResultsSuccess<Name extends LintingRuleNames> {
109
115
  results: LintingRuleResult<Name>[];
110
116
  '.meta': LintingRuleMetadata<Name> & {
111
117
  readonly searchTimeMs: number;
112
118
  readonly processTimeMs: number;
113
119
  };
114
120
  }
121
+ export declare function isLintingResultsError<Name extends LintingRuleNames>(o: LintingResults<Name>): o is LintingResultsError;
122
+ export declare function isLintingResultsSuccess<Name extends LintingRuleNames>(o: LintingResults<Name>): o is LintingResultsSuccess<Name>;
123
+ export type LintingResults<Name extends LintingRuleNames> = LintingResultsSuccess<Name> | LintingResultsError;
115
124
  export declare enum LintingResultCertainty {
116
125
  /**
117
126
  * The linting rule cannot say for sure whether the result is correct or not.
@@ -1,6 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LintingPrettyPrintContext = exports.LintingRuleCertainty = exports.LintingResultCertainty = void 0;
4
+ exports.isLintingResultsError = isLintingResultsError;
5
+ exports.isLintingResultsSuccess = isLintingResultsSuccess;
6
+ function isLintingResultsError(o) {
7
+ return 'error' in o;
8
+ }
9
+ function isLintingResultsSuccess(o) {
10
+ return 'results' in o;
11
+ }
4
12
  var LintingResultCertainty;
5
13
  (function (LintingResultCertainty) {
6
14
  /**
@@ -173,6 +173,7 @@ export declare const LintingRules: {
173
173
  readonly tags: readonly [import("./linter-tags").LintingRuleTag.Style, import("./linter-tags").LintingRuleTag.QuickFix];
174
174
  readonly defaultConfig: {
175
175
  readonly caseing: "auto";
176
+ readonly ignoreNonAlpha: true;
176
177
  };
177
178
  };
178
179
  };
@@ -52,8 +52,7 @@ const PathFunctions = {
52
52
  'file.path': (df, vtx, config) => {
53
53
  const fsep = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, df, vtx, undefined, 'fsep', true);
54
54
  // in the future we can access `.Platform$file.sep` here
55
- const v = fsep?.values();
56
- const sepValues = v ? [...v].flatMap(s => [...s].filter(assert_1.isNotUndefined)) : [path_1.default.sep];
55
+ const sepValues = new Array(...fsep?.values()?.flatMap(s => [...s].filter(assert_1.isNotUndefined)) ?? [path_1.default.sep]);
57
56
  if (sepValues.some(s => s === dependencies_query_format_1.Unknown || (0, assert_1.isUndefined)(s))) {
58
57
  // if we have no fsep, we cannot construct a path
59
58
  return undefined;
@@ -119,19 +118,19 @@ exports.ABSOLUTE_PATH = {
119
118
  }
120
119
  else if ((0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.QueryData)) {
121
120
  const result = queryResults[(0, search_enrichers_1.enrichmentContent)(element, search_enrichers_1.Enrichment.QueryData).query];
122
- const mappedStrings = result.readData.filter(r => r.source !== dependencies_query_format_1.Unknown && (0, strings_1.isAbsolutePath)(r.source, regex)).map(r => {
121
+ const mappedStrings = result.read.filter(r => r.value !== undefined && r.value !== dependencies_query_format_1.Unknown && (0, strings_1.isAbsolutePath)(r.value, regex)).map(r => {
123
122
  const elem = data.normalize.idMap.get(r.nodeId);
124
123
  return {
125
124
  certainty: linter_format_1.LintingResultCertainty.Certain,
126
- filePath: r.source,
125
+ filePath: r.value,
127
126
  range: elem?.info.fullRange ?? elem?.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
128
- quickFix: buildQuickFix(elem, r.source, wd)
127
+ quickFix: buildQuickFix(elem, r.value, wd)
129
128
  };
130
129
  });
131
130
  if (mappedStrings.length > 0) {
132
131
  return mappedStrings;
133
132
  }
134
- else if (result.readData.every(r => r.source !== dependencies_query_format_1.Unknown)) {
133
+ else if (result.read.every(r => r.value !== dependencies_query_format_1.Unknown)) {
135
134
  // if we have no absolute paths, but all paths are known, we can return an empty array
136
135
  return [];
137
136
  }
@@ -145,7 +144,8 @@ exports.ABSOLUTE_PATH = {
145
144
  return strings.filter(s => (0, strings_1.isAbsolutePath)(s, regex)).map(str => ({
146
145
  certainty: linter_format_1.LintingResultCertainty.Uncertain,
147
146
  filePath: str,
148
- range: node.info.fullRange ?? node.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1)
147
+ range: node.info.fullRange ?? node.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
148
+ quickFix: undefined
149
149
  }));
150
150
  }
151
151
  }
@@ -159,7 +159,7 @@ exports.ABSOLUTE_PATH = {
159
159
  },
160
160
  prettyPrint: {
161
161
  [linter_format_1.LintingPrettyPrintContext.Query]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)}`,
162
- [linter_format_1.LintingPrettyPrintContext.Full]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)} is not absolute`
162
+ [linter_format_1.LintingPrettyPrintContext.Full]: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)} is absolute`
163
163
  },
164
164
  info: {
165
165
  name: 'Absolute Paths',
@@ -42,7 +42,7 @@ exports.DATA_FRAME_ACCESS_VALIDATION = {
42
42
  }
43
43
  accesses.push(access);
44
44
  }
45
- const operations = [...accessOperations.entries()].flatMap(([, operations]) => operations);
45
+ const operations = accessOperations.entries().flatMap(([, operations]) => operations).toArray();
46
46
  const metadata = {
47
47
  numOperations: accessOperations.size,
48
48
  numAccesses: operations.length,