]>
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.
23 /* istanbul ignore next */
24 function getId(segment
) { // eslint-disable-line jsdoc/require-jsdoc
25 return segment
.id
+ (segment
.reachable
? "" : "!");
28 //------------------------------------------------------------------------------
30 //------------------------------------------------------------------------------
35 * A flag that debug dumping is enabled or not.
38 enabled
: debug
.enabled
,
41 * Dumps given objects.
42 * @param {...any} args objects to dump.
48 * Dumps the current analyzing state.
49 * @param {ASTNode} node A node to dump.
50 * @param {CodePathState} state A state to dump.
51 * @param {boolean} leaving A flag whether or not it's leaving
54 dumpState
: !debug
.enabled
? debug
: /* istanbul ignore next */ function(node
, state
, leaving
) {
55 for (let i
= 0; i
< state
.currentSegments
.length
; ++i
) {
56 const segInternal
= state
.currentSegments
[i
].internal;
59 segInternal
.exitNodes
.push(node
);
61 segInternal
.nodes
.push(node
);
66 `${state.currentSegments.map(getId).join(",")})`,
67 `${node.type}${leaving ? ":exit" : ""}`
72 * Dumps a DOT code of a given code path.
73 * The DOT code can be visualized with Graphvis.
74 * @param {CodePath} codePath A code path to dump.
76 * @see http://www.graphviz.org
77 * @see http://www.webgraphviz.com
79 dumpDot
: !debug
.enabled
? debug
: /* istanbul ignore next */ function(codePath
) {
83 "node[shape=box,style=\"rounded,filled\",fillcolor=white];\n" +
84 "initial[label=\"\",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];\n";
86 if (codePath
.returnedSegments
.length
> 0) {
87 text
+= "final[label=\"\",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];\n";
89 if (codePath
.thrownSegments
.length
> 0) {
90 text
+= "thrown[label=\"✘\",shape=circle,width=0.3,height=0.3,fixedsize];\n";
93 const traceMap
= Object
.create(null);
94 const arrows
= this.makeDotArrows(codePath
, traceMap
);
96 for (const id
in traceMap
) { // eslint-disable-line guard-for-in
97 const segment
= traceMap
[id
];
101 if (segment
.reachable
) {
104 text
+= "style=\"rounded,dashed,filled\",fillcolor=\"#FF9800\",label=\"<<unreachable>>\\n";
107 if (segment
.internal.nodes
.length
> 0 || segment
.internal.exitNodes
.length
> 0) {
109 segment
.internal.nodes
.map(node
=> {
111 case "Identifier": return `${node.type} (${node.name})`;
112 case "Literal": return `${node.type} (${node.value})`;
113 default: return node
.type
;
116 segment
.internal.exitNodes
.map(node
=> {
118 case "Identifier": return `${node.type}:exit (${node.name})`;
119 case "Literal": return `${node.type}:exit (${node.value})`;
120 default: return `${node.type}:exit`;
131 text
+= `${arrows}\n`;
137 * Makes a DOT code of a given code path.
138 * The DOT code can be visualized with Graphvis.
139 * @param {CodePath} codePath A code path to make DOT.
140 * @param {Object} traceMap Optional. A map to check whether or not segments had been done.
141 * @returns {string} A DOT code of the code path.
143 makeDotArrows(codePath
, traceMap
) {
144 const stack
= [[codePath
.initialSegment
, 0]];
145 const done
= traceMap
|| Object
.create(null);
146 let lastId
= codePath
.initialSegment
.id
;
147 let text
= `initial->${codePath.initialSegment.id}`;
149 while (stack
.length
> 0) {
150 const item
= stack
.pop();
151 const segment
= item
[0];
152 const index
= item
[1];
154 if (done
[segment
.id
] && index
=== 0) {
157 done
[segment
.id
] = segment
;
159 const nextSegment
= segment
.allNextSegments
[index
];
165 if (lastId
=== segment
.id
) {
166 text
+= `->${nextSegment.id}`;
168 text
+= `;\n${segment.id}->${nextSegment.id}`;
170 lastId
= nextSegment
.id
;
172 stack
.unshift([segment
, 1 + index
]);
173 stack
.push([nextSegment
, 0]);
176 codePath
.returnedSegments
.forEach(finalSegment
=> {
177 if (lastId
=== finalSegment
.id
) {
180 text
+= `;\n${finalSegment.id}->final`;
185 codePath
.thrownSegments
.forEach(finalSegment
=> {
186 if (lastId
=== finalSegment
.id
) {
189 text
+= `;\n${finalSegment.id}->thrown`;