Added MacOS SDK
This commit is contained in:
@@ -0,0 +1,636 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
WI.CodeMirrorTokenTrackingController = class CodeMirrorTokenTrackingController extends WI.Object
|
||||
{
|
||||
constructor(codeMirror, delegate)
|
||||
{
|
||||
super();
|
||||
|
||||
console.assert(codeMirror);
|
||||
|
||||
this._codeMirror = codeMirror;
|
||||
this._delegate = delegate || null;
|
||||
this._mode = WI.CodeMirrorTokenTrackingController.Mode.None;
|
||||
|
||||
this._mouseOverDelayDuration = 0;
|
||||
this._mouseOutReleaseDelayDuration = 0;
|
||||
this._classNameForHighlightedRange = null;
|
||||
|
||||
this._enabled = false;
|
||||
this._tracking = false;
|
||||
this._previousTokenInfo = null;
|
||||
this._hoveredMarker = null;
|
||||
this._ignoreNextMouseMove = false;
|
||||
|
||||
const hidePopover = this._hidePopover.bind(this);
|
||||
|
||||
this._codeMirror.addKeyMap({
|
||||
"Cmd-Enter": this._handleCommandEnterKey.bind(this),
|
||||
"Esc": hidePopover
|
||||
});
|
||||
|
||||
this._codeMirror.on("cursorActivity", hidePopover);
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
get delegate()
|
||||
{
|
||||
return this._delegate;
|
||||
}
|
||||
|
||||
set delegate(x)
|
||||
{
|
||||
this._delegate = x;
|
||||
}
|
||||
|
||||
get enabled()
|
||||
{
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
set enabled(enabled)
|
||||
{
|
||||
if (this._enabled === enabled)
|
||||
return;
|
||||
|
||||
this._enabled = enabled;
|
||||
|
||||
var wrapper = this._codeMirror.getWrapperElement();
|
||||
if (enabled) {
|
||||
wrapper.addEventListener("mouseenter", this);
|
||||
wrapper.addEventListener("mouseleave", this);
|
||||
this._updateHoveredTokenInfo({left: WI.mouseCoords.x, top: WI.mouseCoords.y});
|
||||
this._startTracking();
|
||||
} else {
|
||||
wrapper.removeEventListener("mouseenter", this);
|
||||
wrapper.removeEventListener("mouseleave", this);
|
||||
this._stopTracking();
|
||||
}
|
||||
}
|
||||
|
||||
get mode()
|
||||
{
|
||||
return this._mode;
|
||||
}
|
||||
|
||||
set mode(mode)
|
||||
{
|
||||
var oldMode = this._mode;
|
||||
|
||||
this._mode = mode || WI.CodeMirrorTokenTrackingController.Mode.None;
|
||||
|
||||
if (oldMode !== this._mode && this._tracking && this._previousTokenInfo)
|
||||
this._processNewHoveredToken(this._previousTokenInfo);
|
||||
}
|
||||
|
||||
get mouseOverDelayDuration()
|
||||
{
|
||||
return this._mouseOverDelayDuration;
|
||||
}
|
||||
|
||||
set mouseOverDelayDuration(x)
|
||||
{
|
||||
console.assert(x >= 0);
|
||||
this._mouseOverDelayDuration = Math.max(x, 0);
|
||||
}
|
||||
|
||||
get mouseOutReleaseDelayDuration()
|
||||
{
|
||||
return this._mouseOutReleaseDelayDuration;
|
||||
}
|
||||
|
||||
set mouseOutReleaseDelayDuration(x)
|
||||
{
|
||||
console.assert(x >= 0);
|
||||
this._mouseOutReleaseDelayDuration = Math.max(x, 0);
|
||||
}
|
||||
|
||||
get classNameForHighlightedRange()
|
||||
{
|
||||
return this._classNameForHighlightedRange;
|
||||
}
|
||||
|
||||
set classNameForHighlightedRange(x)
|
||||
{
|
||||
this._classNameForHighlightedRange = x || null;
|
||||
}
|
||||
|
||||
get candidate()
|
||||
{
|
||||
return this._candidate;
|
||||
}
|
||||
|
||||
get hoveredMarker()
|
||||
{
|
||||
return this._hoveredMarker;
|
||||
}
|
||||
|
||||
set hoveredMarker(hoveredMarker)
|
||||
{
|
||||
this._hoveredMarker = hoveredMarker;
|
||||
}
|
||||
|
||||
highlightLastHoveredRange()
|
||||
{
|
||||
if (this._candidate)
|
||||
this.highlightRange(this._candidate.hoveredTokenRange);
|
||||
}
|
||||
|
||||
highlightRange(range)
|
||||
{
|
||||
// Nothing to do if we're trying to highlight the same range.
|
||||
if (this._codeMirrorMarkedText && this._codeMirrorMarkedText.className === this._classNameForHighlightedRange) {
|
||||
var highlightedRange = this._codeMirrorMarkedText.find();
|
||||
if (!highlightedRange)
|
||||
return;
|
||||
if (WI.compareCodeMirrorPositions(highlightedRange.from, range.start) === 0 &&
|
||||
WI.compareCodeMirrorPositions(highlightedRange.to, range.end) === 0)
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeHighlightedRange();
|
||||
|
||||
var className = this._classNameForHighlightedRange || "";
|
||||
this._codeMirrorMarkedText = this._codeMirror.markText(range.start, range.end, {className});
|
||||
|
||||
window.addEventListener("mousemove", this, true);
|
||||
}
|
||||
|
||||
removeHighlightedRange()
|
||||
{
|
||||
if (!this._codeMirrorMarkedText)
|
||||
return;
|
||||
|
||||
this._codeMirrorMarkedText.clear();
|
||||
this._codeMirrorMarkedText = null;
|
||||
|
||||
window.removeEventListener("mousemove", this, true);
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_startTracking()
|
||||
{
|
||||
if (this._tracking)
|
||||
return;
|
||||
|
||||
this._tracking = true;
|
||||
this._ignoreNextMouseMove = false;
|
||||
|
||||
var wrapper = this._codeMirror.getWrapperElement();
|
||||
wrapper.addEventListener("mousemove", this, true);
|
||||
wrapper.addEventListener("mouseout", this, false);
|
||||
wrapper.addEventListener("mousedown", this, false);
|
||||
wrapper.addEventListener("mouseup", this, false);
|
||||
wrapper.addEventListener("mousewheel", this, false);
|
||||
window.addEventListener("blur", this, true);
|
||||
}
|
||||
|
||||
_stopTracking()
|
||||
{
|
||||
if (!this._tracking)
|
||||
return;
|
||||
|
||||
this._tracking = false;
|
||||
this._candidate = null;
|
||||
|
||||
var wrapper = this._codeMirror.getWrapperElement();
|
||||
wrapper.removeEventListener("mousemove", this, true);
|
||||
wrapper.removeEventListener("mouseout", this, false);
|
||||
wrapper.removeEventListener("mousedown", this, false);
|
||||
wrapper.removeEventListener("mouseup", this, false);
|
||||
wrapper.removeEventListener("mousewheel", this, false);
|
||||
window.removeEventListener("blur", this, true);
|
||||
window.removeEventListener("mousemove", this, true);
|
||||
|
||||
this._resetTrackingStates();
|
||||
}
|
||||
|
||||
handleEvent(event)
|
||||
{
|
||||
switch (event.type) {
|
||||
case "mouseenter":
|
||||
this._mouseEntered(event);
|
||||
break;
|
||||
case "mouseleave":
|
||||
this._mouseLeft(event);
|
||||
break;
|
||||
case "mousemove":
|
||||
if (event.currentTarget === window)
|
||||
this._mouseMovedWithMarkedText(event);
|
||||
else
|
||||
this._mouseMovedOverEditor(event);
|
||||
break;
|
||||
case "mouseout":
|
||||
// Only deal with a mouseout event that has the editor wrapper as the target.
|
||||
if (!event.currentTarget.contains(event.relatedTarget))
|
||||
this._mouseMovedOutOfEditor(event);
|
||||
break;
|
||||
case "mousedown":
|
||||
this._mouseButtonWasPressedOverEditor(event);
|
||||
break;
|
||||
case "mouseup":
|
||||
this._mouseButtonWasReleasedOverEditor(event);
|
||||
break;
|
||||
case "mousewheel":
|
||||
this._ignoreNextMouseMove = true;
|
||||
break;
|
||||
case "blur":
|
||||
this._windowLostFocus(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_handleCommandEnterKey(codeMirror)
|
||||
{
|
||||
const tokenInfo = this._getTokenInfoForPosition(codeMirror.getCursor("head"));
|
||||
tokenInfo.triggeredBy = WI.CodeMirrorTokenTrackingController.TriggeredBy.Keyboard;
|
||||
this._processNewHoveredToken(tokenInfo);
|
||||
}
|
||||
|
||||
_hidePopover()
|
||||
{
|
||||
if (!this._candidate)
|
||||
return CodeMirror.Pass;
|
||||
|
||||
if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeReleased === "function") {
|
||||
const forceHidePopover = true;
|
||||
this._delegate.tokenTrackingControllerHighlightedRangeReleased(this, forceHidePopover);
|
||||
}
|
||||
}
|
||||
|
||||
_mouseEntered(event)
|
||||
{
|
||||
if (!this._tracking)
|
||||
this._startTracking();
|
||||
}
|
||||
|
||||
_mouseLeft(event)
|
||||
{
|
||||
this._stopTracking();
|
||||
}
|
||||
|
||||
_mouseMovedWithMarkedText(event)
|
||||
{
|
||||
if (this._candidate && this._candidate.triggeredBy === WI.CodeMirrorTokenTrackingController.TriggeredBy.Keyboard)
|
||||
return;
|
||||
|
||||
var shouldRelease = !event.target.classList.contains(this._classNameForHighlightedRange);
|
||||
if (shouldRelease && this._delegate && typeof this._delegate.tokenTrackingControllerCanReleaseHighlightedRange === "function")
|
||||
shouldRelease = this._delegate.tokenTrackingControllerCanReleaseHighlightedRange(this, event.target);
|
||||
|
||||
if (shouldRelease) {
|
||||
if (!this._markedTextMouseoutTimer)
|
||||
this._markedTextMouseoutTimer = setTimeout(this._markedTextIsNoLongerHovered.bind(this), this._mouseOutReleaseDelayDuration);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._markedTextMouseoutTimer)
|
||||
clearTimeout(this._markedTextMouseoutTimer);
|
||||
|
||||
this._markedTextMouseoutTimer = 0;
|
||||
}
|
||||
|
||||
_markedTextIsNoLongerHovered()
|
||||
{
|
||||
if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeReleased === "function")
|
||||
this._delegate.tokenTrackingControllerHighlightedRangeReleased(this);
|
||||
|
||||
this._markedTextMouseoutTimer = 0;
|
||||
}
|
||||
|
||||
_mouseMovedOverEditor(event)
|
||||
{
|
||||
if (this._ignoreNextMouseMove) {
|
||||
this._ignoreNextMouseMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateHoveredTokenInfo({left: event.pageX, top: event.pageY});
|
||||
}
|
||||
|
||||
_updateHoveredTokenInfo(mouseCoords)
|
||||
{
|
||||
// Get the position in the text and the token at that position.
|
||||
var position = this._codeMirror.coordsChar(mouseCoords);
|
||||
var token = this._codeMirror.getTokenAt(position);
|
||||
|
||||
if (!token || !token.type || !token.string) {
|
||||
if (this._hoveredMarker && this._delegate && typeof this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker === "function") {
|
||||
if (!this._codeMirror.findMarksAt(position).includes(this._hoveredMarker.codeMirrorTextMarker))
|
||||
this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker(this, this._hoveredMarker);
|
||||
}
|
||||
|
||||
this._resetTrackingStates();
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop right here if we're hovering the same token as we were last time.
|
||||
if (this._previousTokenInfo &&
|
||||
this._previousTokenInfo.position.line === position.line &&
|
||||
this._previousTokenInfo.token.start === token.start &&
|
||||
this._previousTokenInfo.token.end === token.end)
|
||||
return;
|
||||
|
||||
// We have a new hovered token.
|
||||
var tokenInfo = this._previousTokenInfo = this._getTokenInfoForPosition(position);
|
||||
|
||||
if (/\bmeta\b/.test(token.type)) {
|
||||
let nextTokenPosition = Object.shallowCopy(position);
|
||||
nextTokenPosition.ch = tokenInfo.token.end + 1;
|
||||
|
||||
let nextToken = this._codeMirror.getTokenAt(nextTokenPosition);
|
||||
if (nextToken && nextToken.type && !/\bmeta\b/.test(nextToken.type)) {
|
||||
console.assert(tokenInfo.token.end === nextToken.start);
|
||||
|
||||
tokenInfo.token.type = nextToken.type;
|
||||
tokenInfo.token.string = tokenInfo.token.string + nextToken.string;
|
||||
tokenInfo.token.end = nextToken.end;
|
||||
}
|
||||
} else {
|
||||
let previousTokenPosition = Object.shallowCopy(position);
|
||||
previousTokenPosition.ch = tokenInfo.token.start - 1;
|
||||
|
||||
let previousToken = this._codeMirror.getTokenAt(previousTokenPosition);
|
||||
if (previousToken && previousToken.type && /\bmeta\b/.test(previousToken.type)) {
|
||||
console.assert(tokenInfo.token.start === previousToken.end);
|
||||
|
||||
tokenInfo.token.string = previousToken.string + tokenInfo.token.string;
|
||||
tokenInfo.token.start = previousToken.start;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._tokenHoverTimer)
|
||||
clearTimeout(this._tokenHoverTimer);
|
||||
|
||||
this._tokenHoverTimer = 0;
|
||||
|
||||
if (this._codeMirrorMarkedText || !this._mouseOverDelayDuration)
|
||||
this._processNewHoveredToken(tokenInfo);
|
||||
else
|
||||
this._tokenHoverTimer = setTimeout(this._processNewHoveredToken.bind(this, tokenInfo), this._mouseOverDelayDuration);
|
||||
}
|
||||
|
||||
_getTokenInfoForPosition(position)
|
||||
{
|
||||
var token = this._codeMirror.getTokenAt(position);
|
||||
var innerMode = CodeMirror.innerMode(this._codeMirror.getMode(), token.state);
|
||||
var codeMirrorModeName = innerMode.mode.alternateName || innerMode.mode.name;
|
||||
return {
|
||||
token,
|
||||
position,
|
||||
innerMode,
|
||||
modeName: codeMirrorModeName
|
||||
};
|
||||
}
|
||||
|
||||
_mouseMovedOutOfEditor(event)
|
||||
{
|
||||
if (this._tokenHoverTimer)
|
||||
clearTimeout(this._tokenHoverTimer);
|
||||
|
||||
this._tokenHoverTimer = 0;
|
||||
this._previousTokenInfo = null;
|
||||
this._selectionMayBeInProgress = false;
|
||||
}
|
||||
|
||||
_mouseButtonWasPressedOverEditor(event)
|
||||
{
|
||||
this._selectionMayBeInProgress = true;
|
||||
}
|
||||
|
||||
_mouseButtonWasReleasedOverEditor(event)
|
||||
{
|
||||
this._selectionMayBeInProgress = false;
|
||||
this._mouseMovedOverEditor(event);
|
||||
|
||||
if (this._codeMirrorMarkedText && this._previousTokenInfo) {
|
||||
var position = this._codeMirror.coordsChar({left: event.pageX, top: event.pageY});
|
||||
var marks = this._codeMirror.findMarksAt(position);
|
||||
for (var i = 0; i < marks.length; ++i) {
|
||||
if (marks[i] === this._codeMirrorMarkedText) {
|
||||
if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeWasClicked === "function")
|
||||
this._delegate.tokenTrackingControllerHighlightedRangeWasClicked(this);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_windowLostFocus(event)
|
||||
{
|
||||
this._resetTrackingStates();
|
||||
}
|
||||
|
||||
_processNewHoveredToken(tokenInfo)
|
||||
{
|
||||
console.assert(tokenInfo);
|
||||
|
||||
if (this._selectionMayBeInProgress)
|
||||
return;
|
||||
|
||||
this._candidate = null;
|
||||
|
||||
switch (this._mode) {
|
||||
case WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens:
|
||||
this._candidate = this._processNonSymbolToken(tokenInfo);
|
||||
break;
|
||||
case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
|
||||
case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation:
|
||||
this._candidate = this._processJavaScriptExpression(tokenInfo);
|
||||
break;
|
||||
case WI.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
|
||||
this._candidate = this._processMarkedToken(tokenInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this._candidate)
|
||||
return;
|
||||
|
||||
this._candidate.triggeredBy = tokenInfo.triggeredBy;
|
||||
|
||||
if (this._markedTextMouseoutTimer)
|
||||
clearTimeout(this._markedTextMouseoutTimer);
|
||||
|
||||
this._markedTextMouseoutTimer = 0;
|
||||
|
||||
if (this._delegate && typeof this._delegate.tokenTrackingControllerNewHighlightCandidate === "function")
|
||||
this._delegate.tokenTrackingControllerNewHighlightCandidate(this, this._candidate);
|
||||
}
|
||||
|
||||
_processNonSymbolToken(tokenInfo)
|
||||
{
|
||||
// Ignore any symbol tokens.
|
||||
var type = tokenInfo.token.type;
|
||||
if (!type)
|
||||
return null;
|
||||
|
||||
var startPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
|
||||
var endPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.end};
|
||||
|
||||
return {
|
||||
hoveredToken: tokenInfo.token,
|
||||
hoveredTokenRange: {start: startPosition, end: endPosition},
|
||||
};
|
||||
}
|
||||
|
||||
_processJavaScriptExpression(tokenInfo)
|
||||
{
|
||||
// Only valid within JavaScript.
|
||||
if (tokenInfo.modeName !== "javascript")
|
||||
return null;
|
||||
|
||||
var startPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
|
||||
var endPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.end};
|
||||
|
||||
function tokenIsInRange(token, range)
|
||||
{
|
||||
return token.line >= range.start.line && token.ch >= range.start.ch &&
|
||||
token.line <= range.end.line && token.ch <= range.end.ch;
|
||||
}
|
||||
|
||||
// If the hovered token is within a selection, use the selection as our expression.
|
||||
if (this._codeMirror.somethingSelected()) {
|
||||
var selectionRange = {
|
||||
start: this._codeMirror.getCursor("start"),
|
||||
end: this._codeMirror.getCursor("end")
|
||||
};
|
||||
|
||||
if (tokenIsInRange(startPosition, selectionRange) || tokenIsInRange(endPosition, selectionRange)) {
|
||||
return {
|
||||
hoveredToken: tokenInfo.token,
|
||||
hoveredTokenRange: selectionRange,
|
||||
expression: this._codeMirror.getSelection(),
|
||||
expressionRange: selectionRange,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// We only handle vars, definitions, properties, and the keyword 'this'.
|
||||
var type = tokenInfo.token.type;
|
||||
var isProperty = type.indexOf("property") !== -1;
|
||||
var isKeyword = type.indexOf("keyword") !== -1;
|
||||
if (!isProperty && !isKeyword && type.indexOf("variable") === -1 && type.indexOf("def") === -1)
|
||||
return null;
|
||||
|
||||
// Not object literal property names, but yes if an object literal shorthand property, which is a variable.
|
||||
let state = tokenInfo.innerMode.state;
|
||||
if (isProperty && state.lexical && state.lexical.type === "}") {
|
||||
// Peek ahead to see if the next token is "}" or ",". If it is, we are a shorthand and therefore a variable.
|
||||
let shorthand = false;
|
||||
let mode = tokenInfo.innerMode.mode;
|
||||
let position = {line: tokenInfo.position.line, ch: tokenInfo.token.end};
|
||||
WI.walkTokens(this._codeMirror, mode, position, function(tokenType, string) {
|
||||
if (tokenType)
|
||||
return false;
|
||||
if (string === "(")
|
||||
return false;
|
||||
if (string === "," || string === "}") {
|
||||
shorthand = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!shorthand)
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only the "this" keyword.
|
||||
if (isKeyword && tokenInfo.token.string !== "this")
|
||||
return null;
|
||||
|
||||
// Work out the full hovered expression.
|
||||
var expression = tokenInfo.token.string;
|
||||
var expressionStartPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
|
||||
while (true) {
|
||||
var token = this._codeMirror.getTokenAt(expressionStartPosition);
|
||||
if (!token)
|
||||
break;
|
||||
|
||||
var isDot = !token.type && token.string === ".";
|
||||
var isExpression = token.type && token.type.includes("m-javascript");
|
||||
if (!isDot && !isExpression)
|
||||
break;
|
||||
|
||||
if (isExpression) {
|
||||
// Disallow operators. We want the hovered expression to be just a single operand.
|
||||
// Also, some operators can modify values, such as pre-increment and assignment operators.
|
||||
if (token.type.includes("operator"))
|
||||
break;
|
||||
|
||||
// Don't break out of a template string quasi group.
|
||||
if (token.type.includes("string-2"))
|
||||
break;
|
||||
}
|
||||
|
||||
expression = token.string + expression;
|
||||
expressionStartPosition.ch = token.start;
|
||||
}
|
||||
|
||||
// Return the candidate for this token and expression.
|
||||
return {
|
||||
hoveredToken: tokenInfo.token,
|
||||
hoveredTokenRange: {start: startPosition, end: endPosition},
|
||||
expression,
|
||||
expressionRange: {start: expressionStartPosition, end: endPosition},
|
||||
};
|
||||
}
|
||||
|
||||
_processMarkedToken(tokenInfo)
|
||||
{
|
||||
return this._processNonSymbolToken(tokenInfo);
|
||||
}
|
||||
|
||||
_resetTrackingStates()
|
||||
{
|
||||
if (this._tokenHoverTimer)
|
||||
clearTimeout(this._tokenHoverTimer);
|
||||
|
||||
this._tokenHoverTimer = 0;
|
||||
|
||||
this._selectionMayBeInProgress = false;
|
||||
this._previousTokenInfo = null;
|
||||
this.removeHighlightedRange();
|
||||
}
|
||||
};
|
||||
|
||||
WI.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName = "jump-to-symbol-highlight";
|
||||
|
||||
WI.CodeMirrorTokenTrackingController.Mode = {
|
||||
None: "none",
|
||||
NonSymbolTokens: "non-symbol-tokens",
|
||||
JavaScriptExpression: "javascript-expression",
|
||||
JavaScriptTypeInformation: "javascript-type-information",
|
||||
MarkedTokens: "marked-tokens"
|
||||
};
|
||||
|
||||
WI.CodeMirrorTokenTrackingController.TriggeredBy = {
|
||||
Keyboard: "keyboard",
|
||||
Hover: "hover"
|
||||
};
|
||||
Reference in New Issue
Block a user