summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/actions/pause/highlightCalls.js
blob: aec82fe35bf9f438cb7cde493917c848e730d5c6 (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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

import {
  getSymbols,
  getSelectedFrame,
  getCurrentThread,
} from "../../selectors";

// a is an ast location with start and end positions (line and column).
// b is a single position (line and column).
// This function tests to see if the b position
// falls within the range given in a.
function inHouseContainsPosition(a, b) {
  const bColumn = b.column || 0;
  const startsBefore =
    a.start.line < b.line ||
    (a.start.line === b.line && a.start.column <= bColumn);
  const endsAfter =
    a.end.line > b.line || (a.end.line === b.line && a.end.column >= bColumn);

  return startsBefore && endsAfter;
}

export function highlightCalls(cx) {
  return async function ({ dispatch, getState, parserWorker }) {
    if (!cx) {
      return null;
    }

    const frame = await getSelectedFrame(
      getState(),
      getCurrentThread(getState())
    );

    if (!frame || !parserWorker.isLocationSupported(frame.location)) {
      return null;
    }

    const { thread } = cx;

    const originalAstScopes = await parserWorker.getScopes(frame.location);
    if (!originalAstScopes) {
      return null;
    }

    const symbols = getSymbols(getState(), frame.location);

    if (!symbols) {
      return null;
    }

    if (!symbols.callExpressions) {
      return null;
    }

    const localAstScope = originalAstScopes[0];
    const allFunctionCalls = symbols.callExpressions;

    const highlightedCalls = allFunctionCalls.filter(function (call) {
      const containsStart = inHouseContainsPosition(
        localAstScope,
        call.location.start
      );
      const containsEnd = inHouseContainsPosition(
        localAstScope,
        call.location.end
      );
      return containsStart && containsEnd;
    });

    return dispatch({
      type: "HIGHLIGHT_CALLS",
      thread,
      highlightedCalls,
    });
  };
}

export function unhighlightCalls(cx) {
  return async function ({ dispatch, getState }) {
    const { thread } = cx;
    return dispatch({
      type: "UNHIGHLIGHT_CALLS",
      thread,
    });
  };
}