or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context.mdfile-writing.mdindex.mdtree-traversal.mdxml-generation.md
tile.json

tree-traversal.mddocs/

0

# Tree Traversal

1

2

Tree traversal system in Istanbul Lib Report implements the visitor pattern for walking coverage trees and generating reports with different organizational strategies. The system provides flexible navigation through coverage data with support for custom processing at each node.

3

4

## Capabilities

5

6

### Visitor Pattern

7

8

The core visitor implementation allows custom processing during tree traversal with specific callbacks for different node types and traversal phases.

9

10

```javascript { .api }

11

/**

12

* Visitor for traversing coverage trees with custom callbacks

13

*/

14

class Visitor {

15

/**

16

* Create a visitor with delegate methods

17

* @param {Object} delegate - Partial visitor implementing methods of interest

18

*/

19

constructor(delegate);

20

21

/**

22

* Called before traversal begins

23

* @param {Object} root - Root node of the tree

24

* @param {Object} state - Optional state passed around during traversal

25

*/

26

onStart(root, state);

27

28

/**

29

* Called for every summary node during traversal

30

* @param {Object} node - Current summary node

31

* @param {Object} state - Optional state passed around during traversal

32

*/

33

onSummary(node, state);

34

35

/**

36

* Called for every detail node during traversal

37

* @param {Object} node - Current detail node

38

* @param {Object} state - Optional state passed around during traversal

39

*/

40

onDetail(node, state);

41

42

/**

43

* Called after all children have been visited for a summary node

44

* @param {Object} node - Current summary node

45

* @param {Object} state - Optional state passed around during traversal

46

*/

47

onSummaryEnd(node, state);

48

49

/**

50

* Called after traversal ends

51

* @param {Object} root - Root node of the tree

52

* @param {Object} state - Optional state passed around during traversal

53

*/

54

onEnd(root, state);

55

}

56

```

57

58

**Usage Example:**

59

60

```javascript

61

const visitor = new Visitor({

62

onStart(root, state) {

63

console.log('Starting traversal');

64

state.fileCount = 0;

65

},

66

67

onDetail(node, state) {

68

state.fileCount++;

69

const summary = node.getCoverageSummary();

70

console.log(`File: ${node.getQualifiedName()}`);

71

console.log(` Statements: ${summary.statements.pct}%`);

72

},

73

74

onEnd(root, state) {

75

console.log(`Processed ${state.fileCount} files`);

76

}

77

});

78

79

// Use with tree

80

tree.visit(visitor, {});

81

```

82

83

### Composite Visitor

84

85

Allows combining multiple visitors to process a tree with multiple different operations in a single traversal.

86

87

```javascript { .api }

88

/**

89

* Composite visitor that delegates to multiple visitors

90

*/

91

class CompositeVisitor extends Visitor {

92

/**

93

* Create a composite visitor

94

* @param {Array|Object} visitors - Array of visitors or single visitor

95

*/

96

constructor(visitors);

97

}

98

```

99

100

**Usage Example:**

101

102

```javascript

103

const summaryVisitor = {

104

onSummary(node) {

105

console.log(`Summary: ${node.getQualifiedName()}`);

106

}

107

};

108

109

const detailVisitor = {

110

onDetail(node) {

111

console.log(`Detail: ${node.getQualifiedName()}`);

112

}

113

};

114

115

const composite = new CompositeVisitor([summaryVisitor, detailVisitor]);

116

tree.visit(composite);

117

```

118

119

### Base Node

120

121

Abstract base class for tree nodes providing common navigation and traversal methods.

122

123

```javascript { .api }

124

/**

125

* Base class for tree nodes

126

*/

127

class BaseNode {

128

/**

129

* Check if this node is the root of the tree

130

* @returns {boolean} True if this is the root node

131

*/

132

isRoot();

133

134

/**

135

* Visit all nodes depth-first from this node down

136

* @param {Visitor} visitor - Visitor called during tree traversal

137

* @param {Object} [state] - Optional state passed around during traversal

138

*/

139

visit(visitor, state);

140

141

/**

142

* Check if this is a summary node (abstract)

143

* @returns {boolean} True if this is a summary node

144

*/

145

isSummary();

146

147

/**

148

* Get the parent node (abstract)

149

* @returns {BaseNode|null} Parent node or null if root

150

*/

151

getParent();

152

153

/**

154

* Get child nodes (abstract)

155

* @returns {Array<BaseNode>} Array of child nodes

156

*/

157

getChildren();

158

}

159

```

