<commit_before>const React = require("react");
const { DOM: dom, PropTypes, createFactory } = React;

const ReactDOM = require("react-dom");
const ImPropTypes = require("react-immutable-proptypes");
const { bindActionCreators } = require("redux");
const { connect } = require("react-redux");
const classnames = require("classnames");

const SourceEditor = require("../utils/source-editor");
const SourceFooter = createFactory(require("./SourceFooter"));
const EditorSearchBar = createFactory(require("./EditorSearchBar"));
const { renderConditionalPanel } = require("./EditorConditionalPanel");
const { debugGlobal } = require("devtools-launchpad");
const {
  getSourceText, getBreakpointsForSource,
  getSelectedLocation, getSelectedFrame,
  getSelectedSource, getHitCountForSource,
  getCoverageEnabled
} = require("../selectors");
const { makeLocationId } = require("../reducers/breakpoints");
const actions = require("../actions");
const Breakpoint = React.createFactory(require("./EditorBreakpoint"));
const HitMarker = React.createFactory(require("./EditorHitMarker"));

const { getDocument, setDocument } = require("../utils/source-documents");
const { shouldShowFooter } = require("../utils/editor");
const { isFirefox } = require("devtools-config");
const { showMenu } = require("../utils/menu");
const { isEnabled } = require("devtools-config");
const { isOriginalId } = require("../utils/source-map");

require("./Editor.css");

function isTextForSource(sourceText) {
  return !sourceText.get("loading") && !sourceText.get("error");
}

function breakpointAtLine(breakpoints, line) {
  return breakpoints.find(b => {
    return b.location.line === line + 1;
  });
}

function getTextForLine(codeMirror, line) {
  return codeMirror.getLine(line - 1).trim();
}

function getCursorLine(codeMirror) {
  return codeMirror.getCursor().line;
}
/**
 * Forces the breakpoint gutter to be the same size as the line
 * numbers gutter. Editor CSS will absolutely position the gutter
 * beneath the line numbers. This makes it easy to be flexible with
 * how we overlay breakpoints.
 */
function resizeBreakpointGutter(editor) {
  const gutters = editor.display.gutters;
  const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers");
  const breakpoints = gutters.querySelector(".breakpoints");
  breakpoints.style.width = `${lineNumbers.clientWidth}px`;
}

