/*
 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

WebInspector.SourceCodeTextEditor = function(sourceCode)
{
    console.assert(sourceCode instanceof WebInspector.SourceCode);

    this._sourceCode = sourceCode;
    this._breakpointMap = {};
    this._issuesLineNumberMap = new Map;
    this._widgetMap = new Map;
    this._contentPopulated = false;
    this._invalidLineNumbers = {0: true};
    this._ignoreContentDidChange = 0;

    WebInspector.TextEditor.call(this, null, null, this);

    this._typeTokenScrollHandler = null;
    this._typeTokenAnnotator = null;
    this._basicBlockAnnotator = null;
    
    this._isProbablyMinified = false;

    // FIXME: Currently this just jumps between resources and related source map resources. It doesn't "jump to symbol" yet.
    this._updateTokenTrackingControllerState();

    this.element.classList.add(WebInspector.SourceCodeTextEditor.StyleClassName);

    if (this._supportsDebugging) {
        WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.DisabledStateDidChange, this._breakpointStatusDidChange, this);
        WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.AutoContinueDidChange, this._breakpointStatusDidChange, this);
        WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.ResolvedStateDidChange, this._breakpointStatusDidChange, this);
        WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.LocationDidChange, this._updateBreakpointLocation, this);

        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);

        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, this._debuggerDidResume, this);
        if (WebInspector.debuggerManager.activeCallFrame)
            this._debuggerDidPause();

        this._activeCallFrameDidChange();
    }

    WebInspector.issueManager.addEventListener(WebInspector.IssueManager.Event.IssueWasAdded, this._issueWasAdded, this);

    if (this._sourceCode instanceof WebInspector.SourceMapResource || this._sourceCode.sourceMaps.length > 0)
        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
    else
        this._sourceCode.addEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);

    sourceCode.requestContent().then(this._contentAvailable.bind(this));

    // FIXME: Cmd+L shorcut doesn't actually work.
    new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.Command, "L", this.showGoToLineDialog.bind(this), this.element);
    new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.Control, "G", this.showGoToLineDialog.bind(this), this.element);
};

// FIXME: Move to a WebInspector.Object subclass and we can remove this.
WebInspector.Object.deprecatedAddConstructorFunctions(WebInspector.SourceCodeTextEditor);

WebInspector.SourceCodeTextEditor.StyleClassName = "source-code";
WebInspector.SourceCodeTextEditor.LineErrorStyleClassName = "error";
WebInspector.SourceCodeTextEditor.LineWarningStyleClassName = "warning";
WebInspector.SourceCodeTextEditor.PopoverDebuggerContentStyleClassName = "debugger-popover-content";
WebInspector.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName = "hovered-expression-highlight";
WebInspector.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken = 500;
WebInspector.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease = 1000;
WebInspector.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling = 100;
WebInspector.SourceCodeTextEditor.AutoFormatMinimumLineLength = 500;
WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol = Symbol("source-code-widget-contains-multiple-issues");

WebInspector.SourceCodeTextEditor.Event = {
    ContentWillPopulate: "source-code-text-editor-content-will-populate",
    ContentDidPopulate: "source-code-text-editor-content-did-populate"
};

WebInspector.SourceCodeTextEditor.prototype = {
    constructor: WebInspector.SourceCodeTextEditor,

    // Public

    get sourceCode()
    {
        return this._sourceCode;
    },

    shown: function()
    {
        WebInspector.TextEditor.prototype.shown.call(this);

        if (WebInspector.showJavaScriptTypeInformationSetting.value) {
            if (this._typeTokenAnnotator)
                this._typeTokenAnnotator.resume();
            if (this._basicBlockAnnotator)
                this._basicBlockAnnotator.resume();
            if (!this._typeTokenScrollHandler && (this._typeTokenAnnotator || this._basicBlockAnnotator))
                this._enableScrollEventsForTypeTokenAnnotator();
        } else {
            if (this._typeTokenAnnotator || this._basicBlockAnnotator)
                this._setTypeTokenAnnotatorEnabledState(false);
        }
    },

    hidden: function()
    {
        WebInspector.TextEditor.prototype.hidden.call(this);

        this.tokenTrackingController.removeHighlightedRange();

        this._dismissPopover();
        
        this._dismissEditingController(true);

        if (this._typeTokenAnnotator)
            this._typeTokenAnnotator.pause();
        if (this._basicBlockAnnotator)
            this._basicBlockAnnotator.pause();
    },

    close: function()
    {
        if (this._supportsDebugging) {
            WebInspector.Breakpoint.removeEventListener(WebInspector.Breakpoint.Event.DisabledStateDidChange, this._breakpointStatusDidChange, this);
            WebInspector.Breakpoint.removeEventListener(WebInspector.Breakpoint.Event.AutoContinueDidChange, this._breakpointStatusDidChange, this);
            WebInspector.Breakpoint.removeEventListener(WebInspector.Breakpoint.Event.ResolvedStateDidChange, this._breakpointStatusDidChange, this);
            WebInspector.Breakpoint.removeEventListener(WebInspector.Breakpoint.Event.LocationDidChange, this._updateBreakpointLocation, this);

            WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
            WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
            WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
            WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);

            if (this._activeCallFrameSourceCodeLocation) {
                this._activeCallFrameSourceCodeLocation.removeEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
                delete this._activeCallFrameSourceCodeLocation;
            }
        }

        WebInspector.issueManager.removeEventListener(WebInspector.IssueManager.Event.IssueWasAdded, this._issueWasAdded, this);

        WebInspector.notifications.removeEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
        this._sourceCode.removeEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);
    },

    canBeFormatted: function()
    {
        // Currently we assume that source map resources are formatted how the author wants it.
        // We could allow source map resources to be formatted, we would then need to make
        // SourceCodeLocation watch listen for mappedResource's formatting changes, and keep
        // a formatted location alongside the regular mapped location.
        if (this._sourceCode instanceof WebInspector.SourceMapResource)
            return false;

        return WebInspector.TextEditor.prototype.canBeFormatted.call(this);
    },

    canShowTypeAnnotations: function()
    {
        return !!this._typeTokenAnnotator;
    },

    customPerformSearch: function(query)
    {
        function searchResultCallback(error, matches)
        {
            // Bail if the query changed since we started.
            if (this.currentSearchQuery !== query)
                return;

            if (error || !matches || !matches.length) {
                // Report zero matches.
                this.dispatchEventToListeners(WebInspector.TextEditor.Event.NumberOfSearchResultsDidChange);
                return;
            }

            var queryRegex = new RegExp(query.escapeForRegExp(), "gi");
            var searchResults = [];

            for (var i = 0; i < matches.length; ++i) {
                var matchLineNumber = matches[i].lineNumber;
                var line = this.line(matchLineNumber);

                // Reset the last index to reuse the regex on a new line.
                queryRegex.lastIndex = 0;

                // Search the line and mark the ranges.
                var lineMatch = null;
                while (queryRegex.lastIndex + query.length <= line.length && (lineMatch = queryRegex.exec(line))) {
                    var resultTextRange = new WebInspector.TextRange(matchLineNumber, lineMatch.index, matchLineNumber, queryRegex.lastIndex);
                    searchResults.push(resultTextRange);
                }
            }

            this.addSearchResults(searchResults);

            this.dispatchEventToListeners(WebInspector.TextEditor.Event.NumberOfSearchResultsDidChange);
        }

        if (this.hasEdits())
            return false;

        if (this._sourceCode instanceof WebInspector.SourceMapResource)
            return false;

        if (this._sourceCode instanceof WebInspector.Resource)
            PageAgent.searchInResource(this._sourceCode.parentFrame.id, this._sourceCode.url, query, false, false, searchResultCallback.bind(this));
        else if (this._sourceCode instanceof WebInspector.Script)
            DebuggerAgent.searchInContent(this._sourceCode.id, query, false, false, searchResultCallback.bind(this));
        return true;
    },

    showGoToLineDialog: function()
    {
        if (!this._goToLineDialog) {
            this._goToLineDialog = new WebInspector.GoToLineDialog;
            this._goToLineDialog.delegate = this;
        }

        this._goToLineDialog.present(this.element);
    },

    isGoToLineDialogValueValid: function(goToLineDialog, lineNumber)
    {
        return !isNaN(lineNumber) && lineNumber > 0 && lineNumber <= this.lineCount;
    },

    goToLineDialogValueWasValidated: function(goToLineDialog, lineNumber)
    {
        var position = new WebInspector.SourceCodePosition(lineNumber - 1, 0);
        var range = new WebInspector.TextRange(lineNumber - 1, 0, lineNumber, 0);
        this.revealPosition(position, range, false, true);
    },

    goToLineDialogWasDismissed: function()
    {
        this.focus();
    },

    contentDidChange: function(replacedRanges, newRanges)
    {
        WebInspector.TextEditor.prototype.contentDidChange.call(this, replacedRanges, newRanges);

        if (this._ignoreContentDidChange > 0)
            return;

        for (var range of newRanges)
            this._updateEditableMarkers(range);

        if (this._typeTokenAnnotator || this._basicBlockAnnotator) {
            this._setTypeTokenAnnotatorEnabledState(false);
            this._typeTokenAnnotator = null;
            this._basicBlockAnnotator = null;
        }
    },

    toggleTypeAnnotations: function()
    {
        if (!this._typeTokenAnnotator)
            return false;

        var newActivatedState = !this._typeTokenAnnotator.isActive();
        if (newActivatedState && this._isProbablyMinified && !this.formatted)
            this.formatted = true;

        this._setTypeTokenAnnotatorEnabledState(newActivatedState);
        return newActivatedState;
    },

    showPopoverForTypes: function(types, bounds, title)
    {
        var content = document.createElement("div");
        content.className = "object expandable";

        var titleElement = document.createElement("div");
        titleElement.className = "title";
        titleElement.textContent = title;
        content.appendChild(titleElement);

        var section = new WebInspector.TypePropertiesSection(types);
        section.expanded = true;
        section.element.classList.add("body");
        content.appendChild(section.element);

        this._showPopover(content, bounds);
    },

    // Protected

    prettyPrint: function(pretty)
    {
        // The annotators must be cleared before pretty printing takes place and resumed 
        // after so that they clear their annotations in a known state and insert new annotations 
        // in the new state.
        var shouldResumeTypeTokenAnnotator = this._typeTokenAnnotator && this._typeTokenAnnotator.isActive();
        var shouldResumeBasicBlockAnnotator = this._basicBlockAnnotator && this._basicBlockAnnotator.isActive();
        if (shouldResumeTypeTokenAnnotator || shouldResumeBasicBlockAnnotator)
            this._setTypeTokenAnnotatorEnabledState(false);

        WebInspector.TextEditor.prototype.prettyPrint.call(this, pretty);

        if (pretty || !this._isProbablyMinified) {
            if (shouldResumeTypeTokenAnnotator || shouldResumeBasicBlockAnnotator)
                this._setTypeTokenAnnotatorEnabledState(true);
        } else {
            console.assert(!pretty && this._isProbablyMinified);
            if (this._typeTokenAnnotator || this._basicBlockAnnotator)
                this._setTypeTokenAnnotatorEnabledState(false);
        }
    },

    // Private

    _unformattedLineInfoForEditorLineInfo: function(lineInfo)
    {
        if (this.formatterSourceMap)
            return this.formatterSourceMap.formattedToOriginal(lineInfo.lineNumber, lineInfo.columnNumber);
        return lineInfo;
    },

    _sourceCodeLocationForEditorPosition: function(position)
    {
        var lineInfo = {lineNumber: position.line, columnNumber: position.ch};
        var unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(lineInfo);
        return this.sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);
    },

    _editorLineInfoForSourceCodeLocation: function(sourceCodeLocation)
    {
        if (this._sourceCode instanceof WebInspector.SourceMapResource)
            return {lineNumber: sourceCodeLocation.displayLineNumber, columnNumber: sourceCodeLocation.displayColumnNumber};
        return {lineNumber: sourceCodeLocation.formattedLineNumber, columnNumber: sourceCodeLocation.formattedColumnNumber};
    },

    _breakpointForEditorLineInfo: function(lineInfo)
    {
        if (!this._breakpointMap[lineInfo.lineNumber])
            return null;
        return this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber];
    },

    _addBreakpointWithEditorLineInfo: function(breakpoint, lineInfo)
    {
        if (!this._breakpointMap[lineInfo.lineNumber])
            this._breakpointMap[lineInfo.lineNumber] = {};

        this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber] = breakpoint;
    },

    _removeBreakpointWithEditorLineInfo: function(breakpoint, lineInfo)
    {
        console.assert(breakpoint === this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber]);

        delete this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber];

        if (isEmptyObject(this._breakpointMap[lineInfo.lineNumber]))
            delete this._breakpointMap[lineInfo.lineNumber];
    },

    _contentWillPopulate: function(content)
    {
        this.dispatchEventToListeners(WebInspector.SourceCodeTextEditor.Event.ContentWillPopulate);

        // We only do the rest of this work before the first populate.
        if (this._contentPopulated)
            return;

        if (this._supportsDebugging) {
            this._breakpointMap = {};

            var breakpoints = WebInspector.debuggerManager.breakpointsForSourceCode(this._sourceCode);
            for (var i = 0; i < breakpoints.length; ++i) {
                var breakpoint = breakpoints[i];
                console.assert(this._matchesBreakpoint(breakpoint));
                var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
                this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
            }
        }

        if (this._sourceCode instanceof WebInspector.Resource)
            this.mimeType = this._sourceCode.syntheticMIMEType;
        else if (this._sourceCode instanceof WebInspector.Script)
            this.mimeType = "text/javascript";

        // Automatically format the content if it looks minified and it can be formatted.
        console.assert(!this.formatted);
        if (this.canBeFormatted()) {
            var lastNewlineIndex = 0;
            while (true) {
                var nextNewlineIndex = content.indexOf("\n", lastNewlineIndex);
                if (nextNewlineIndex === -1) {
                    if (content.length - lastNewlineIndex > WebInspector.SourceCodeTextEditor.AutoFormatMinimumLineLength) {
                        this.autoFormat = true;
                        this._isProbablyMinified = true;
                    }
                    break;
                }

                if (nextNewlineIndex - lastNewlineIndex > WebInspector.SourceCodeTextEditor.AutoFormatMinimumLineLength) {
                    this.autoFormat = true;
                    this._isProbablyMinified = true;
                    break;
                }

                lastNewlineIndex = nextNewlineIndex + 1;
            }
        }
    },

    _contentDidPopulate: function()
    {
        this._contentPopulated = true;

        this.dispatchEventToListeners(WebInspector.SourceCodeTextEditor.Event.ContentDidPopulate);

        // We add the issues each time content is populated. This is needed because lines might not exist
        // if we tried added them before when the full content wasn't available. (When populating with
        // partial script content this can be called multiple times.)

        this._reinsertAllIssues();

        this._updateEditableMarkers();
    },

    _populateWithContent: function(content)
    {
        content = content || "";

        this._contentWillPopulate(content);
        this.string = content;

        this._makeTypeTokenAnnotator();
        this._makeBasicBlockAnnotator();

        if (WebInspector.showJavaScriptTypeInformationSetting.value) {
            if (this._basicBlockAnnotator || this._typeTokenAnnotator)
                this._setTypeTokenAnnotatorEnabledState(true);
        }

        this._contentDidPopulate();
    },

    _contentAvailable: function(parameters)
    {
        // Return if resource is not available.
        if (parameters.error)
            return;

        var sourceCode = parameters.sourceCode;
        var content = parameters.content;
        var base64Encoded = parameters.base64Encoded;

        console.assert(sourceCode === this._sourceCode);
        console.assert(!base64Encoded);

        // Abort if the full content populated while waiting for this async callback.
        if (this._fullContentPopulated)
            return;

        this._fullContentPopulated = true;
        this._invalidLineNumbers = {};

        this._populateWithContent(content);
    },

    _breakpointStatusDidChange: function(event)
    {
        this._updateBreakpointStatus(event.target);
    },

    _breakpointsEnabledDidChange: function()
    {
        console.assert(this._supportsDebugging);

        var breakpoints = WebInspector.debuggerManager.breakpointsForSourceCode(this._sourceCode);
        for (var breakpoint of breakpoints)
            this._updateBreakpointStatus(breakpoint);
    },

    _updateBreakpointStatus: function(breakpoint)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        if (!this._matchesBreakpoint(breakpoint))
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
    },

    _updateBreakpointLocation: function(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.target;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (this._ignoreAllBreakpointLocationUpdates)
            return;

        if (breakpoint === this._ignoreLocationUpdateBreakpoint)
            return;

        var sourceCodeLocation = breakpoint.sourceCodeLocation;

        if (this._sourceCode instanceof WebInspector.SourceMapResource) {
            // Update our breakpoint location if the display location changed.
            if (sourceCodeLocation.displaySourceCode !== this._sourceCode)
                return;
            var oldLineInfo = {lineNumber: event.data.oldDisplayLineNumber, columnNumber: event.data.oldDisplayColumnNumber};
            var newLineInfo = {lineNumber: sourceCodeLocation.displayLineNumber, columnNumber: sourceCodeLocation.displayColumnNumber};
        } else {
            // Update our breakpoint location if the original location changed.
            if (sourceCodeLocation.sourceCode !== this._sourceCode)
                return;
            var oldLineInfo = {lineNumber: event.data.oldFormattedLineNumber, columnNumber: event.data.oldFormattedColumnNumber};
            var newLineInfo = {lineNumber: sourceCodeLocation.formattedLineNumber, columnNumber: sourceCodeLocation.formattedColumnNumber};
        }

        var existingBreakpoint = this._breakpointForEditorLineInfo(oldLineInfo);
        if (!existingBreakpoint)
            return;

        console.assert(breakpoint === existingBreakpoint);

        this.setBreakpointInfoForLineAndColumn(oldLineInfo.lineNumber, oldLineInfo.columnNumber, null);
        this.setBreakpointInfoForLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));

        this._removeBreakpointWithEditorLineInfo(breakpoint, oldLineInfo);
        this._addBreakpointWithEditorLineInfo(breakpoint, newLineInfo);
    },

    _breakpointAdded: function(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.data.breakpoint;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (breakpoint === this._ignoreBreakpointAddedBreakpoint)
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
    },

    _breakpointRemoved: function(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.data.breakpoint;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (breakpoint === this._ignoreBreakpointRemovedBreakpoint)
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._removeBreakpointWithEditorLineInfo(breakpoint, lineInfo);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, null);
    },

    _activeCallFrameDidChange: function()
    {
        console.assert(this._supportsDebugging);

        if (this._activeCallFrameSourceCodeLocation) {
            this._activeCallFrameSourceCodeLocation.removeEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
            delete this._activeCallFrameSourceCodeLocation;
        }

        var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
        if (!activeCallFrame || !this._matchesSourceCodeLocation(activeCallFrame.sourceCodeLocation)) {
            this.executionLineNumber = NaN;
            this.executionColumnNumber = NaN;
            return;
        }

        this._dismissPopover();

        this._activeCallFrameSourceCodeLocation = activeCallFrame.sourceCodeLocation;
        this._activeCallFrameSourceCodeLocation.addEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);

        // Don't return early if the line number didn't change. The execution state still
        // could have changed (e.g. continuing in a loop with a breakpoint inside).

        var lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
        this.executionLineNumber = lineInfo.lineNumber;
        this.executionColumnNumber = lineInfo.columnNumber;

        // If we have full content or this source code isn't a Resource we can return early.
        // Script source code populates from the request started in the constructor.
        if (this._fullContentPopulated || !(this._sourceCode instanceof WebInspector.Resource) || this._requestingScriptContent)
            return;

        // Since we are paused in the debugger we need to show some content, and since the Resource
        // content hasn't populated yet we need to populate with content from the Scripts by URL.
        // Document resources will attempt to populate the scripts as inline (in <script> tags.)
        // Other resources are assumed to be full scripts (JavaScript resources).
        if (this._sourceCode.type === WebInspector.Resource.Type.Document)
            this._populateWithInlineScriptContent();
        else
            this._populateWithScriptContent();
    },

    _activeCallFrameSourceCodeLocationChanged: function(event)
    {
        console.assert(!isNaN(this.executionLineNumber));
        if (isNaN(this.executionLineNumber))
            return;

        console.assert(WebInspector.debuggerManager.activeCallFrame);
        console.assert(this._activeCallFrameSourceCodeLocation === WebInspector.debuggerManager.activeCallFrame.sourceCodeLocation);

        var lineInfo = this._editorLineInfoForSourceCodeLocation(this._activeCallFrameSourceCodeLocation);
        this.executionLineNumber = lineInfo.lineNumber;
        this.executionColumnNumber = lineInfo.columnNumber;
    },

    _populateWithInlineScriptContent: function()
    {
        console.assert(this._sourceCode instanceof WebInspector.Resource);
        console.assert(!this._fullContentPopulated);
        console.assert(!this._requestingScriptContent);

        var scripts = this._sourceCode.scripts;
        console.assert(scripts.length);
        if (!scripts.length)
            return;

        var pendingRequestCount = scripts.length;

        // If the number of scripts hasn't change since the last populate, then there is nothing to do.
        if (this._inlineScriptContentPopulated === pendingRequestCount)
            return;

        this._inlineScriptContentPopulated = pendingRequestCount;

        function scriptContentAvailable(parameters)
        {
            // Return early if we are still waiting for content from other scripts.
            if (--pendingRequestCount)
                return;

            delete this._requestingScriptContent;

            // Abort if the full content populated while waiting for these async callbacks.
            if (this._fullContentPopulated)
                return;

            const scriptOpenTag = "<script>";
            const scriptCloseTag = "</script>";

            var content = "";
            var lineNumber = 0;
            var columnNumber = 0;

            this._invalidLineNumbers = {};

            for (var i = 0; i < scripts.length; ++i) {
                // Fill the line gap with newline characters.
                for (var newLinesCount = scripts[i].range.startLine - lineNumber; newLinesCount > 0; --newLinesCount) {
                    if (!columnNumber)
                        this._invalidLineNumbers[scripts[i].range.startLine - newLinesCount] = true;
                    columnNumber = 0;
                    content += "\n";
                }

                // Fill the column gap with space characters.
                for (var spacesCount = scripts[i].range.startColumn - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount)
                    content += " ";

                // Add script tags and content.
                content += scriptOpenTag;
                content += scripts[i].content;
                content += scriptCloseTag;

                lineNumber = scripts[i].range.endLine;
                columnNumber = scripts[i].range.endColumn + scriptCloseTag.length;
            }

            this._populateWithContent(content);
        }

        this._requestingScriptContent = true;

        var boundScriptContentAvailable = scriptContentAvailable.bind(this);
        for (var i = 0; i < scripts.length; ++i)
            scripts[i].requestContent().then(boundScriptContentAvailable);
    },

    _populateWithScriptContent: function()
    {
        console.assert(this._sourceCode instanceof WebInspector.Resource);
        console.assert(!this._fullContentPopulated);
        console.assert(!this._requestingScriptContent);

        // We can assume this resource only has one script that starts at line/column 0.
        var scripts = this._sourceCode.scripts;
        console.assert(scripts.length === 1);
        if (!scripts.length)
            return;

        console.assert(scripts[0].range.startLine === 0);
        console.assert(scripts[0].range.startColumn === 0);

        function scriptContentAvailable(parameters)
        {
            var content = parameters.content;
            delete this._requestingScriptContent;

            // Abort if the full content populated while waiting for this async callback.
            if (this._fullContentPopulated)
                return;

            // This is the full content.
            this._fullContentPopulated = true;

            this._populateWithContent(content);
        }

        this._requestingScriptContent = true;

        scripts[0].requestContent().then(scriptContentAvailable.bind(this));
    },

    _matchesSourceCodeLocation: function(sourceCodeLocation)
    {
        if (this._sourceCode instanceof WebInspector.SourceMapResource)
            return sourceCodeLocation.displaySourceCode === this._sourceCode;
        if (this._sourceCode instanceof WebInspector.Resource)
            return sourceCodeLocation.sourceCode.url === this._sourceCode.url;
        if (this._sourceCode instanceof WebInspector.Script)
            return sourceCodeLocation.sourceCode === this._sourceCode;
        return false;
    },

    _matchesBreakpoint: function(breakpoint)
    {
        console.assert(this._supportsDebugging);
        if (this._sourceCode instanceof WebInspector.SourceMapResource)
            return breakpoint.sourceCodeLocation.displaySourceCode === this._sourceCode;
        if (this._sourceCode instanceof WebInspector.Resource)
            return breakpoint.url === this._sourceCode.url;
        if (this._sourceCode instanceof WebInspector.Script)
            return breakpoint.url === this._sourceCode.url || breakpoint.scriptIdentifier === this._sourceCode.id;
        return false;
    },

    _matchesIssue: function(issue)
    {
        if (this._sourceCode instanceof WebInspector.Resource)
            return issue.url === this._sourceCode.url;
        // FIXME: Support issues for Scripts based on id, not only by URL.
        if (this._sourceCode instanceof WebInspector.Script)
            return issue.url === this._sourceCode.url;
        return false;
    },

    _issueWasAdded: function(event)
    {
        var issue = event.data.issue;
        if (!this._matchesIssue(issue))
            return;

        this._addIssue(issue);
    },

    _addIssue: function(issue)
    {
        // FIXME: Issue should have a SourceCodeLocation.
        var sourceCodeLocation = this._sourceCode.createSourceCodeLocation(issue.lineNumber, issue.columnNumber);
        var lineNumber = sourceCodeLocation.formattedLineNumber;

        var lineNumberIssues = this._issuesLineNumberMap.get(lineNumber);
        if (!lineNumberIssues) {
            lineNumberIssues = [];
            this._issuesLineNumberMap.set(lineNumber, lineNumberIssues);
        }

        // Avoid displaying duplicate issues on the same line.
        for (var existingIssue of lineNumberIssues) {
            if (existingIssue.columnNumber === issue.columnNumber && existingIssue.text === issue.text)
                return;
        }

        lineNumberIssues.push(issue);

        if (issue.level === WebInspector.IssueMessage.Level.Error)
            this.addStyleClassToLine(lineNumber, WebInspector.SourceCodeTextEditor.LineErrorStyleClassName);
        else if (issue.level === WebInspector.IssueMessage.Level.Warning)
            this.addStyleClassToLine(lineNumber, WebInspector.SourceCodeTextEditor.LineWarningStyleClassName);
        else
            console.error("Unknown issue level");

        var widget = this._issueWidgetForLine(lineNumber);
        if (widget) {
            if (issue.level === WebInspector.IssueMessage.Level.Error)
                widget.widgetElement.classList.add(WebInspector.SourceCodeTextEditor.LineErrorStyleClassName);
            else if (issue.level === WebInspector.IssueMessage.Level.Warning)
                widget.widgetElement.classList.add(WebInspector.SourceCodeTextEditor.LineWarningStyleClassName);

            this._updateIssueWidgetForIssues(widget, lineNumberIssues);
        }
    },

    _issueWidgetForLine: function(lineNumber)
    {
        var widget = this._widgetMap.get(lineNumber);
        if (widget)
            return widget;

        widget = this.createWidgetForLine(lineNumber);
        if (!widget)
            return null;

        var widgetElement = widget.widgetElement;
        widgetElement.classList.add("issue-widget");
        widgetElement.classList.add("inline");
        widgetElement.addEventListener("click", this._handleWidgetClick.bind(this, widget, lineNumber));

        this._widgetMap.set(lineNumber, widget);

        return widget;
    },

    _iconClassNameForIssueLevel: function(level)
    {
        if (level === WebInspector.IssueMessage.Level.Warning)
            return "icon-warning";

        console.assert(level === WebInspector.IssueMessage.Level.Error);
        return "icon-error";
    },

    _updateIssueWidgetForIssues: function(widget, issues)
    {
        var widgetElement = widget.widgetElement;
        widgetElement.removeChildren();

        if (widgetElement.classList.contains("inline") || issues.length === 1) {
            var arrowElement = widgetElement.appendChild(document.createElement("span"));
            arrowElement.className = "arrow";

            var iconElement = widgetElement.appendChild(document.createElement("span"));
            iconElement.className = "icon";            

            var textElement = widgetElement.appendChild(document.createElement("span"));
            textElement.className = "text";

            if (issues.length === 1) {
                iconElement.classList.add(this._iconClassNameForIssueLevel(issues[0].level));
                textElement.textContent = issues[0].text;
            } else {
                var errorsCount = 0;
                var warningsCount = 0;
                for (var issue of issues) {
                    if (issue.level === WebInspector.IssueMessage.Level.Error)
                        ++errorsCount;
                    else if (issue.level === WebInspector.IssueMessage.Level.Warning)
                        ++warningsCount;
                }

                if (warningsCount && errorsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WebInspector.UIString("%d Errors, %d Warnings").format(errorsCount, warningsCount);
                } else if (errorsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WebInspector.UIString("%d Errors").format(errorsCount);
                } else if (warningsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WebInspector.UIString("%d Warnings").format(warningsCount);
                }

                widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol] = true;
            }
        } else {
            for (var issue of issues) {
                var iconElement = widgetElement.appendChild(document.createElement("span"));
                iconElement.className = "icon";
                iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));

                var textElement = widgetElement.appendChild(document.createElement("span"));
                textElement.className = "text";
                textElement.textContent = issue.text;

                widgetElement.appendChild(document.createElement("br"));
            }
        }

        widget.update();
    },

    _isWidgetToggleable: function(widget)
    {
        if (widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol])
            return true;

        if (!widget.widgetElement.classList.contains("inline"))
            return true;

        var textElement = widget.widgetElement.lastChild;
        if (textElement.offsetWidth !== textElement.scrollWidth)
            return true;
        
        return false;
    },

    _handleWidgetClick: function(widget, lineNumber, event)
    {
        if (!this._isWidgetToggleable(widget))
            return;

        widget.widgetElement.classList.toggle("inline");

        var lineNumberIssues = this._issuesLineNumberMap.get(lineNumber);
        this._updateIssueWidgetForIssues(widget, lineNumberIssues);
    },

    _breakpointInfoForBreakpoint: function(breakpoint)
    {
        return {resolved: breakpoint.resolved, disabled: breakpoint.disabled, autoContinue: breakpoint.autoContinue};
    },

    get _supportsDebugging()
    {
        if (this._sourceCode instanceof WebInspector.Resource)
            return this._sourceCode.type === WebInspector.Resource.Type.Document || this._sourceCode.type === WebInspector.Resource.Type.Script;
        if (this._sourceCode instanceof WebInspector.Script)
            return true;
        return false;
    },

    // TextEditor Delegate

    textEditorBaseURL: function(textEditor)
    {
        return this._sourceCode.url;
    },

    textEditorShouldHideLineNumber: function(textEditor, lineNumber)
    {
        return lineNumber in this._invalidLineNumbers;
    },

    textEditorGutterContextMenu: function(textEditor, lineNumber, columnNumber, editorBreakpoints, event)
    {
        if (!this._supportsDebugging)
            return;

        event.preventDefault();

        var contextMenu = new WebInspector.ContextMenu(event);

        // Paused. Add Continue to Here option only if we have a script identifier for the location.
        if (WebInspector.debuggerManager.paused) {
            var editorLineInfo = {lineNumber, columnNumber};
            var unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(editorLineInfo);
            var sourceCodeLocation = this._sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);

            if (sourceCodeLocation.sourceCode instanceof WebInspector.Script)
                var script = sourceCodeLocation.sourceCode;
            else if (sourceCodeLocation.sourceCode instanceof WebInspector.Resource)
                var script = sourceCodeLocation.sourceCode.scriptForLocation(sourceCodeLocation);

            if (script) {
                function continueToLocation()
                {
                    WebInspector.debuggerManager.continueToLocation(script.id, sourceCodeLocation.lineNumber, sourceCodeLocation.columnNumber);
                }

                contextMenu.appendItem(WebInspector.UIString("Continue to Here"), continueToLocation);
                contextMenu.appendSeparator();
            }
        }

        var breakpoints = [];
        for (var i = 0; i < editorBreakpoints.length; ++i) {
            var lineInfo = editorBreakpoints[i];
            var breakpoint = this._breakpointForEditorLineInfo(lineInfo);
            console.assert(breakpoint);
            if (breakpoint)
                breakpoints.push(breakpoint);
        }

        // No breakpoints.
        if (!breakpoints.length) {
            function addBreakpoint()
            {
                var data = this.textEditorBreakpointAdded(this, lineNumber, columnNumber);
                this.setBreakpointInfoForLineAndColumn(data.lineNumber, data.columnNumber, data.breakpointInfo);
            }

            contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), addBreakpoint.bind(this));
            contextMenu.show();
            return;
        }

        // Single breakpoint.
        if (breakpoints.length === 1) {
            var breakpoint = breakpoints[0];
            function revealInSidebar()
            {
                WebInspector.debuggerSidebarPanel.show();
                var treeElement = WebInspector.debuggerSidebarPanel.treeElementForRepresentedObject(breakpoint);
                if (treeElement)
                    treeElement.revealAndSelect();
            }

            breakpoint.appendContextMenuItems(contextMenu, event.target);
            contextMenu.appendSeparator();
            contextMenu.appendItem(WebInspector.UIString("Reveal in Debugger Navigation Sidebar"), revealInSidebar);
            contextMenu.show();
            return;
        }

        // Multiple breakpoints.
        var shouldDisable = false;
        for (var i = 0; i < breakpoints.length; ++i) {
            if (!breakpoints[i].disabled) {
                shouldDisable = true;
                break;
            }
        }

        function removeBreakpoints()
        {
            for (var i = 0; i < breakpoints.length; ++i) {
                var breakpoint = breakpoints[i];
                if (WebInspector.debuggerManager.isBreakpointRemovable(breakpoint))
                    WebInspector.debuggerManager.removeBreakpoint(breakpoint);
            }
        }

        function toggleBreakpoints()
        {
            for (var i = 0; i < breakpoints.length; ++i)
                breakpoints[i].disabled = shouldDisable;
        }

        if (shouldDisable)
            contextMenu.appendItem(WebInspector.UIString("Disable Breakpoints"), toggleBreakpoints.bind(this));
        else
            contextMenu.appendItem(WebInspector.UIString("Enable Breakpoints"), toggleBreakpoints.bind(this));
        contextMenu.appendItem(WebInspector.UIString("Delete Breakpoints"), removeBreakpoints.bind(this));
        contextMenu.show();
    },

    textEditorBreakpointAdded: function(textEditor, lineNumber, columnNumber)
    {
        if (!this._supportsDebugging)
            return null;

        var editorLineInfo = {lineNumber, columnNumber};
        var unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(editorLineInfo);
        var sourceCodeLocation = this._sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);
        var breakpoint = new WebInspector.Breakpoint(sourceCodeLocation);

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);

        this._ignoreBreakpointAddedBreakpoint = breakpoint;

        var shouldSkipEventDispatch = false;
        var shouldSpeculativelyResolveBreakpoint = true;
        WebInspector.debuggerManager.addBreakpoint(breakpoint, shouldSkipEventDispatch, shouldSpeculativelyResolveBreakpoint);
        delete this._ignoreBreakpointAddedBreakpoint;

        // Return the more accurate location and breakpoint info.
        return {
            breakpointInfo: this._breakpointInfoForBreakpoint(breakpoint),
            lineNumber: lineInfo.lineNumber,
            columnNumber: lineInfo.columnNumber
        };
    },

    textEditorBreakpointRemoved: function(textEditor, lineNumber, columnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var lineInfo = {lineNumber, columnNumber};
        var breakpoint = this._breakpointForEditorLineInfo(lineInfo);
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        this._removeBreakpointWithEditorLineInfo(breakpoint, lineInfo);

        this._ignoreBreakpointRemovedBreakpoint = breakpoint;
        WebInspector.debuggerManager.removeBreakpoint(breakpoint);
        delete this._ignoreBreakpointAddedBreakpoint;
    },

    textEditorBreakpointMoved: function(textEditor, oldLineNumber, oldColumnNumber, newLineNumber, newColumnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var oldLineInfo = {lineNumber: oldLineNumber, columnNumber: oldColumnNumber};
        var breakpoint = this._breakpointForEditorLineInfo(oldLineInfo);
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        this._removeBreakpointWithEditorLineInfo(breakpoint, oldLineInfo);

        var newLineInfo = {lineNumber: newLineNumber, columnNumber: newColumnNumber};
        var unformattedNewLineInfo = this._unformattedLineInfoForEditorLineInfo(newLineInfo);
        this._ignoreLocationUpdateBreakpoint = breakpoint;
        breakpoint.sourceCodeLocation.update(this._sourceCode, unformattedNewLineInfo.lineNumber, unformattedNewLineInfo.columnNumber);
        delete this._ignoreLocationUpdateBreakpoint;

        var accurateNewLineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, accurateNewLineInfo);

        if (accurateNewLineInfo.lineNumber !== newLineInfo.lineNumber || accurateNewLineInfo.columnNumber !== newLineInfo.columnNumber)
            this.updateBreakpointLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, accurateNewLineInfo.lineNumber, accurateNewLineInfo.columnNumber);
    },

    textEditorBreakpointClicked: function(textEditor, lineNumber, columnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var breakpoint = this._breakpointForEditorLineInfo({lineNumber, columnNumber});
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        breakpoint.cycleToNextMode();
    },

    textEditorUpdatedFormatting: function(textEditor)
    {
        this._ignoreAllBreakpointLocationUpdates = true;
        this._sourceCode.formatterSourceMap = this.formatterSourceMap;
        delete this._ignoreAllBreakpointLocationUpdates;

        // Always put the source map on both the Script and Resource if both exist. For example,
        // if this SourceCode is a Resource, then there might also be a Script. In the debugger,
        // the backend identifies call frames with Script line and column information, and the
        // Script needs the formatter source map to produce the proper display line and column.
        if (this._sourceCode instanceof WebInspector.Resource && !(this._sourceCode instanceof WebInspector.SourceMapResource)) {
            var scripts = this._sourceCode.scripts;
            for (var i = 0; i < scripts.length; ++i)
                scripts[i].formatterSourceMap = this.formatterSourceMap;
        } else if (this._sourceCode instanceof WebInspector.Script) {
            if (this._sourceCode.resource)
                this._sourceCode.resource.formatterSourceMap = this.formatterSourceMap;
        }

        // Some breakpoints / issues may have moved, some might not have. Just go through
        // and remove and reinsert all the breakpoints / issues.

        var oldBreakpointMap = this._breakpointMap;
        this._breakpointMap = {};

        for (var lineNumber in oldBreakpointMap) {
            for (var columnNumber in oldBreakpointMap[lineNumber]) {
                var breakpoint = oldBreakpointMap[lineNumber][columnNumber];
                var newLineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                this._addBreakpointWithEditorLineInfo(breakpoint, newLineInfo);
                this.setBreakpointInfoForLineAndColumn(lineNumber, columnNumber, null);
                this.setBreakpointInfoForLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
            }
        }

        this._reinsertAllIssues();
    },

    _clearWidgets: function()
    {
        for (var widget of this._widgetMap.values())
            widget.clear();

        this._widgetMap.clear();
    },

    _reinsertAllIssues: function()
    {
        this._issuesLineNumberMap.clear();
        this._clearWidgets();

        var issues = WebInspector.issueManager.issuesForSourceCode(this._sourceCode);
        for (var issue of issues) {
            console.assert(this._matchesIssue(issue));
            this._addIssue(issue);
        }
    },

    _debuggerDidPause: function(event)
    {
        this._updateTokenTrackingControllerState();
        if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            this._typeTokenAnnotator.refresh();
        if (this._basicBlockAnnotator && this._basicBlockAnnotator.isActive())
            this._basicBlockAnnotator.refresh();
    },

    _debuggerDidResume: function(event)
    {
        this._updateTokenTrackingControllerState();
        this._dismissPopover();
        if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            this._typeTokenAnnotator.refresh();
        if (this._basicBlockAnnotator && this._basicBlockAnnotator.isActive())
            this._basicBlockAnnotator.refresh();
    },

    _sourceCodeSourceMapAdded: function(event)
    {
        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
        this._sourceCode.removeEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);

        this._updateTokenTrackingControllerState();
    },

    _updateTokenTrackingControllerState: function()
    {
        var mode = WebInspector.CodeMirrorTokenTrackingController.Mode.None;
        if (WebInspector.debuggerManager.paused)
            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression;
        else if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation;
        else if (this._hasColorMarkers())
            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens;
        else if ((this._sourceCode instanceof WebInspector.SourceMapResource || this._sourceCode.sourceMaps.length !== 0) && WebInspector.modifierKeys.metaKey && !WebInspector.modifierKeys.altKey && !WebInspector.modifierKeys.shiftKey)
            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;

        this.tokenTrackingController.enabled = mode !== WebInspector.CodeMirrorTokenTrackingController.Mode.None;

        if (mode === this.tokenTrackingController.mode)
            return;

        switch (mode) {
        case WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
            this.tokenTrackingController.mouseOverDelayDuration = 0;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
            break;
        case WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens:
            this.tokenTrackingController.mouseOverDelayDuration = 0;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
            this.tokenTrackingController.classNameForHighlightedRange = WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
            this._dismissPopover();
            break;
        case WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
        case WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation:
            this.tokenTrackingController.mouseOverDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease;
            this.tokenTrackingController.classNameForHighlightedRange = WebInspector.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName;
            break;
        }

        this.tokenTrackingController.mode = mode;
    },

    _hasColorMarkers: function()
    {
        for (var marker of this.markers) {
            if (marker.type === WebInspector.TextMarker.Type.Color)
                return true;
        }
        return false;
    },

    // CodeMirrorTokenTrackingController Delegate

    tokenTrackingControllerCanReleaseHighlightedRange: function(tokenTrackingController, element)
    {
        if (!this._popover)
            return true;

        if (!window.getSelection().isCollapsed && this._popover.element.contains(window.getSelection().anchorNode))
            return false;

        return true;
    },

    tokenTrackingControllerHighlightedRangeReleased: function(tokenTrackingController)
    {
        if (!this._mouseIsOverPopover)
            this._dismissPopover();
    },

    tokenTrackingControllerHighlightedRangeWasClicked: function(tokenTrackingController)
    {
        if (this.tokenTrackingController.mode !== WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens)
            return;

        // Links are handled by TextEditor.
        if (/\blink\b/.test(this.tokenTrackingController.candidate.hoveredToken.type))
            return;

        var sourceCodeLocation = this._sourceCodeLocationForEditorPosition(this.tokenTrackingController.candidate.hoveredTokenRange.start);
        if (this.sourceCode instanceof WebInspector.SourceMapResource)
            WebInspector.resourceSidebarPanel.showOriginalOrFormattedSourceCodeLocation(sourceCodeLocation);
        else
            WebInspector.resourceSidebarPanel.showSourceCodeLocation(sourceCodeLocation);
    },

    tokenTrackingControllerNewHighlightCandidate: function(tokenTrackingController, candidate)
    {
        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens) {
            this.tokenTrackingController.highlightRange(candidate.hoveredTokenRange);
            return;
        }

        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression) {
            this._tokenTrackingControllerHighlightedJavaScriptExpression(candidate);
            return;
        }

        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation) {
            this._tokenTrackingControllerHighlightedJavaScriptTypeInformation(candidate);
            return;
        }

        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens) {
            var markers = this.markersAtPosition(candidate.hoveredTokenRange.start);
            if (markers.length > 0)
                this._tokenTrackingControllerHighlightedMarkedExpression(candidate, markers);
            else
                this._dismissEditingController();
        }
    },

    tokenTrackingControllerMouseOutOfHoveredMarker: function(tokenTrackingController, hoveredMarker)
    {
        this._dismissEditingController();
    },

    _tokenTrackingControllerHighlightedJavaScriptExpression: function(candidate)
    {
        console.assert(candidate.expression);

        function populate(error, result, wasThrown)
        {
            if (error || wasThrown)
                return;

            if (candidate !== this.tokenTrackingController.candidate)
                return;

            var data = WebInspector.RemoteObject.fromPayload(result);
            switch (data.type) {
            case "function":
                this._showPopoverForFunction(data);
                break;
            case "object":
                if (data.subtype === "null" || data.subtype === "regexp")
                    this._showPopoverWithFormattedValue(data);
                else
                    this._showPopoverForObject(data);
                break;
            case "string":
            case "number":
            case "boolean":
            case "undefined":
            case "symbol":
                this._showPopoverWithFormattedValue(data);
                break;
            }
        }

        if (WebInspector.debuggerManager.activeCallFrame) {
            DebuggerAgent.evaluateOnCallFrame.invoke({callFrameId: WebInspector.debuggerManager.activeCallFrame.id, expression: candidate.expression, objectGroup: "popover", doNotPauseOnExceptionsAndMuteConsole: true}, populate.bind(this));
            return;
        }

        // No call frame available. Use the main page's context.
        RuntimeAgent.evaluate.invoke({expression: candidate.expression, objectGroup: "popover", doNotPauseOnExceptionsAndMuteConsole: true}, populate.bind(this));
    },

    _tokenTrackingControllerHighlightedJavaScriptTypeInformation: function(candidate)
    {
        console.assert(candidate.expression);

        var sourceCode = this._sourceCode;
        var sourceID = sourceCode.scripts[0].id;
        var range = candidate.hoveredTokenRange;
        var offset = this.currentPositionToOriginalOffset({line: range.start.line, ch: range.start.ch});

        var allRequests = [{
            typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
            sourceID,
            divot: offset
        }];

        function handler(error, allTypes) {
            if (error)
                return;

            if (candidate !== this.tokenTrackingController.candidate)
                return;

            console.assert(allTypes.length === 1);
            if (!allTypes.length)
                return;
            var types = allTypes[0];
            if (types.isValid) {
                var popoverTitle = WebInspector.TypeTokenView.titleForPopover(WebInspector.TypeTokenView.TitleType.Variable, candidate.expression);
                this.showPopoverForTypes(types, null, popoverTitle);
            }
        }

        RuntimeAgent.getRuntimeTypesForVariablesAtOffsets(allRequests, handler.bind(this));
    },

    _showPopover: function(content, bounds)
    {
        console.assert(this.tokenTrackingController.candidate || bounds);

        var shouldHighlightRange = false;
        var candidate = this.tokenTrackingController.candidate;
        // If bounds is falsey, this is a popover introduced from a hover event.
        // Otherwise, this is called from TypeTokenAnnotator.
        if (!bounds) {
            if (!candidate)
                return;

            var rects = this.rectsForRange(candidate.hoveredTokenRange);
            bounds = WebInspector.Rect.unionOfRects(rects);

            shouldHighlightRange = true;
        }

        content.classList.add(WebInspector.SourceCodeTextEditor.PopoverDebuggerContentStyleClassName);

        this._popover = this._popover || new WebInspector.Popover(this);
        this._popover.presentNewContentWithFrame(content, bounds.pad(5), [WebInspector.RectEdge.MIN_Y, WebInspector.RectEdge.MAX_Y, WebInspector.RectEdge.MAX_X]);
        if (shouldHighlightRange)
            this.tokenTrackingController.highlightRange(candidate.expressionRange);

        this._trackPopoverEvents();
    },

    _showPopoverForFunction: function(data)
    {
        var candidate = this.tokenTrackingController.candidate;

        function didGetDetails(error, response)
        {
            if (error) {
                console.error(error);
                this._dismissPopover();
                return;
            }

            // Nothing to do if the token has changed since the time we
            // asked for the function details from the backend.
            if (candidate !== this.tokenTrackingController.candidate)
                return;

            var wrapper = document.createElement("div");
            wrapper.className = "body formatted-function";
            wrapper.textContent = data.description;

            var content = document.createElement("div");
            content.className = "function";

            var title = content.appendChild(document.createElement("div"));
            title.className = "title";
            title.textContent = response.name || response.inferredName || response.displayName || WebInspector.UIString("(anonymous function)");

            content.appendChild(wrapper);

            this._showPopover(content);
        }
        DebuggerAgent.getFunctionDetails(data.objectId, didGetDetails.bind(this));
    },

    _showPopoverForObject: function(data)
    {
        var content = document.createElement("div");
        content.className = "object expandable";

        var titleElement = document.createElement("div");
        titleElement.className = "title";
        titleElement.textContent = data.description;
        content.appendChild(titleElement);

        // FIXME: If this is a variable, it would be nice to put the variable name in the PropertyPath.
        var objectTree = new WebInspector.ObjectTreeView(data, WebInspector.ObjectTreeView.Mode.Properties, null);
        objectTree.showOnlyProperties();
        objectTree.expand();

        var bodyElement = content.appendChild(document.createElement("div"));
        bodyElement.className = "body";
        bodyElement.appendChild(objectTree.element);

        this._showPopover(content);
    },

    _showPopoverWithFormattedValue: function(remoteObject)
    {
        var content = WebInspector.FormattedValue.createElementForRemoteObject(remoteObject);
        this._showPopover(content);
    },

    willDismissPopover: function(popover)
    {
        this.tokenTrackingController.removeHighlightedRange();

        RuntimeAgent.releaseObjectGroup("popover");
    },

    _dismissPopover: function()
    {
        if (!this._popover)
            return;

        this._popover.dismiss();

        if (this._popoverEventListeners && this._popoverEventListenersAreRegistered) {
            this._popoverEventListenersAreRegistered = false;
            this._popoverEventListeners.unregister();
        }
    },

    _trackPopoverEvents: function()
    {
        if (!this._popoverEventListeners) 
            this._popoverEventListeners = new WebInspector.EventListenerSet(this, "Popover listeners");
        if (!this._popoverEventListenersAreRegistered) {
            this._popoverEventListenersAreRegistered = true;
            this._popoverEventListeners.register(this._popover.element, "mouseover", this._popoverMouseover);
            this._popoverEventListeners.register(this._popover.element, "mouseout", this._popoverMouseout);
            this._popoverEventListeners.install();
        }
    },

    _popoverMouseover: function(event)
    {
        this._mouseIsOverPopover = true;
    },

    _popoverMouseout: function(event)
    {
        this._mouseIsOverPopover = this._popover.element.contains(event.relatedTarget);
    },

    _updateEditableMarkers: function(range)
    {
        this.createColorMarkers(range);
        this.createGradientMarkers(range);

        this._updateTokenTrackingControllerState();
    },

    _tokenTrackingControllerHighlightedMarkedExpression: function(candidate, markers)
    {
        // Look for the outermost editable marker.
        var editableMarker;
        for (var marker of markers) {
            if (!marker.range || (marker.type !== WebInspector.TextMarker.Type.Color && marker.type !== WebInspector.TextMarker.Type.Gradient))
                continue;

            if (!editableMarker || (marker.range.startLine < editableMarker.range.startLine || (marker.range.startLine === editableMarker.range.startLine && marker.range.startColumn < editableMarker.range.startColumn)))
                editableMarker = marker;
        }

        if (!editableMarker) {
            this.tokenTrackingController.hoveredMarker = null;
            return;
        }

        if (this.tokenTrackingController.hoveredMarker === editableMarker)
            return;

        this._dismissEditingController();

        this.tokenTrackingController.hoveredMarker = editableMarker;

        this._editingController = this.editingControllerForMarker(editableMarker);

        if (marker.type === WebInspector.TextMarker.Type.Color) {
            var color = this._editingController.value;
            if (!color || !color.valid) {
                editableMarker.clear();
                delete this._editingController;
                return;
            }
        }

        this._editingController.delegate = this;
        this._editingController.presentHoverMenu();
    },

    _dismissEditingController: function(discrete)
    {
        if (this._editingController)
            this._editingController.dismissHoverMenu(discrete);
        
        this.tokenTrackingController.hoveredMarker = null;
        delete this._editingController;
    },

    // CodeMirrorEditingController Delegate
    
    editingControllerDidStartEditing: function(editingController)
    {
        // We can pause the token tracking controller during editing, it will be reset
        // to the expected state by calling _updateEditableMarkers() in the
        // editingControllerDidFinishEditing delegate.
        this.tokenTrackingController.enabled = false;

        // We clear the marker since we'll reset it after editing.
        editingController.marker.clear();
        
        // We ignore content changes made as a result of color editing.
        this._ignoreContentDidChange++;
    },
    
    editingControllerDidFinishEditing: function(editingController)
    {
        this._updateEditableMarkers(editingController.range);

        this._ignoreContentDidChange--;

        delete this._editingController;
    },

    _setTypeTokenAnnotatorEnabledState: function(shouldActivate)
    {
        console.assert(this._typeTokenAnnotator);
        if (!this._typeTokenAnnotator)
            return;

        if (shouldActivate) {
            RuntimeAgent.enableTypeProfiler();

            this._typeTokenAnnotator.reset();
            if (this._basicBlockAnnotator) {
                console.assert(!this._basicBlockAnnotator.isActive());
                this._basicBlockAnnotator.reset();
            }

            if (!this._typeTokenScrollHandler)
                this._enableScrollEventsForTypeTokenAnnotator();
        } else {
            // Because we disable type profiling when exiting the inspector, there is no need to call 
            // RuntimeAgent.disableTypeProfiler() here.  If we were to call it here, JavaScriptCore would 
            // compile out all the necessary type profiling information, so if a user were to quickly press then 
            // unpress the type profiling button, we wouldn't be able to re-show type information which would 
            // provide a confusing user experience.

            this._typeTokenAnnotator.clear();
            if (this._basicBlockAnnotator)
                this._basicBlockAnnotator.clear();

            if (this._typeTokenScrollHandler)
                this._disableScrollEventsForTypeTokenAnnotator();
        }

        WebInspector.showJavaScriptTypeInformationSetting.value = shouldActivate;

        this._updateTokenTrackingControllerState();
    },

    _getAssociatedScript: function()
    {
        var script = null;
        // FIXME: This needs to me modified to work with HTML files with inline script tags.
        if (this._sourceCode instanceof WebInspector.Script)
            script = this._sourceCode;
        else if (this._sourceCode instanceof WebInspector.Resource && this._sourceCode.type === WebInspector.Resource.Type.Script && this._sourceCode.scripts.length)
            script = this._sourceCode.scripts[0];
        return script;
    },

    _makeTypeTokenAnnotator: function()
    {
        if (!RuntimeAgent.getRuntimeTypesForVariablesAtOffsets)
            return;

        var script = this._getAssociatedScript();
        if (!script)
            return;

        this._typeTokenAnnotator = new WebInspector.TypeTokenAnnotator(this, script);
    },

    _makeBasicBlockAnnotator: function()
    {
        if (!RuntimeAgent.getBasicBlocks)
            return;

        var script = this._getAssociatedScript();
        if (!script)
            return;

        this._basicBlockAnnotator = new WebInspector.BasicBlockAnnotator(this, script);
    },

    _enableScrollEventsForTypeTokenAnnotator: function()
    {
        // Pause updating type tokens while scrolling to prevent frame loss.
        console.assert(!this._typeTokenScrollHandler);
        this._typeTokenScrollHandler = this._makeTypeTokenScrollEventHandler();
        this.addScrollHandler(this._typeTokenScrollHandler);
    },

    _disableScrollEventsForTypeTokenAnnotator: function()
    {
        console.assert(this._typeTokenScrollHandler);
        this.removeScrollHandler(this._typeTokenScrollHandler);
        this._typeTokenScrollHandler = null;
    },

    _makeTypeTokenScrollEventHandler: function()
    {
        var timeoutIdentifier = null;
        function scrollHandler()
        {
            if (timeoutIdentifier)
                clearTimeout(timeoutIdentifier);
            else {
                if (this._typeTokenAnnotator)
                    this._typeTokenAnnotator.pause();
                if (this._basicBlockAnnotator)
                    this._basicBlockAnnotator.pause();
            }

            timeoutIdentifier = setTimeout(function() {
                timeoutIdentifier = null;
                if (this._typeTokenAnnotator)
                    this._typeTokenAnnotator.resume();
                if (this._basicBlockAnnotator)
                    this._basicBlockAnnotator.resume();
            }.bind(this), WebInspector.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling);
        }

        return scrollHandler.bind(this);
    }
};

WebInspector.SourceCodeTextEditor.prototype.__proto__ = WebInspector.TextEditor.prototype;