160

161

### Base Tree

162

163

Abstract base class for coverage trees providing tree-wide traversal operations.

164

165

```javascript { .api }

166

/**

167

* Abstract base class for a coverage tree

168

*/

169

class BaseTree {

170

/**

171

* Create a tree with the specified root node

172

* @param {BaseNode} root - Root node of the tree

173

*/

174

constructor(root);

175

176

/**

177

* Returns the root node of the tree

178

* @returns {BaseNode} Root node

179

*/

180

getRoot();

181

182

/**

183

* Visits the tree depth-first with the supplied partial visitor

184

* @param {Visitor|Object} visitor - Visitor or partial visitor object

185

* @param {Object} [state] - State to be passed around during traversal

186

*/

187

visit(visitor, state);

188

}

189

```

190

191

**Usage Example:**

192

193

```javascript

194

// Get tree from context

195

const tree = context.getTree('nested');

196

197

// Visit with partial visitor

198

tree.visit({

199

onStart(root) {

200

console.log('=== Coverage Report ===');

201

},

202

203

onSummary(node) {

204

const summary = node.getCoverageSummary();

205

const name = node.getQualifiedName() || 'All files';

206

console.log(`\\n${name}:`);

207

console.log(` Statements: ${summary.statements.covered}/${summary.statements.total} (${summary.statements.pct}%)`);

208

console.log(` Branches: ${summary.branches.covered}/${summary.branches.total} (${summary.branches.pct}%)`);

209

console.log(` Functions: ${summary.functions.covered}/${summary.functions.total} (${summary.functions.pct}%)`);

210

console.log(` Lines: ${summary.lines.covered}/${summary.lines.total} (${summary.lines.pct}%)`);

211

},

212

213

onDetail(node) {

214

const summary = node.getCoverageSummary();

215

console.log(` ${node.getRelativeName()}: ${summary.statements.pct}%`);

216

}

217

});

218

```

219

220

### Path Utility

221

222

Path management utility for normalized file path operations across platforms.

223

224

```javascript { .api }

225

/**

226

* Path utility for normalized file path operations

227

*/

228

class Path {

229

/**

230

* Create a path from string or array

231

* @param {string|Array} strOrArray - Path string or array of path elements

232

*/

233

constructor(strOrArray);

234

235

/**

236

* Convert path to string with '/' separators

237

* @returns {string} Path as string

238

*/

239

toString();

240

241

/**

242

* Check if path has parent elements

243

* @returns {boolean} True if path has parent

244

*/

245

hasParent();

246

247

/**

248

* Get parent path

249

* @returns {Path} Parent path instance

250

* @throws {Error} If path has no parent

251

*/

252

parent();

253

254

/**

255

* Get copy of path elements array

256

* @returns {Array} Array of path elements

257

*/

258

elements();

259

260

/**

261

* Get the last element of the path

262

* @returns {string} Last path element

263

*/

264

name();

265

266

/**

267

* Check if this path contains another path

268

* @param {Path} other - Other path to compare

269

* @returns {boolean} True if this path contains the other

270

*/

271

contains(other);

272

273

/**

274

* Check if this path is an ancestor of another path

275

* @param {Path} other - Other path to compare

276

* @returns {boolean} True if this is ancestor of other

277

*/

278

ancestorOf(other);

279

280

/**

281

* Check if this path is a descendant of another path

282

* @param {Path} other - Other path to compare

283

* @returns {boolean} True if this is descendant of other

284

*/

285

descendantOf(other);

286

287

/**

288

* Get common prefix path with another path

289

* @param {Path} other - Other path to compare

290

* @returns {Path} Common prefix path

291

*/

292

commonPrefixPath(other);

293

294

/**

295

* Compare two paths for sorting

296

* @param {Path} a - First path

297

* @param {Path} b - Second path

298

* @returns {number} -1, 0, or 1 for sorting

299

*/

300

static compare(a, b);

301

302

/**

303

* Array-like operations - Path implements array manipulation methods

304

*/

305

306

/**

307

* Add elements to the end of the path

308

* @param {...string} elements - Elements to add

309

* @returns {number} New length of the path

310

*/

311

push(...elements);

312

313

/**

314

* Remove and return the last element of the path

315

* @returns {string} Last element, or undefined if empty

316

*/

317

pop();

318

319

/**

320

* Remove and return the first element of the path

321

* @returns {string} First element, or undefined if empty

322

*/

323

shift();

324

325

/**

326

* Add elements to the beginning of the path

327

* @param {...string} elements - Elements to add

328

* @returns {number} New length of the path

329

*/

330

unshift(...elements);

331

332

/**

333

* Change path contents by removing/inserting elements

334

* @param {number} start - Index to start changes

335

* @param {number} [deleteCount] - Number of elements to remove

336

* @param {...string} items - Elements to insert

337

* @returns {Array} Array of removed elements

338

*/

339

splice(start, deleteCount, ...items);

340

341

/**

342

* Length of the path (number of elements)

343

* @type {number}

344

*/

345

length;

346

}

347

```

