75 lines
1.7 KiB
JavaScript
75 lines
1.7 KiB
JavaScript
"use strict";
|
|
|
|
function NameStack() {
|
|
this._stack = [];
|
|
}
|
|
|
|
Object.defineProperty(NameStack.prototype, "length", {
|
|
get: function() {
|
|
return this._stack.length;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Create a new entry in the stack. Useful for tracking names across
|
|
* expressions.
|
|
*/
|
|
NameStack.prototype.push = function() {
|
|
this._stack.push(null);
|
|
};
|
|
|
|
/**
|
|
* Discard the most recently-created name on the stack.
|
|
*/
|
|
NameStack.prototype.pop = function() {
|
|
this._stack.pop();
|
|
};
|
|
|
|
/**
|
|
* Update the most recent name on the top of the stack.
|
|
*
|
|
* @param {object} token The token to consider as the source for the most
|
|
* recent name.
|
|
*/
|
|
NameStack.prototype.set = function(token) {
|
|
this._stack[this.length - 1] = token;
|
|
};
|
|
|
|
/**
|
|
* Generate a string representation of the most recent name.
|
|
*
|
|
* @returns {string}
|
|
*/
|
|
NameStack.prototype.infer = function() {
|
|
var nameToken = this._stack[this.length - 1];
|
|
var prefix = "";
|
|
var type;
|
|
|
|
// During expected operation, the topmost entry on the stack will only
|
|
// reflect the current function's name when the function is declared without
|
|
// the `function` keyword (i.e. for in-line accessor methods). In other
|
|
// cases, the `function` expression itself will introduce an empty entry on
|
|
// the top of the stack, and this should be ignored.
|
|
if (!nameToken || nameToken.type === "class") {
|
|
nameToken = this._stack[this.length - 2];
|
|
}
|
|
|
|
if (!nameToken) {
|
|
return "(empty)";
|
|
}
|
|
|
|
type = nameToken.type;
|
|
|
|
if (type !== "(string)" && type !== "(number)" && type !== "(identifier)" && type !== "default") {
|
|
return "(expression)";
|
|
}
|
|
|
|
if (nameToken.accessorType) {
|
|
prefix = nameToken.accessorType + " ";
|
|
}
|
|
|
|
return prefix + nameToken.value;
|
|
};
|
|
|
|
module.exports = NameStack;
|