diff options
Diffstat (limited to 'devtools/client/debugger/src/selectors/visibleColumnBreakpoints.js')
-rw-r--r-- | devtools/client/debugger/src/selectors/visibleColumnBreakpoints.js | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/selectors/visibleColumnBreakpoints.js b/devtools/client/debugger/src/selectors/visibleColumnBreakpoints.js new file mode 100644 index 0000000000..ce463bea14 --- /dev/null +++ b/devtools/client/debugger/src/selectors/visibleColumnBreakpoints.js @@ -0,0 +1,149 @@ +/* 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 { createSelector } from "devtools/client/shared/vendor/reselect"; + +import { + getViewport, + getSelectedSource, + getSelectedSourceTextContent, + getBreakpointPositionsForSource, +} from "./index"; +import { getVisibleBreakpoints } from "./visibleBreakpoints"; +import { getSelectedLocation } from "../utils/selected-location"; +import { sortSelectedLocations } from "../utils/location"; +import { getLineText } from "../utils/source"; + +function contains(location, range) { + return ( + location.line >= range.start.line && + location.line <= range.end.line && + (!location.column || + (location.column >= range.start.column && + location.column <= range.end.column)) + ); +} + +function convertToList(breakpointPositions) { + return [].concat(...Object.values(breakpointPositions)); +} + +/** + * Retrieve the list of column breakpoints to be displayed. + * This ignores lines without any breakpoint, but also lines with a single possible breakpoint. + * So that we only return breakpoints where there is at least two possible breakpoint on a given line. + * Also, this only consider lines currently visible in CodeMirror editor. + * + * This method returns an array whose elements are objects having two attributes: + * - breakpoint: A breakpoint object refering to a precise column location + * - location: The location object in an active source where the breakpoint location matched. + * This location may be the generated or original source based on the currently selected source type. + * + * See `visibleColumnBreakpoints()` for the definition of arguments. + */ +export function getColumnBreakpoints( + positions, + breakpoints, + viewport, + selectedSource, + selectedSourceTextContent +) { + if (!positions || !selectedSource || !breakpoints.length || !viewport) { + return []; + } + + const breakpointsPerLine = new Map(); + for (const breakpoint of breakpoints) { + if (breakpoint.options.hidden) { + continue; + } + const location = getSelectedLocation(breakpoint, selectedSource); + const { line } = location; + let breakpointsPerColumn = breakpointsPerLine.get(line); + if (!breakpointsPerColumn) { + breakpointsPerColumn = new Map(); + breakpointsPerLine.set(line, breakpointsPerColumn); + } + breakpointsPerColumn.set(location.column, breakpoint); + } + + const columnBreakpoints = []; + for (const keyLine in positions) { + const positionsPerLine = positions[keyLine]; + // Only consider positions where there is more than one breakable position per line. + // When there is only one breakpoint, this isn't a column breakpoint. + if (positionsPerLine.length <= 1) { + continue; + } + for (const breakpointPosition of positionsPerLine) { + const location = getSelectedLocation(breakpointPosition, selectedSource); + const { line } = location; + + // Ignore any further computation if there is no breakpoint on that line. + const breakpointsPerColumn = breakpointsPerLine.get(line); + if (!breakpointsPerColumn) { + continue; + } + + // Only consider positions visible in the current CodeMirror viewport + if (!contains(location, viewport)) { + continue; + } + + // Filters out breakpoints to the right of the line. (bug 1552039) + // XXX Not really clear why we get such positions?? + const { column } = location; + if (column) { + const lineText = getLineText( + selectedSource.id, + selectedSourceTextContent, + line + ); + if (column > lineText.length) { + continue; + } + } + + // Finally, return the expected format output for this selector. + // Location of each column breakpoint + a reference to the breakpoint object (if one is set on that column, it can be null). + const breakpoint = breakpointsPerColumn.get(column); + + columnBreakpoints.push({ + location, + breakpoint, + }); + } + } + + return columnBreakpoints; +} + +function getVisibleBreakpointPositions(state) { + const source = getSelectedSource(state); + if (!source) { + return null; + } + return getBreakpointPositionsForSource(state, source.id); +} + +export const visibleColumnBreakpoints = createSelector( + getVisibleBreakpointPositions, + getVisibleBreakpoints, + getViewport, + getSelectedSource, + getSelectedSourceTextContent, + getColumnBreakpoints +); + +export function getFirstBreakpointPosition(state, location) { + const positions = getBreakpointPositionsForSource(state, location.source.id); + if (!positions) { + return null; + } + + return sortSelectedLocations(convertToList(positions), location.source).find( + position => + getSelectedLocation(position, location.source).line == location.line + ); +} |