]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/linter/code-path-analysis/debug-helpers.js
2 * @fileoverview Helpers to debug for code path analysis.
3 * @author Toru Nagashima
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const debug
= require("debug")("eslint:code-path");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
19 * Gets id of a given segment.
20 * @param {CodePathSegment} segment A segment to get.
21 * @returns {string} Id of the segment.
24 function getId(segment
) { // eslint-disable-line jsdoc/require-jsdoc -- Ignoring
25 return segment
.id
+ (segment
.reachable
? "" : "!");
29 * Get string for the given node and operation.
30 * @param {ASTNode} node The node to convert.
31 * @param {"enter" | "exit" | undefined} label The operation label.
32 * @returns {string} The string representation.
34 function nodeToString(node
, label
) {
35 const suffix
= label
? `:${label}` : "";
38 case "Identifier": return `${node.type}${suffix} (${node.name})`;
39 case "Literal": return `${node.type}${suffix} (${node.value})`;
40 default: return `${node.type}${suffix}`;
44 //------------------------------------------------------------------------------
46 //------------------------------------------------------------------------------
51 * A flag that debug dumping is enabled or not.
54 enabled
: debug
.enabled
,
57 * Dumps given objects.
58 * @param {...any} args objects to dump.
64 * Dumps the current analyzing state.
65 * @param {ASTNode} node A node to dump.
66 * @param {CodePathState} state A state to dump.
67 * @param {boolean} leaving A flag whether or not it's leaving
70 dumpState
: !debug
.enabled
? debug
: /* c8 ignore next */ function(node
, state
, leaving
) {
71 for (let i
= 0; i
< state
.currentSegments
.length
; ++i
) {
72 const segInternal
= state
.currentSegments
[i
].internal;
75 const last
= segInternal
.nodes
.length
- 1;
77 if (last
>= 0 && segInternal
.nodes
[last
] === nodeToString(node
, "enter")) {
78 segInternal
.nodes
[last
] = nodeToString(node
, void 0);
80 segInternal
.nodes
.push(nodeToString(node
, "exit"));
83 segInternal
.nodes
.push(nodeToString(node
, "enter"));
88 `${state.currentSegments.map(getId).join(",")})`,
89 `${node.type}${leaving ? ":exit" : ""}`
94 * Dumps a DOT code of a given code path.
95 * The DOT code can be visualized with Graphvis.
96 * @param {CodePath} codePath A code path to dump.
98 * @see http://www.graphviz.org
99 * @see http://www.webgraphviz.com
101 dumpDot
: !debug
.enabled
? debug
: /* c8 ignore next */ function(codePath
) {
105 "node[shape=box,style=\"rounded,filled\",fillcolor=white];\n" +
106 "initial[label=\"\",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];\n";
108 if (codePath
.returnedSegments
.length
> 0) {
109 text
+= "final[label=\"\",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];\n";
111 if (codePath
.thrownSegments
.length
> 0) {
112 text
+= "thrown[label=\"✘\",shape=circle,width=0.3,height=0.3,fixedsize];\n";
115 const traceMap
= Object
.create(null);
116 const arrows
= this.makeDotArrows(codePath
, traceMap
);
118 for (const id
in traceMap
) { // eslint-disable-line guard-for-in -- Want ability to traverse prototype
119 const segment
= traceMap
[id
];
123 if (segment
.reachable
) {
126 text
+= "style=\"rounded,dashed,filled\",fillcolor=\"#FF9800\",label=\"<<unreachable>>\\n";
129 if (segment
.internal.nodes
.length
> 0) {
130 text
+= segment
.internal.nodes
.join("\\n");
138 text
+= `${arrows}\n`;
144 * Makes a DOT code of a given code path.
145 * The DOT code can be visualized with Graphvis.
146 * @param {CodePath} codePath A code path to make DOT.
147 * @param {Object} traceMap Optional. A map to check whether or not segments had been done.
148 * @returns {string} A DOT code of the code path.
150 makeDotArrows(codePath
, traceMap
) {
151 const stack
= [[codePath
.initialSegment
, 0]];
152 const done
= traceMap
|| Object
.create(null);
153 let lastId
= codePath
.initialSegment
.id
;
154 let text
= `initial->${codePath.initialSegment.id}`;
156 while (stack
.length
> 0) {
157 const item
= stack
.pop();
158 const segment
= item
[0];
159 const index
= item
[1];
161 if (done
[segment
.id
] && index
=== 0) {
164 done
[segment
.id
] = segment
;
166 const nextSegment
= segment
.allNextSegments
[index
];
172 if (lastId
=== segment
.id
) {
173 text
+= `->${nextSegment.id}`;
175 text
+= `;\n${segment.id}->${nextSegment.id}`;
177 lastId
= nextSegment
.id
;
179 stack
.unshift([segment
, 1 + index
]);
180 stack
.push([nextSegment
, 0]);
183 codePath
.returnedSegments
.forEach(finalSegment
=> {
184 if (lastId
=== finalSegment
.id
) {
187 text
+= `;\n${finalSegment.id}->final`;
192 codePath
.thrownSegments
.forEach(finalSegment
=> {
193 if (lastId
=== finalSegment
.id
) {
196 text
+= `;\n${finalSegment.id}->thrown`;