348

349

**Usage Examples:**

350

351

```javascript

352

const { Path } = require('istanbul-lib-report/lib/path');

353

354

// Create paths

355

const path1 = new Path('/src/components/Button.js');

356

const path2 = new Path(['src', 'components', 'Button.js']);

357

358

// Path operations

359

console.log(path1.toString()); // "src/components/Button.js"

360

console.log(path1.name()); // "Button.js"

361

console.log(path1.hasParent()); // true

362

363

const parentPath = path1.parent(); // Path for "src/components"

364

console.log(parentPath.toString()); // "src/components"

365

366

// Path relationships

367

const rootPath = new Path(['src']);

368

console.log(rootPath.ancestorOf(path1)); // true

369

console.log(path1.descendantOf(rootPath)); // true

370

371

// Common prefix

372

const path3 = new Path(['src', 'utils', 'helpers.js']);

373

const common = path1.commonPrefixPath(path3); // Path for "src"

374

375

// Array-like operations

376

const workingPath = new Path(['src', 'components']);

377

console.log(workingPath.length); // 2

378

379

// Add elements

380

workingPath.push('Button.js'); // ['src', 'components', 'Button.js']

381

workingPath.unshift('project'); // ['project', 'src', 'components', 'Button.js']

382

383

// Remove elements

384

const filename = workingPath.pop(); // 'Button.js', path is now ['project', 'src', 'components']

385

const project = workingPath.shift(); // 'project', path is now ['src', 'components']

386

387

// Splice operations

388

const removed = workingPath.splice(1, 0, 'ui'); // [], path is now ['src', 'ui', 'components']

389

workingPath.splice(1, 1, 'shared'); // ['ui'], path is now ['src', 'shared', 'components']

390

```

391

392

## Types

393

394

```javascript { .api }

395

interface VisitorDelegate {

396

onStart?(root: Object, state: Object): void;

397

onSummary?(node: Object, state: Object): void;

398

onDetail?(node: Object, state: Object): void;

399

onSummaryEnd?(node: Object, state: Object): void;

400

onEnd?(root: Object, state: Object): void;

401

}

402

403

interface TreeNode {

404

isRoot(): boolean;

405

isSummary(): boolean;

406

getParent(): TreeNode | null;

407

getChildren(): TreeNode[];

408

getQualifiedName(): string;

409

getRelativeName(): string;

410

getCoverageSummary(): Object;

411

visit(visitor: Visitor, state?: Object): void;

412

}

413

414

interface Tree {

415

getRoot(): TreeNode;

416

visit(visitor: Visitor | VisitorDelegate, state?: Object): void;

417

}

418

```