const Editor = React.createClass({
  propTypes: {
    breakpoints: ImPropTypes.map.isRequired,
    hitCount: PropTypes.object,
    selectedLocation: PropTypes.object,
    selectedSource: ImPropTypes.map,
    sourceText: PropTypes.object,
    addBreakpoint: PropTypes.func,
    disableBreakpoint: PropTypes.func,
    enableBreakpoint: PropTypes.func,
    removeBreakpoint: PropTypes.func,
    setBreakpointCondition: PropTypes.func,
    jumpToMappedLocation: PropTypes.func,
    coverageOn: PropTypes.bool,
    selectedFrame: PropTypes.object
  },

  displayName: "Editor",

  contextTypes: {
    shortcuts: PropTypes.object
  },

  onGutterClick(cm, line, gutter, ev) {
    // ignore right clicks in the gutter
    if (ev.which === 3) {
      return;
    }

    if (this.isCbPanelOpen()) {
      return this.closeConditionalPanel(line);
    }

    this.toggleBreakpoint(line);
  },

  onContextMenu(cm, event) {
    if (event.target.classList.contains("CodeMirror-linenumber")) {
      return this.onGutterContextMenu(cm, event);
    }

    event.stopPropagation();
    event.preventDefault();

    const { line, ch } = this.editor.codeMirror.coordsChar({
      left: event.clientX,
      top: event.clientY
    });

    const sourceLocation = {
      sourceId: this.props.selectedLocation.sourceId,
      line: line,
      column: ch
    };

    const pairedType = isOriginalId(this.props.selectedLocation.sourceId)
      ? L10N.getStr("generated") : L10N.getStr("original");

    const jumpLabel = {
      accesskey: "C",
      disabled: false,
      label: L10N.getFormatStr("editor.jumpToMappedLocation", pairedType),
      click: () => this.props.jumpToMappedLocation(sourceLocation)
    };

    showMenu(event, [
      jumpLabel
    ]);
  },

  onGutterContextMenu(cm, event) {
    event.stopPropagation();
    event.preventDefault();

    const line = this.editor.codeMirror.lineAtHeight(event.clientY);
    const bp = breakpointAtLine(this.props.breakpoints, line);
    this.showGutterMenu(event, line, bp);
  },

  showConditionalPanel(line) {
    if (this.isCbPanelOpen()) {
      return;
    }

    const { selectedLocation: { sourceId },
            setBreakpointCondition, breakpoints } = this.props;

    const bp = breakpointAtLine(breakpoints, line);
    const location = { sourceId, line: line + 1 };
    const condition = bp ? bp.condition : "";

    const setBreakpoint = value => {
      setBreakpointCondition(location, {
        condition: value,<commit_msg>Fix gutter context menu (#1595)<commit_after>const React = require("react");
const { DOM: dom, PropTypes, createFactory } = React;

const ReactDOM = require("react-dom");
const ImPropTypes = require("react-immutable-proptypes");
const { bindActionCreators } = require("redux");
const { connect } = require("react-redux");
const classnames = require("classnames");

const SourceEditor = require("../utils/source-editor");
const SourceFooter = createFactory(require("./SourceFooter"));
const EditorSearchBar = createFactory(require("./EditorSearchBar"));
const { renderConditionalPanel } = require("./EditorConditionalPanel");
const { debugGlobal } = require("devtools-launchpad");
const {
  getSourceText, getBreakpointsForSource,
  getSelectedLocation, getSelectedFrame,
  getSelectedSource, getHitCountForSource,
  getCoverageEnabled
} = require("../selectors");
const { makeLocationId } = require("../reducers/breakpoints");
const actions = require("../actions");
const Breakpoint = React.createFactory(require("./EditorBreakpoint"));
const HitMarker = React.createFactory(require("./EditorHitMarker"));

const { getDocument, setDocument } = require("../utils/source-documents");
const { shouldShowFooter } = require("../utils/editor");
const { isFirefox } = require("devtools-config");
const { showMenu } = require("../utils/menu");
const { isEnabled } = require("devtools-config");
const { isOriginalId } = require("../utils/source-map");

require("./Editor.css");

function isTextForSource(sourceText) {
  return !sourceText.get("loading") && !sourceText.get("error");
}

function breakpointAtLine(breakpoints, line) {
  return breakpoints.find(b => {
    return b.location.line === line + 1;
  });
}

function getTextForLine(codeMirror, line) {
  return codeMirror.getLine(line - 1).trim();
}

function getCursorLine(codeMirror) {
  return codeMirror.getCursor().line;
}
/**
 * Forces the breakpoint gutter to be the same size as the line
 * numbers gutter. Editor CSS will absolutely position the gutter
 * beneath the line numbers. This makes it easy to be flexible with
 * how we overlay breakpoints.
 */
function resizeBreakpointGutter(editor) {
  const gutters = editor.display.gutters;
  const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers");
  const breakpoints = gutters.querySelector(".breakpoints");
  breakpoints.style.width = `${lineNumbers.clientWidth}px`;
}

const Editor = React.createClass({
  propTypes: {
    breakpoints: ImPropTypes.map.isRequired,
    hitCount: PropTypes.object,
    selectedLocation: PropTypes.object,
    selectedSource: ImPropTypes.map,
    sourceText: PropTypes.object,
    addBreakpoint: PropTypes.func,
    disableBreakpoint: PropTypes.func,
    enableBreakpoint: PropTypes.func,
    removeBreakpoint: PropTypes.func,
    setBreakpointCondition: PropTypes.func,
    jumpToMappedLocation: PropTypes.func,
    coverageOn: PropTypes.bool,
    selectedFrame: PropTypes.object
  },

  displayName: "Editor",

  contextTypes: {
    shortcuts: PropTypes.object
  },

  onGutterClick(cm, line, gutter, ev) {
    // ignore right clicks in the gutter
    if (ev.which === 3) {
      return;
    }

    if (this.isCbPanelOpen()) {
      return this.closeConditionalPanel(line);
    }

    this.toggleBreakpoint(line);
  },

  onContextMenu(cm, event) {
    if (event.target.classList.contains("CodeMirror-linenumber")) {
      return this.onGutterContextMenu(event);
    }

    event.stopPropagation();
    event.preventDefault();

    const { line, ch } = this.editor.codeMirror.coordsChar({
      left: event.clientX,
      top: event.clientY
    });

    const sourceLocation = {
      sourceId: this.props.selectedLocation.sourceId,
      line: line,
      column: ch
    };

    const pairedType = isOriginalId(this.props.selectedLocation.sourceId)
      ? L10N.getStr("generated") : L10N.getStr("original");

    const jumpLabel = {
      accesskey: "C",
      disabled: false,
      label: L10N.getFormatStr("editor.jumpToMappedLocation", pairedType),
      click: () => this.props.jumpToMappedLocation(sourceLocation)
    };

    showMenu(event, [
      jumpLabel
    ]);
  },

  onGutterContextMenu(event) {
    event.stopPropagation();
    event.preventDefault();

    const line = this.editor.codeMirror.lineAtHeight(event.clientY);
    const bp = breakpointAtLine(this.props.breakpoints, line);
    this.showGutterMenu(event, line, bp);
  },

  showConditionalPanel(line) {
    if (this.isCbPanelOpen()) {
      return;
    }

    const { selectedLocation: { sourceId },
            setBreakpointCondition, breakpoints } = this.props;

    const bp = breakpointAtLine(breakpoints, line);
    const location = { sourceId, line: line + 1 };
    const condition = bp ? bp.condition : "";

    const setBreakpoint = value => {
      setBreakpointCondition(location, {
        condition: value,
{'fraction_non_alphanumeric': 0.13147040626933387, 'fraction_numerical': 0.002474737059187461, 'mean_word_length': 4.102051551814834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7116351', 'n_tokens_mistral': 2902, 'n_tokens_neox': 2837, 'n_words': 591}