@eagleoutice/flowr 2.2.2 → 2.2.3

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 (68) hide show
  1. package/cli/repl/commands/repl-dataflow.js +7 -4
  2. package/cli/repl/commands/repl-parse.js +43 -2
  3. package/cli/repl/print-version.d.ts +1 -0
  4. package/cli/repl/print-version.js +7 -2
  5. package/cli/repl/server/connection.js +10 -8
  6. package/core/pipeline-executor.d.ts +6 -0
  7. package/core/pipeline-executor.js +8 -0
  8. package/core/print/dataflow-printer.js +3 -0
  9. package/core/steps/all/core/01-parse-tree-sitter.d.ts +7 -0
  10. package/core/steps/pipeline/default-pipelines.d.ts +57 -47
  11. package/core/steps/pipeline/default-pipelines.js +23 -2
  12. package/core/steps/pipeline/pipeline.d.ts +1 -1
  13. package/core/steps/pipeline/pipeline.js +1 -1
  14. package/core/steps/pipeline-step.d.ts +1 -3
  15. package/dataflow/environments/resolve-by-name.d.ts +3 -2
  16. package/dataflow/environments/resolve-by-name.js +4 -4
  17. package/dataflow/extractor.d.ts +10 -0
  18. package/dataflow/extractor.js +10 -0
  19. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
  20. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +20 -4
  21. package/documentation/doc-util/doc-dfg.d.ts +5 -3
  22. package/documentation/doc-util/doc-dfg.js +10 -8
  23. package/documentation/doc-util/doc-files.d.ts +1 -1
  24. package/documentation/doc-util/doc-files.js +1 -1
  25. package/documentation/doc-util/doc-normalized-ast.d.ts +2 -1
  26. package/documentation/doc-util/doc-normalized-ast.js +4 -5
  27. package/documentation/doc-util/doc-repl.d.ts +6 -2
  28. package/documentation/doc-util/doc-repl.js +10 -6
  29. package/documentation/doc-util/doc-structure.d.ts +1 -1
  30. package/documentation/doc-util/doc-types.d.ts +7 -5
  31. package/documentation/doc-util/doc-types.js +15 -10
  32. package/documentation/index.d.ts +9 -0
  33. package/documentation/index.js +26 -0
  34. package/documentation/print-capabilities-markdown.js +105 -19
  35. package/documentation/print-core-wiki.d.ts +1 -0
  36. package/documentation/print-core-wiki.js +406 -0
  37. package/documentation/print-dataflow-graph-wiki.js +27 -27
  38. package/documentation/print-interface-wiki.js +1 -1
  39. package/documentation/print-linting-and-testing-wiki.js +26 -8
  40. package/documentation/print-normalized-ast-wiki.js +22 -17
  41. package/documentation/print-query-wiki.js +7 -7
  42. package/documentation/print-search-wiki.js +2 -1
  43. package/package.json +3 -2
  44. package/queries/catalog/happens-before-query/happens-before-query-format.js +1 -1
  45. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +1 -1
  46. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +1 -1
  47. package/queries/catalog/search-query/search-query-format.js +1 -1
  48. package/r-bridge/data/data.d.ts +48 -7
  49. package/r-bridge/data/data.js +62 -8
  50. package/r-bridge/data/types.d.ts +7 -1
  51. package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +2 -0
  52. package/r-bridge/lang-4.x/ast/model/processing/node-id.js +2 -5
  53. package/r-bridge/lang-4.x/ast/parser/json/format.d.ts +6 -0
  54. package/r-bridge/lang-4.x/ast/parser/json/format.js +6 -0
  55. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +13 -2
  56. package/r-bridge/lang-4.x/ast/parser/json/parser.js +19 -3
  57. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.d.ts +3 -0
  58. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +3 -0
  59. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +6 -1
  60. package/r-bridge/parser.d.ts +10 -0
  61. package/r-bridge/parser.js +26 -2
  62. package/search/flowr-search-builder.d.ts +1 -2
  63. package/search/flowr-search-builder.js +1 -3
  64. package/util/mermaid/dfg.d.ts +3 -0
  65. package/util/mermaid/dfg.js +24 -8
  66. package/util/strings.d.ts +9 -0
  67. package/util/strings.js +14 -0
  68. package/util/version.js +1 -1
@@ -21,6 +21,8 @@ const log_1 = require("../../../../../../util/log");
21
21
  const fs_1 = __importDefault(require("fs"));
22
22
  const parser_1 = require("../../../../../../r-bridge/lang-4.x/ast/parser/json/parser");
23
23
  const shell_executor_1 = require("../../../../../../r-bridge/shell-executor");
24
+ const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
25
+ const assert_1 = require("../../../../../../util/assert");
24
26
  let sourceProvider = (0, retriever_1.requestProviderFromFile)();
