Bug 1534332 - get empty lines r=loganfsmyth

Differential Revision: https://phabricator.services.mozilla.com/D22985

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jason Laster 2019-03-12 21:07:43 +00:00
Родитель 5ea52d4cbf
Коммит b1985ff010
9 изменённых файлов: 125 добавлений и 25 удалений

Просмотреть файл

@ -97,7 +97,17 @@ async function _setBreakpointPositions(sourceId, thunkArgs) {
let positions = convertToList(results, generatedSource);
positions = await mapLocations(positions, thunkArgs);
positions = filterByUniqLocation(positions);
dispatch({ type: "ADD_BREAKPOINT_POSITIONS", sourceId, positions });
const source = getSource(getState(), sourceId);
// NOTE: it's possible that the source was removed during a navigate
if (!source) {
return;
}
dispatch({
type: "ADD_BREAKPOINT_POSITIONS",
source: source,
positions
});
}
export function setBreakpointPositions(sourceId: string) {

Просмотреть файл

@ -17,7 +17,8 @@ import {
getSelectedSource,
getBreakpointAtLocation,
getConditionalPanelLocation,
getBreakpointsForSource
getBreakpointsForSource,
isEmptyLineInSource
} from "../../selectors";
import {
assertBreakpoint,
@ -32,7 +33,6 @@ import {
import remapLocations from "./remapLocations";
import { syncBreakpoint } from "./syncBreakpoint";
import { closeConditionalPanel } from "../ui";
import { isEmptyLineInSource } from "../../reducers/ast";
// this will need to be changed so that addCLientBreakpoint is removed

Просмотреть файл

@ -8,6 +8,7 @@ import type {
Breakpoint,
SourceLocation,
XHRBreakpoint,
Source,
BreakpointPositions
} from "../../types";
@ -95,5 +96,5 @@ export type BreakpointAction =
| {|
type: "ADD_BREAKPOINT_POSITIONS",
positions: BreakpointPositions,
sourceId: string
source: Source
|};

Просмотреть файл

@ -166,15 +166,6 @@ export function getPreview(state: OuterState) {
return state.ast.preview;
}
export function isEmptyLineInSource(
state: OuterState,
line: number,
selectedSourceId: string
) {
const emptyLines = getEmptyLines(state, selectedSourceId);
return emptyLines && emptyLines.includes(line);
}
const emptySourceMetaData = {};
export function getSourceMetaData(state: OuterState, sourceId: string) {
return state.ast.sourceMetaData[sourceId] || emptySourceMetaData;
@ -193,12 +184,4 @@ export function isLineInScope(state: OuterState, line: number) {
return linesInScope && linesInScope.includes(line);
}
export function getEmptyLines(state: OuterState, sourceId: string) {
if (!sourceId) {
return null;
}
return state.ast.emptyLines[sourceId];
}
export default update;

Просмотреть файл

@ -13,6 +13,7 @@ import { isGeneratedId, isOriginalId } from "devtools-source-map";
import { isEqual } from "lodash";
import { makeBreakpointId } from "../utils/breakpoint";
import { findEmptyLines } from "../utils/empty-lines";
import type {
XHRBreakpoint,
@ -31,7 +32,8 @@ export type BreakpointsState = {
breakpoints: BreakpointsMap,
breakpointPositions: BreakpointPositionsMap,
xhrBreakpoints: XHRBreakpointsList,
breakpointsDisabled: boolean
breakpointsDisabled: boolean,
emptyLines: { [string]: number[] }
};
export function initialBreakpointsState(
@ -41,7 +43,8 @@ export function initialBreakpointsState(
breakpoints: {},
xhrBreakpoints: xhrBreakpoints,
breakpointPositions: {},
breakpointsDisabled: false
breakpointsDisabled: false,
emptyLines: {}
};
}
@ -111,12 +114,18 @@ function update(
}
case "ADD_BREAKPOINT_POSITIONS": {
const { sourceId, positions } = action;
const { source, positions } = action;
const emptyLines = findEmptyLines(source, positions);
return {
...state,
breakpointPositions: {
...state.breakpointPositions,
[sourceId]: positions
[source.id]: positions
},
emptyLines: {
...state.emptyLines,
[source.id]: emptyLines
}
};
}
@ -383,4 +392,21 @@ export function getBreakpointPositionsForLine(
});
}
export function isEmptyLineInSource(
state: OuterState,
line: number,
selectedSourceId: string
) {
const emptyLines = getEmptyLines(state, selectedSourceId);
return emptyLines && emptyLines.includes(line);
}
export function getEmptyLines(state: OuterState, sourceId: string) {
if (!sourceId) {
return null;
}
return state.breakpoints.emptyLines[sourceId];
}
export default update;

Просмотреть файл

@ -0,0 +1,30 @@
/* 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/>. */
// @flow
import { xor, range } from "lodash";
import { getSelectedLocation } from "./source-maps";
import type { BreakpointPositions, Source } from "../types";
export function findEmptyLines(
source: Source,
breakpointPositions: BreakpointPositions
): number[] {
if (!breakpointPositions || source.isWasm) {
return [];
}
const sourceText = source.text || "";
const lineCount = sourceText.split("\n").length;
const sourceLines = range(1, lineCount + 1);
const breakpointLines = breakpointPositions
.map(point => getSelectedLocation(point, source).line)
// NOTE: at the moment it is possible the location is an unmapped generated
// line which could be greater than the line count.
.filter(line => line <= lineCount);
return xor(sourceLines, breakpointLines);
}

Просмотреть файл

@ -21,6 +21,7 @@ CompiledModules(
'dbg.js',
'defer.js',
'DevToolsUtils.js',
'empty-lines.js',
'expressions.js',
'fromJS.js',
'function.js',

Просмотреть файл

@ -0,0 +1,33 @@
/* 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/>. */
// @flow
import { findEmptyLines } from "../empty-lines";
import { makeSource } from "../test-head";
function ml(gLine) {
const generatedLocation = { line: gLine, column: 0, sourceId: "foo" };
return { generatedLocation, location: generatedLocation };
}
describe("emptyLines", () => {
it("no positions", () => {
const source = makeSource("foo", { text: "\n" });
const lines = findEmptyLines(source, []);
expect(lines).toEqual([1, 2]);
});
it("one position", () => {
const source = makeSource("foo", { text: "\n" });
const lines = findEmptyLines(source, [ml(1)]);
expect(lines).toEqual([2]);
});
it("outside positions are not included", () => {
const source = makeSource("foo", { text: "\n" });
const lines = findEmptyLines(source, [ml(10)]);
expect(lines).toEqual([1, 2]);
});
});

Просмотреть файл

@ -35,6 +35,20 @@ function enableBreakpoints(dbg, count) {
return enabled;
}
function every(array, predicate) {
return !array.some(item => !predicate(item));
}
function subset(subArray, superArray) {
return every(subArray, subItem => superArray.includes(subItem));
}
function assertEmptyLines(dbg, lines) {
const sourceId = dbg.selectors.getSelectedSourceId(dbg.store.getState());
const emptyLines = dbg.selectors.getEmptyLines(dbg.store.getState(), sourceId);
ok(subset(lines, emptyLines), 'empty lines should match');
}
// Test enabling and disabling a breakpoint using the check boxes
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html", "simple2");
@ -65,6 +79,8 @@ add_task(async function() {
await addBreakpoint(dbg, "simple2", 3);
await addBreakpoint(dbg, "simple2", 5);
assertEmptyLines(dbg, [1,2]);
rightClickElement(dbg, "breakpointItem", 3);
const disableBreakpointDispatch = waitForDispatch(dbg, "DISABLE_BREAKPOINT");
selectContextMenuItem(dbg, selectors.breakpointContextMenu.disableSelf);