blob: 1600af071b3ec5a3caffdae1703bac71aae12510 [file] [log] [blame]
/*
* Copyright (C) 2014-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.
*/
WI.TypeTokenView = class TypeTokenView extends WI.Object
{
constructor(tokenAnnotator, shouldHaveRightMargin, shouldHaveLeftMargin, titleType, functionOrVariableName)
{
console.assert(titleType === WI.TypeTokenView.TitleType.Variable || titleType === WI.TypeTokenView.TitleType.ReturnStatement);
super();
var span = document.createElement("span");
span.classList.add("type-token");
if (shouldHaveRightMargin)
span.classList.add("type-token-right-spacing");
if (shouldHaveLeftMargin)
span.classList.add("type-token-left-spacing");
this.element = span;
this._tokenAnnotator = tokenAnnotator;
this._typeDescription = null;
this._colorClass = null;
this._popoverTitle = WI.TypeTokenView.titleForPopover(titleType, functionOrVariableName);
this._setUpMouseoverHandlers();
}
// Static
static titleForPopover(titleType, functionOrVariableName)
{
if (titleType === WI.TypeTokenView.TitleType.Variable)
return WI.UIString("Type information for variable: %s").format(functionOrVariableName);
if (functionOrVariableName)
return WI.UIString("Return type for function: %s").format(functionOrVariableName);
return WI.UIString("Return type for anonymous function");
}
// Public
update(typeDescription)
{
console.assert(typeDescription instanceof WI.TypeDescription);
this._typeDescription = typeDescription;
var title = this._displayTypeName();
if (title === this.element.textContent)
return;
this.element.textContent = title;
var hashString = title[title.length - 1] === "?" ? title.slice(0, title.length - 1) : title;
if (this._colorClass)
this.element.classList.remove(this._colorClass);
this._colorClass = WI.TypeTokenView.ColorClassForType[hashString] || "type-token-default";
this.element.classList.add(this._colorClass);
}
// Private
_setUpMouseoverHandlers()
{
var timeoutID = null;
this.element.addEventListener("mouseover", function() {
function showPopoverAfterDelay()
{
timeoutID = null;
var domRect = this.element.getBoundingClientRect();
var bounds = new WI.Rect(domRect.left, domRect.top, domRect.width, domRect.height);
this._tokenAnnotator.sourceCodeTextEditor.showPopoverForTypes(this._typeDescription, bounds, this._popoverTitle);
}
if (this._shouldShowPopover())
timeoutID = setTimeout(showPopoverAfterDelay.bind(this), WI.TypeTokenView.DelayHoverTime);
}.bind(this));
this.element.addEventListener("mouseout", function() {
if (timeoutID)
clearTimeout(timeoutID);
});
}
_shouldShowPopover()
{
if (!this._typeDescription.valid)
return false;
if (this._typeDescription.typeSet.primitiveTypeNames.length > 1)
return true;
if (this._typeDescription.structures && this._typeDescription.structures.length)
return true;
return false;
}
_displayTypeName()
{
if (!this._typeDescription.valid)
return "";
var typeSet = this._typeDescription.typeSet;
if (this._typeDescription.leastCommonAncestor) {
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object))
return this._typeDescription.leastCommonAncestor;
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.NullOrUndefinedTypeBits))
return this._typeDescription.leastCommonAncestor + "?";
}
// The order of these checks are important.
// For example, if a value is only a function, it is contained in TypeFunction, but it is also contained in (TypeFunction | TypeNull).
// Therefore, more specific types must be checked first.
// The strings returned here should match those in TypeTokenView.ColorClassForType
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Function))
return "Function";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Undefined))
return "Undefined";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Null))
return "Null";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Boolean))
return "Boolean";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Integer))
return "Integer";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Number | WI.TypeSet.TypeBit.Integer))
return "Number";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.String))
return "String";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Symbol))
return "Symbol";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.BigInt))
return "BigInt";
if (typeSet.isContainedIn(WI.TypeSet.NullOrUndefinedTypeBits))
return "(?)";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Function | WI.TypeSet.NullOrUndefinedTypeBits))
return "Function?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Boolean | WI.TypeSet.NullOrUndefinedTypeBits))
return "Boolean?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Integer | WI.TypeSet.NullOrUndefinedTypeBits))
return "Integer?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Number | WI.TypeSet.TypeBit.Integer | WI.TypeSet.NullOrUndefinedTypeBits))
return "Number?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.String | WI.TypeSet.NullOrUndefinedTypeBits))
return "String?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Symbol | WI.TypeSet.NullOrUndefinedTypeBits))
return "Symbol?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.BigInt | WI.TypeSet.NullOrUndefinedTypeBits))
return "BigInt?";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.TypeBit.Function | WI.TypeSet.TypeBit.String))
return "Object";
if (typeSet.isContainedIn(WI.TypeSet.TypeBit.Object | WI.TypeSet.TypeBit.Function | WI.TypeSet.TypeBit.String | WI.TypeSet.NullOrUndefinedTypeBits))
return "Object?";
return WI.UIString("(many)");
}
};
WI.TypeTokenView.TitleType = {
Variable: Symbol("title-type-variable"),
ReturnStatement: Symbol("title-type-return-statement")
};
WI.TypeTokenView.ColorClassForType = {
"String": "type-token-string",
"Symbol": "type-token-symbol",
"BigInt": "type-token-bigint",
"Function": "type-token-function",
"Number": "type-token-number",
"Integer": "type-token-number",
"Undefined": "type-token-empty",
"Null": "type-token-empty",
"(?)": "type-token-empty",
"Boolean": "type-token-boolean",
"(many)": "type-token-many"
};
WI.TypeTokenView.DelayHoverTime = 350;