25
27
  function setSourceProvider(provider) {
26
28
  sourceProvider = provider;
@@ -29,14 +31,28 @@ function processSourceCall(name, args, rootId, data, config) {
29
31
  const information = config.includeFunctionCall ?
30
32
  (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information
31
33
  : (0, info_1.initializeCleanDataflowInformation)(rootId, data);
32
- const sourceFile = args[0];
34
+ const sourceFileArgument = args[0];
33
35
  if (!config.forceFollow && (0, config_1.getConfig)().ignoreSourceCalls) {
34
- (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping source call ${JSON.stringify(sourceFile)} (disabled in config file)`);
36
+ (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping source call ${JSON.stringify(sourceFileArgument)} (disabled in config file)`);
35
37
  information.graph.markIdForUnknownSideEffects(rootId);
36
38
  return information;
37
39
  }
38
- if (sourceFile !== r_function_call_1.EmptyArgument && sourceFile?.value?.type === type_1.RType.String) {
39
- const path = (0, retriever_1.removeRQuotes)(sourceFile.lexeme);
40
+ let sourceFile;
41
+ if (sourceFileArgument !== r_function_call_1.EmptyArgument && sourceFileArgument?.value?.type === type_1.RType.String) {
42
+ sourceFile = [(0, retriever_1.removeRQuotes)(sourceFileArgument.lexeme)];
43
+ }
44
+ else if (sourceFileArgument !== r_function_call_1.EmptyArgument) {
45
+ sourceFile = (0, resolve_by_name_1.resolveValueOfVariable)(sourceFileArgument.value?.lexeme, data.environment, data.completeAst.idMap)?.map(x => {
46
+ if (typeof x === 'object' && x && 'str' in x) {
47
+ return x.str;
48
+ }
49
+ else {
50
+ return undefined;
51
+ }
52
+ }).filter(assert_1.isNotUndefined);
53
+ }
54
+ if (sourceFile && sourceFile.length === 1) {
55
+ const path = (0, retriever_1.removeRQuotes)(sourceFile[0]);
40
56
  const request = sourceProvider.createRequest(path);
41
57
  // check if the sourced file has already been dataflow analyzed, and if so, skip it
42
58
  if (data.referenceChain.includes((0, retriever_1.requestFingerprint)(request))) {
@@ -3,19 +3,21 @@ import type { RShell } from '../../r-bridge/shell';
3
3
  import type { MermaidMarkdownMark } from '../../util/mermaid/dfg';
4
4
  import { DEFAULT_DATAFLOW_PIPELINE } from '../../core/steps/pipeline/default-pipelines';
5
5
  import type { PipelineOutput } from '../../core/steps/pipeline/pipeline';
6
- export declare function printDfGraph(graph: DataflowGraph, mark?: ReadonlySet<MermaidMarkdownMark>): string;
6
+ import type { KnownParser } from '../../r-bridge/parser';
7
+ export declare function printDfGraph(graph: DataflowGraph, mark?: ReadonlySet<MermaidMarkdownMark>, simplified?: boolean): string;
7
8
  export interface PrintDataflowGraphOptions {
8
9
  readonly mark?: ReadonlySet<MermaidMarkdownMark>;
9
10
  readonly showCode?: boolean;
10
11
  readonly codeOpen?: boolean;
11
12
  readonly exposeResult?: boolean;
12
13
  readonly switchCodeAndGraph?: boolean;
14
+ readonly simplified?: boolean;
13
15
  }
14
16
  export declare function formatSideEffect(ef: UnknownSidEffect): string;
15
- export declare function printDfGraphForCode(shell: RShell, code: string, options: PrintDataflowGraphOptions & {
17
+ export declare function printDfGraphForCode(parser: KnownParser, code: string, options: PrintDataflowGraphOptions & {
16
18
  exposeResult: true;
17
19
  }): Promise<[string, PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>]>;
18
- export declare function printDfGraphForCode(shell: RShell, code: string, options?: PrintDataflowGraphOptions & {
20
+ export declare function printDfGraphForCode(parser: KnownParser, code: string, options?: PrintDataflowGraphOptions & {
19
21
  exposeResult?: false | undefined;
20
22
  }): Promise<string>;
21
23
  /** returns resolved expected df graph */
@@ -13,13 +13,15 @@ const resolve_graph_1 = require("../../dataflow/graph/resolve-graph");
13
13
  const diff_1 = require("../../dataflow/graph/diff");
14
14
  const assert_1 = require("../../util/assert");
15
15
  const time_1 = require("../../util/time");
16
- function printDfGraph(graph, mark) {
16
+ const doc_files_1 = require("./doc-files");
17
+ function printDfGraph(graph, mark, simplified = false) {
17
18
  return `
18
19
  \`\`\`mermaid
19
20
  ${(0, dfg_1.graphToMermaid)({
20
21
  graph,
21
22
  prefix: 'flowchart LR',
22
- mark
23
+ mark,
24
+ simplified
23
25
  }).string}
24
26
  \`\`\`
25
27
  `;
@@ -32,18 +34,18 @@ function formatSideEffect(ef) {
32
34
  return `${ef}`;
33
35
  }
34
36
  }
35
- async function printDfGraphForCode(shell, code, { mark, showCode = true, codeOpen = false, exposeResult, switchCodeAndGraph = false } = {}) {
37
+ async function printDfGraphForCode(parser, code, { simplified = false, mark, showCode = true, codeOpen = false, exposeResult, switchCodeAndGraph = false } = {}) {
36
38
  const now = performance.now();
37
- const result = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
38
- parser: shell,
39
+ const result = await (0, default_pipelines_1.createDataflowPipeline)(parser, {
39
40
  request: (0, retriever_1.requestFromInput)(code)
40
41
  }).allRemainingSteps();
41
42
  const duration = performance.now() - now;
42
43
  if (switchCodeAndGraph) {
43
44
  (0, assert_1.guard)(showCode, 'can not switch code and graph if code is not shown');
44
45
  }
45
- const metaInfo = `The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parse and normalize) within the generation environment.`;
46
- const dfGraph = printDfGraph(result.dataflow.graph, mark);
46
+ const metaInfo = `The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parse and normalize, using the [${parser.name}](${doc_files_1.FlowrWikiBaseRef}/Engines) engine) within the generation environment.`;
47
+ const dfGraph = printDfGraph(result.dataflow.graph, mark, simplified);
48
+ const simplyText = simplified ? '(simplified) ' : '';
47
49
  let resultText = '\n\n';
48
50
  if (showCode) {
49
51
  const codeText = `\`\`\`r
@@ -53,7 +55,7 @@ ${code}
53
55
  resultText += `
54
56
  <details${codeOpen ? ' open' : ''}>
55
57
 
56
- <summary style="color:gray">${switchCodeAndGraph ? 'Dataflow Graph of the R Code' : 'R Code of the Dataflow Graph'}</summary>
58
+ <summary style="color:gray">${switchCodeAndGraph ? `${simplyText}Dataflow Graph of the R Code` : `R Code of the ${simplyText}Dataflow Graph`}</summary>
57
59
 
58
60
  ${metaInfo} ${mark ? `The following marks are used in the graph to highlight sub-parts (uses ids): {${[...mark].join(', ')}}.` : ''}
59
61
  We encountered ${result.dataflow.graph.unknownSideEffects.size > 0 ? 'unknown side effects (with ids: ' + [...result.dataflow.graph.unknownSideEffects].map(formatSideEffect).join(', ') + ')' : 'no unknown side effects'} during the analysis.
@@ -1,7 +1,7 @@
1
1
  export declare const FlowrGithubBaseRef = "https://github.com/flowr-analysis";
2
2
  export declare const FlowrSiteBaseRef = "https://flowr-analysis.github.io/flowr";
3
3
  export declare const RemoteFlowrFilePathBaseRef = "https://github.com/flowr-analysis/flowr/tree/main/";
4
- export declare const FlowrWikiBaseRef = "https://github.com/flowr-analysis/flowr/wiki/";
4
+ export declare const FlowrWikiBaseRef = "https://github.com/flowr-analysis/flowr/wiki";
5
5
  export declare const FlowrNpmRef = "https://www.npmjs.com/package/@eagleoutice/flowr";
6
6
  export declare const FlowrDockerRef = "https://hub.docker.com/r/eagleoutice/flowr";
7
7
  export declare const FlowrCodecovRef = "https://app.codecov.io/gh/flowr-analysis/flowr";
@@ -11,7 +11,7 @@ const fs_1 = __importDefault(require("fs"));
11
11
  exports.FlowrGithubBaseRef = 'https://github.com/flowr-analysis';
12
12
  exports.FlowrSiteBaseRef = 'https://flowr-analysis.github.io/flowr';
13
13
  exports.RemoteFlowrFilePathBaseRef = `${exports.FlowrGithubBaseRef}/flowr/tree/main/`;
14
- exports.FlowrWikiBaseRef = `${exports.FlowrGithubBaseRef}/flowr/wiki/`;
14
+ exports.FlowrWikiBaseRef = `${exports.FlowrGithubBaseRef}/flowr/wiki`;
15
15
  exports.FlowrNpmRef = 'https://www.npmjs.com/package/@eagleoutice/flowr';
16
16
  exports.FlowrDockerRef = 'https://hub.docker.com/r/eagleoutice/flowr';
17
17
  exports.FlowrCodecovRef = 'https://app.codecov.io/gh/flowr-analysis/flowr';
@@ -1,11 +1,12 @@
1
1
  import type { DataflowGraph } from '../../dataflow/graph/graph';
2
2
  import type { RShell } from '../../r-bridge/shell';
3
3
  import type { RNodeWithParent } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
4
+ import type { KnownParser } from '../../r-bridge/parser';
4
5
  export declare function printNormalizedAst(ast: RNodeWithParent, prefix?: string): string;
5
6
  export interface PrintNormalizedAstOptions {
6
7
  readonly showCode?: boolean;
7
8
  readonly prefix?: string;
8
9
  }
9
- export declare function printNormalizedAstForCode(shell: RShell, code: string, { showCode, prefix }?: PrintNormalizedAstOptions): Promise<string>;
10
+ export declare function printNormalizedAstForCode(parser: KnownParser, code: string, { showCode, prefix }?: PrintNormalizedAstOptions): Promise<string>;
10
11
  /** returns resolved expected df graph */
11
12
  export declare function verifyExpectedSubgraph(shell: RShell, code: string, expectedSubgraph: DataflowGraph): Promise<DataflowGraph>;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.printNormalizedAst = printNormalizedAst;
4
4
  exports.printNormalizedAstForCode = printNormalizedAstForCode;
5
5
  exports.verifyExpectedSubgraph = verifyExpectedSubgraph;
6
- const pipeline_executor_1 = require("../../core/pipeline-executor");
7
6
  const default_pipelines_1 = require("../../core/steps/pipeline/default-pipelines");
8
7
  const retriever_1 = require("../../r-bridge/retriever");
9
8
  const decorate_1 = require("../../r-bridge/lang-4.x/ast/model/processing/decorate");
@@ -12,6 +11,7 @@ const diff_1 = require("../../dataflow/graph/diff");
12
11
  const assert_1 = require("../../util/assert");
13
12
  const ast_1 = require("../../util/mermaid/ast");
14
13
  const time_1 = require("../../util/time");
14
+ const doc_files_1 = require("./doc-files");
15
15
  function printNormalizedAst(ast, prefix = 'flowchart TD\n') {
16
16
  return `
17
17
  \`\`\`mermaid
@@ -19,14 +19,13 @@ ${(0, ast_1.normalizedAstToMermaid)(ast, prefix)}
19
19
  \`\`\`
20
20
  `;
21
21
  }
22
- async function printNormalizedAstForCode(shell, code, { showCode = true, prefix = 'flowchart TD\n' } = {}) {
22
+ async function printNormalizedAstForCode(parser, code, { showCode = true, prefix = 'flowchart TD\n' } = {}) {
23
23
  const now = performance.now();
24
- const result = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_NORMALIZE_PIPELINE, {
25
- parser: shell,
24
+ const result = await (0, default_pipelines_1.createNormalizePipeline)(parser, {
26
25
  request: (0, retriever_1.requestFromInput)(code)
27
26
  }).allRemainingSteps();
28
27
  const duration = performance.now() - now;
29
- const metaInfo = `The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing with the R&nbsp;shell) within the generation environment.`;
28
+ const metaInfo = `The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing with the [${parser.name}](${doc_files_1.FlowrWikiBaseRef}/Engines) engine) within the generation environment.`;
30
29
  return '\n\n' + printNormalizedAst(result.normalize.ast, prefix) + (showCode ? `
31
30
  <details>
32
31
 
@@ -1,13 +1,17 @@
1
- import type { RShell } from '../../r-bridge/shell';
1
+ import type { KnownParser } from '../../r-bridge/parser';
2
2
  export declare function printReplHelpAsMarkdownTable(): string;
3
3
  export interface DocumentReplSessionOptions {
4
4
  /** defaults to false and shows starting the repl */
5
5
  hideEntry?: boolean;
6
6
  /** defaults to false and allows access to the R session */
7
7
  allowRSessionAccess?: boolean;
8
+ /** defaults to false and opens the details section by default */
9
+ openOutput?: boolean;
10
+ /** additional arguments to pass to the repl */
11
+ args?: string;
8
12
  }
9
13
  export interface DocumentReplCommand {
10
14
  command: string;
11
15
  description: string;
12
16
  }
13
- export declare function documentReplSession(shell: RShell, commands: readonly DocumentReplCommand[], options?: DocumentReplSessionOptions): Promise<string>;
17
+ export declare function documentReplSession(parser: KnownParser, commands: readonly DocumentReplCommand[], options?: DocumentReplSessionOptions): Promise<string>;
@@ -10,6 +10,7 @@ const ansi_1 = require("../../util/ansi");
10
10
  const doc_docker_1 = require("./doc-docker");
11
11
  const prompt_1 = require("../../cli/repl/prompt");
12
12
  const doc_code_1 = require("./doc-code");
13
+ const print_version_1 = require("../../cli/repl/print-version");
13
14
  function printHelpForScript(script, starredVersion) {
14
15
  let base = `| **${(0, doc_cli_option_1.getReplCommand)(script[0], false, starredVersion !== undefined)}** | ${script[1].description}`;
15
16
  if (starredVersion) {
@@ -37,7 +38,7 @@ function printReplHelpAsMarkdownTable() {
37
38
  ${scriptHelp.sort().join('\n')}
38
39
  `;
39
40
  }
40
- async function documentReplSession(shell, commands, options) {
41
+ async function documentReplSession(parser, commands, options) {
41
42
  const collect = [];
42
43
  for (const command of commands) {
43
44
  const entry = { command, lines: [] };
@@ -50,11 +51,14 @@ async function documentReplSession(shell, commands, options) {
50
51
  entry.lines.push(msg);
51
52
  }
52
53
  };
53
- await (0, core_1.replProcessAnswer)(collectingOutput, command.command, shell, options?.allowRSessionAccess ?? false);
54
+ await (0, core_1.replProcessAnswer)(collectingOutput, command.command, parser, options?.allowRSessionAccess ?? false);
54
55
  collect.push(entry);
55
56
  }
56
57
  let result = '';
57
- let cache = options?.hideEntry ? '' : `docker run -it --rm ${doc_docker_1.DockerName}\n`;
58
+ let cache = options?.hideEntry ? '' : `$ docker run -it --rm ${doc_docker_1.DockerName} ${options?.args ? options?.args + ' ' : ''}# or npm run flowr ${options?.args ? '-- ' + options?.args : ''}\n`;
59
+ if (!options?.hideEntry) {
60
+ cache += await (0, print_version_1.versionReplString)(parser) + '\n';
61
+ }
58
62
  for (const { command, lines } of collect) {
59
63
  if (lines.length === 0) {
60
64
  cache += prompt_1.rawPrompt + ' ' + command.command + '\n';
@@ -62,13 +66,13 @@ async function documentReplSession(shell, commands, options) {
62
66
  }
63
67
  result += `
64
68
  ${(0, doc_code_1.codeBlock)('shell', cache + prompt_1.rawPrompt + ' ' + command.command)}
65
- <details>
69
+ <details${options?.openOutput ? ' open' : ''}>
66
70
  <summary style='color:gray'>Output</summary>
67
71
 
68
- ${command.description}
69
-
70
72
  ${(0, doc_code_1.codeBlock)('text', lines.join('\n'))}
71
73
 
74
+ ${command.description}
75
+
72
76
  </details>
73
77
 
74
78
  `;
@@ -6,7 +6,7 @@ export interface DetailsOptions {
6
6
  }
7
7
  export declare function details(title: string, content: string, { color, open, hideIfEmpty, prefixInit }?: DetailsOptions): string;
8
8
  export interface BlockOptions {
9
- readonly type: 'NOTE' | 'WARNING' | 'INFO' | 'TIP';
9
+ readonly type: 'NOTE' | 'WARNING' | 'TIP';
10
10
  readonly content: string;
11
11
  }
12
12
  export declare function block({ type, content }: BlockOptions): string;
@@ -25,22 +25,24 @@ export interface MermaidTypeReport {
25
25
  program: ts.Program;
26
26
  }
27
27
  export declare function getTypesFromFolderAsMermaid(options: GetTypesAsMermaidOption): MermaidTypeReport;
28
- export declare function implSnippet(node: TypeElementInSource | undefined, program: ts.Program, showName?: boolean, nesting?: number): string;
28
+ export declare function implSnippet(node: TypeElementInSource | undefined, program: ts.Program, showName?: boolean, nesting?: number, open?: boolean): string;
29
29
  export interface PrintHierarchyArguments {
30
30
  readonly program: ts.Program;
31
- readonly hierarchy: TypeElementInSource[];
31
+ readonly info: TypeElementInSource[];
32
32
  readonly root: string;
33
33
  readonly collapseFromNesting?: number;
34
34
  readonly initialNesting?: number;
35
35
  readonly maxDepth?: number;
36
+ readonly openTop?: boolean;
36
37
  }
37
38
  export declare const mermaidHide: string[];
38
- export declare function printHierarchy({ program, hierarchy, root, collapseFromNesting, initialNesting, maxDepth }: PrintHierarchyArguments): string;
39
+ export declare function printHierarchy({ program, info, root, collapseFromNesting, initialNesting, maxDepth, openTop }: PrintHierarchyArguments): string;
39
40
  /**
40
41
  * Create a short link to a type in the documentation
41
- * @param name - The name of the type, e.g. `MyType`, may include a container, e.g. `MyContainer::MyType` (this works with function nestings too)
42
+ * @param name - The name of the type, e.g. `MyType`, may include a container, e.g.,`MyContainer::MyType` (this works with function nestings too)
42
43
  * @param hierarchy - The hierarchy of types to search in
43
44
  * @param codeStyle - Whether to use code style for the link
45
+ * @param realNameWrapper - How to highlight the function in name in the `x::y` format?
44
46
  */
45
- export declare function shortLink(name: string, hierarchy: TypeElementInSource[], codeStyle?: boolean): string;
47
+ export declare function shortLink(name: string, hierarchy: readonly TypeElementInSource[], codeStyle?: boolean, realNameWrapper?: string): string;
46
48
  export declare function getDocumentationForType(name: string, hierarchy: TypeElementInSource[]): string;
@@ -305,33 +305,36 @@ function getTypesFromFolderAsMermaid(options) {
305
305
  }
306
306
  return getTypesFromFileAsMermaid(files, options);
307
307
  }
308
- function implSnippet(node, program, showName = true, nesting = 0) {
308
+ function implSnippet(node, program, showName = true, nesting = 0, open = false) {
309
309
  (0, assert_1.guard)(node !== undefined, 'Node must be defined => invalid change of type name?');
310
310
  const indent = ' '.repeat(nesting * 2);
311
311
  const bold = node.kind === 'interface' || node.kind === 'enum' ? '**' : '';
312
312
  const sep = node.comments ? ' \n' : '\n';
313
313
  let text = node.comments?.join('\n') ?? '';
314
+ if (text.trim() !== '') {
315
+ text = ' ' + text;
316
+ }
314
317
  const code = node.node.getFullText(program.getSourceFile(node.node.getSourceFile().fileName));
315
- text += `\n${indent}<details><summary style="color:gray">Defined at <a href="${getTypePathLink(node)}">${getTypePathLink(node, '.')}</a></summary>\n\n${(0, doc_code_1.codeBlock)('ts', code)}\n\n</details>\n`;
318
+ text += `\n<details${open ? ' open' : ''}><summary style="color:gray">Defined at <a href="${getTypePathLink(node)}">${getTypePathLink(node, '.')}</a></summary>\n\n${(0, doc_code_1.codeBlock)('ts', code)}\n\n</details>\n`;
316
319
  const init = showName ? `* ${bold}[${node.name}](${getTypePathLink(node)})${bold} ${sep}${indent}` : '';
317
320
  return ` ${indent}${showName ? init : ''} ${text.replaceAll('\t', ' ').split(/\n/g).join(`\n${indent} `)}`;
318
321
  }
319
322
  exports.mermaidHide = ['Leaf', 'Location', 'Namespace', 'Base', 'WithChildren', 'Partial', 'RAccessBase'];
320
- function printHierarchy({ program, hierarchy, root, collapseFromNesting = 1, initialNesting = 0, maxDepth = 20 }) {
323
+ function printHierarchy({ program, info, root, collapseFromNesting = 1, initialNesting = 0, maxDepth = 20, openTop }) {
321
324
  if (initialNesting > maxDepth) {
322
325
  return '';
323
326
  }
324
- const node = hierarchy.find(e => e.name === root);
327
+ const node = info.find(e => e.name === root);
325
328
  if (!node) {
326
329
  return '';
327
330
  }
328
- const thisLine = implSnippet(node, program, true, initialNesting);
331
+ const thisLine = implSnippet(node, program, true, initialNesting, initialNesting === 0 && openTop);
329
332
  const result = [];
330
333
  for (const baseType of node.extends) {
331
334
  if (exports.mermaidHide.includes(baseType)) {
332
335
  continue;
333
336
  }
334
- const res = printHierarchy({ program, hierarchy, root: baseType, collapseFromNesting, initialNesting: initialNesting + 1, maxDepth });
337
+ const res = printHierarchy({ program, info: info, root: baseType, collapseFromNesting, initialNesting: initialNesting + 1, maxDepth });
335
338
  result.push(res);
336
339
  }
337
340
  const out = result.join('\n');
@@ -358,19 +361,21 @@ function retrieveNode(name, hierarchy) {
358
361
  }
359
362
  /**
360
363
  * Create a short link to a type in the documentation
361
- * @param name - The name of the type, e.g. `MyType`, may include a container, e.g. `MyContainer::MyType` (this works with function nestings too)
364
+ * @param name - The name of the type, e.g. `MyType`, may include a container, e.g.,`MyContainer::MyType` (this works with function nestings too)
362
365
  * @param hierarchy - The hierarchy of types to search in
363
366
  * @param codeStyle - Whether to use code style for the link
367
+ * @param realNameWrapper - How to highlight the function in name in the `x::y` format?
364
368
  */
365
- function shortLink(name, hierarchy, codeStyle = true) {
369
+ function shortLink(name, hierarchy, codeStyle = true, realNameWrapper = 'b') {
366
370
  const res = retrieveNode(name, hierarchy);
367
371
  if (!res) {
372
+ console.error(`Could not find node ${name} when resolving short link!`);
368
373
  return '';
369
374
  }
370
375
  const [pkg, mainName, node] = res;
371
- const comments = node.comments?.join('\n').replace(/\\?\n|```[a-zA-Z]*|\s\s*/g, ' ').replace(/<\/?code>|`/g, '').replace(/"/g, '\'') ?? '';
376
+ const comments = node.comments?.join('\n').replace(/\\?\n|```[a-zA-Z]*|\s\s*/g, ' ').replace(/<\/?code>|`/g, '').replace(/<\/?p\/?>/g, ' ').replace(/"/g, '\'') ?? '';
372
377
  return `[${codeStyle ? '<code>' : ''}${(node.comments?.length ?? 0) > 0 ?
373
- (0, html_hover_over_1.textWithTooltip)(pkg ? `${pkg}::<b>${mainName}</b>` : mainName, comments.length > 400 ? comments.slice(0, 400) + '...' : comments) : node.name}${codeStyle ? '</code>' : ''}](${getTypePathLink(node)})`;
378
+ (0, html_hover_over_1.textWithTooltip)(pkg ? `${pkg}::<${realNameWrapper}>${mainName}</${realNameWrapper}>` : mainName, comments.length > 400 ? comments.slice(0, 400) + '...' : comments) : node.name}${codeStyle ? '</code>' : ''}](${getTypePathLink(node)})`;
374
379
  }
375
380
  function getDocumentationForType(name, hierarchy) {
376
381
  const res = retrieveNode(name, hierarchy);
@@ -0,0 +1,9 @@
1
+ export * from './print-core-wiki';
2
+ export * from './print-query-wiki';
3
+ export * from './print-search-wiki';
4
+ export * from './print-engines-wiki';
5
+ export * from './print-interface-wiki';
6
+ export * from './print-dataflow-graph-wiki';
7
+ export * from './print-normalized-ast-wiki';
8
+ export * from './print-capabilities-markdown';
9
+ export * from './print-linting-and-testing-wiki';
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./print-core-wiki"), exports);
18
+ __exportStar(require("./print-query-wiki"), exports);
19
+ __exportStar(require("./print-search-wiki"), exports);
20
+ __exportStar(require("./print-engines-wiki"), exports);
21
+ __exportStar(require("./print-interface-wiki"), exports);
22
+ __exportStar(require("./print-dataflow-graph-wiki"), exports);
23
+ __exportStar(require("./print-normalized-ast-wiki"), exports);
24
+ __exportStar(require("./print-capabilities-markdown"), exports);
25
+ __exportStar(require("./print-linting-and-testing-wiki"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -1,18 +1,81 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const data_1 = require("../r-bridge/data/data");
4
- const version_1 = require("../util/version");
5
7
  const log_1 = require("../../test/functionality/_helper/log");
8
+ const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
9
+ const strings_1 = require("../util/strings");
10
+ const doc_general_1 = require("./doc-util/doc-general");
11
+ const tree_sitter_executor_1 = require("../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor");
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const doc_structure_1 = require("./doc-util/doc-structure");
14
+ const detailedInfoFile = 'coverage/flowr-test-details.json';
15
+ function obtainDetailedInfos() {
16
+ if (!fs_1.default.existsSync(detailedInfoFile)) {
17
+ return undefined;
18
+ }
19
+ const content = fs_1.default.readFileSync(detailedInfoFile).toString();
20
+ const base = JSON.parse(content);
21
+ const out = new Map();
22
+ for (const [key, values] of base) {
23
+ out.set(key, values.map(v => ({
24
+ id: v.id,
25
+ name: v.name,
26
+ capabilities: new Set(v.capabilities),
27
+ context: new Set(v.context)
28
+ })));
29
+ }
30
+ return out;
31
+ }
6
32
  const supportedSymbolMap = new Map([
7
- ['not', ':red_circle:'],
8
- ['partially', ':large_orange_diamond:'],
9
- ['fully', ':green_square:']
33
+ ['not', '🔴'],
34
+ ['partially', '🔶'],
35
+ ['fully', '🟩']
10
36
  ]);
11
- function printSingleCapability(depth, index, capability) {
37
+ function getTestDetails(info, capability) {
38
+ if (!info.info) {
39
+ return '';
40
+ }
41
+ const totalTests = info.info.get(capability.id);
42
+ const uniqueTests = totalTests?.filter((v, i, a) => a.findIndex(t => t.id === v.id) === i);
43
+ if (!uniqueTests || uniqueTests.length === 0) {
44
+ return '';
45
+ }
46
+ const grouped = new Map();
47
+ for (const { context } of uniqueTests) {
48
+ for (const c of context) {
49
+ grouped.set(c, (grouped.get(c) ?? 0) + 1);
50
+ }
51
+ }
52
+ if (grouped.get('desugar-tree-sitter') !== undefined && grouped.get('desugar-tree-sitter') === grouped.get('desugar-shell')) {
53
+ grouped.set('desugar', grouped.get('desugar-tree-sitter') ?? 0);
54
+ grouped.delete('desugar-shell');
55
+ grouped.delete('desugar-tree-sitter');
56
+ }
57
+ grouped.delete('other'); // opinionated view on the categories
58
+ const output = grouped.get('output');
59
+ grouped.delete('output');
60
+ const testString = [`${uniqueTests.length} test${uniqueTests.length !== 1 ? 's' : ''}`];
61
+ // sort by count
62
+ const sorted = [...grouped.entries()].sort((a, b) => b[1] - a[1]);
63
+ for (const [context, count] of sorted) {
64
+ testString.push(`${context}: ${count}`);
65
+ }
66
+ if (output) {
67
+ testString.push(`and backed with output: ${output}`);
68
+ }
69
+ return ` (${testString.join(', ')})`;
70
+ }
71
+ function escapeId(id) {
72
+ return id.replace(/[^a-zA-Z0-9]/g, '_');
73
+ }
74
+ async function printSingleCapability(info, depth, index, capability) {
12
75
  const indent = ' '.repeat(depth);
13
76
  const indexStr = index.toString().padStart(2, ' ');
14
77
  const nextLineIndent = ' '.repeat(depth + indexStr.length);
15
- const mainLine = `${indent}${indexStr}. **${capability.name}** (<a id='${capability.id}'>\`${capability.id}\`</a>)`;
78
+ const mainLine = `${indent}${indexStr}. <a id='${capability.id}'></a>**${capability.name}** <a href="#${escapeId(capability.id)}">🔗</a>${getTestDetails(info, capability)}`;
16
79
  let nextLine = '';
17
80
  if (capability.supported) {
18
81
  nextLine += `${supportedSymbolMap.get(capability.supported)} `;
@@ -20,43 +83,66 @@ function printSingleCapability(depth, index, capability) {
20
83
  if (capability.description) {
21
84
  nextLine += capability.description;
22
85
  }
23
- if (capability.note) {
24
- nextLine += `\\\n${nextLineIndent}_${capability.note}_`;
86
+ if (capability.url) {
87
+ nextLine += '\\\nSee ' + (0, strings_1.joinWithLast)(capability.url.map(({ name, href }) => `[${name}](${href})`)) + ' for more info.';
88
+ }
89
+ nextLine += ' Internal ID: `' + capability.id + '`';
90
+ if (capability.example) {
91
+ nextLine += `\n${(0, doc_general_1.prefixLines)(typeof capability.example === 'string' ? capability.example : await capability.example(info.parser), nextLineIndent + '> ')}`;
25
92
  }
26
93
  return nextLine ? `${mainLine}\\\n${nextLineIndent}${nextLine}` : mainLine;
27
94
  }
28
- function printAsMarkdown(capabilities, depth = 0, lines = []) {
95
+ async function printAsMarkdown(info, capabilities, depth = 0, lines = []) {
29
96
  for (let i = 0; i < capabilities.length; i++) {
30
97
  const capability = capabilities[i];
31
- const result = printSingleCapability(depth, i + 1, capability);
98
+ const result = await printSingleCapability(info, depth, i + 1, capability);
32
99
  lines.push(result);
33
100
  if (capability.capabilities) {
34
- printAsMarkdown(capability.capabilities, depth + 1, lines);
101
+ await printAsMarkdown(info, capability.capabilities, depth + 1, lines);
35
102
  }
36
103
  }
37
104
  return lines.join('\n');
38
105
  }
39
106
  function getPreamble() {
40
- const currentDateAndTime = new Date().toISOString().replace('T', ', ').replace(/\.\d+Z$/, ' UTC');
41
- const shortenFilename = module.filename.replace(/^.*src\//, 'src/');
42
- return `_This document was generated from '${shortenFilename}' on ${currentDateAndTime} summarizing flowR's current capabilities (v${(0, version_1.flowrVersion)().format()})._
107
+ return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'current capabilities' })}
43
108
 
44
- The code-font behind each capability name is a link to the capability's id. This id can be used to reference the capability in a labeled test within flowR.
109
+ Each capability has an id that can be used to link to it (use the link symbol to get a direct link to the capability).
110
+ The internal id is also mentioned in the capability description. This id can be used to reference the capability in a labeled test within flowR.
45
111
  Besides, we use colored bullets like this:
46
112
 
47
113
  | <!-- --> | <!-- --> |
48
114
  | ---------------------- | ----------------------------------------------------- |
49
- | :green_square: | _flowR_ is capable of handling this feature fully |
50
- | :large_orange_diamond: | _flowR_ is capable of handling this feature partially |
51
- | :red_circle: | _flowR_ is not capable of handling this feature |
115
+ | ${supportedSymbolMap.get('fully')} | _flowR_ is capable of handling this feature _fully_ |
116
+ | ${supportedSymbolMap.get('partially')} | _flowR_ is capable of handling this feature _partially_ |
117
+ | ${supportedSymbolMap.get('not')} | _flowR_ is _not_ capable of handling this feature |
52
118
 
53
119
  :cloud: This could be a feature diagram... :cloud:
54
120
 
121
+ ${(0, doc_structure_1.block)({
122
+ type: 'NOTE',
123
+ content: `
124
+ The capabilities are a qualitative measure of the features that flowR can handle.
125
+ Statements like "flowR can fully handle 50/80 capabilities" are discouraged as the capabilities may have a vastly different granularity.
126
+ Please prefer using a statement like "flowR has only partial support for feature 'XY'" (or simply reference this document) within the flowR sources.
127
+ `
128
+ })}
55
129
  `;
56
130
  }
131
+ async function print(parser) {
132
+ /* check if the detailed test data is available */
133
+ if (!fs_1.default.existsSync(detailedInfoFile)) {
134
+ console.warn('\x1b[31mNo detailed test data available. Run the full tests (npm run test-full) to generate it.\x1b[m');
135
+ }
136
+ return getPreamble() + await printAsMarkdown({ parser, info: obtainDetailedInfos() }, data_1.flowrCapabilities.capabilities);
137
+ }
57
138
  /** if we run this script, we want a Markdown representation of the capabilities */
58
139
  if (require.main === module) {
59
140
  (0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
60
- console.log(getPreamble() + printAsMarkdown(data_1.flowrCapabilities.capabilities));
141
+ void tree_sitter_executor_1.TreeSitterExecutor.initTreeSitter().then(() => {
142
+ const parser = new tree_sitter_executor_1.TreeSitterExecutor();
143
+ void print(parser).then(str => {
144
+ console.log(str);
145
+ });
146
+ });
61
147
  }
62
148
  //# sourceMappingURL=print-capabilities-markdown.js.map
@@ -0,0 +1 @@
1
+ export {};