summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/code-path-analysis/code-path.js
blob: 200ff434b8d4176b1eca10bd8bf031733acbe33d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
 * @fileoverview A class of the code path.
 * @author Toru Nagashima
 * @copyright 2015 Toru Nagashima. All rights reserved.
 * See LICENSE file in root directory for full license.
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var CodePathState = require("./code-path-state");
var IdGenerator = require("./id-generator");

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

/**
 * A code path.
 *
 * @constructor
 * @param {string} id - An identifier.
 * @param {CodePath|null} upper - The code path of the upper function scope.
 * @param {function} onLooped - A callback function to notify looping.
 */
function CodePath(id, upper, onLooped) {
    /**
     * The identifier of this code path.
     * Rules use it to store additional information of each rule.
     * @type {string}
     */
    this.id = id;

    /**
     * The code path of the upper function scope.
     * @type {CodePath|null}
     */
    this.upper = upper;

    /**
     * The code paths of nested function scopes.
     * @type {CodePath[]}
     */
    this.childCodePaths = [];

    // Initializes internal state.
    Object.defineProperty(
        this,
        "internal",
        {value: new CodePathState(new IdGenerator(id + "_"), onLooped)});

    // Adds this into `childCodePaths` of `upper`.
    if (upper) {
        upper.childCodePaths.push(this);
    }
}

CodePath.prototype = {
    constructor: CodePath,

    /**
     * The initial code path segment.
     * @type {CodePathSegment}
     */
    get initialSegment() {
        return this.internal.initialSegment;
    },

    /**
     * Final code path segments.
     * This array is a mix of `returnedSegments` and `thrownSegments`.
     * @type {CodePathSegment[]}
     */
    get finalSegments() {
        return this.internal.finalSegments;
    },

    /**
     * Final code path segments which is with `return` statements.
     * This array contains the last path segment if it's reachable.
     * Since the reachable last path returns `undefined`.
     * @type {CodePathSegment[]}
     */
    get returnedSegments() {
        return this.internal.returnedForkContext;
    },

    /**
     * Final code path segments which is with `throw` statements.
     * @type {CodePathSegment[]}
     */
    get thrownSegments() {
        return this.internal.thrownForkContext;
    },

    /**
     * Current code path segments.
     * @type {CodePathSegment[]}
     */
    get currentSegments() {
        return this.internal.currentSegments;
    }
};

/**
 * Gets the state of a given code path.
 *
 * @param {CodePath} codePath - A code path to get.
 * @returns {CodePathState} The state of the code path.
 */
CodePath.getState = function getState(codePath) {
    return codePath.internal;
};

module.exports = CodePath;