Slightly refactor and add explanations for optimized functions
This commit is contained in:
parent
58a91ee9e9
commit
a452f781b8
@ -92,15 +92,14 @@ Buffer.prototype._newline = function (removeLast) {
|
||||
this.removeLast(" ");
|
||||
|
||||
// remove whitespace if last character was a newline
|
||||
var trimStart = this._getPostNewlineTrailingSpaceStart();
|
||||
if (trimStart) {
|
||||
this.buf = this.buf.substring(0, trimStart);
|
||||
}
|
||||
|
||||
this._removeSpacesAfterLastNewline();
|
||||
this._push("\n");
|
||||
};
|
||||
|
||||
Buffer.prototype._getPostNewlineTrailingSpaceStart = function () {
|
||||
/**
|
||||
* If buffer ends with a newline and some spaces after it, trim those spaces.
|
||||
*/
|
||||
Buffer.prototype._removeSpacesAfterLastNewline = function () {
|
||||
var lastNewlineIndex = this.buf.lastIndexOf('\n');
|
||||
if (lastNewlineIndex === -1)
|
||||
return;
|
||||
@ -115,7 +114,7 @@ Buffer.prototype._getPostNewlineTrailingSpaceStart = function () {
|
||||
}
|
||||
|
||||
if (index === lastNewlineIndex) {
|
||||
return index + 1;
|
||||
this.buf = this.buf.substring(0, index + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -3,7 +3,15 @@ module.exports = Whitespace;
|
||||
var _ = require("lodash");
|
||||
var util = require("../util");
|
||||
|
||||
// a helper to iterate array from arbitrary index
|
||||
/**
|
||||
* Returns `i`th number from `base`, continuing from 0 when `max` is reached.
|
||||
* Useful for shifting `for` loop by a fixed number but going over all items.
|
||||
*
|
||||
* @param {Number} i Current index in the loop
|
||||
* @param {Number} base Start index for which to return 0
|
||||
* @param {Number} max Array length
|
||||
* @returns {Number} shiftedIndex
|
||||
*/
|
||||
function getLookupIndex(i, base, max) {
|
||||
i += base;
|
||||
|
||||
@ -17,7 +25,14 @@ function Whitespace(tokens, comments) {
|
||||
this.tokens = _.sortBy(tokens.concat(comments), "start");
|
||||
this.used = [];
|
||||
|
||||
// speed up common case where methods are called for next tokens
|
||||
// Profiling this code shows that while generator passes over it, indexes
|
||||
// returned by `getNewlinesBefore` and `getNewlinesAfter` are always increasing.
|
||||
|
||||
// We use this implementation detail for an optimization: instead of always
|
||||
// starting to look from `this.tokens[0]`, we will start `for` loops from the
|
||||
// previous successful match. We will enumerate all tokens—but the common
|
||||
// case will be much faster.
|
||||
|
||||
this._lastFoundIndex = 0;
|
||||
}
|
||||
|
||||
@ -28,6 +43,7 @@ Whitespace.prototype.getNewlinesBefore = function (node) {
|
||||
var token;
|
||||
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
|
||||
@ -35,6 +51,7 @@ Whitespace.prototype.getNewlinesBefore = function (node) {
|
||||
if (node.start === token.start) {
|
||||
startToken = tokens[i - 1];
|
||||
endToken = token;
|
||||
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
}
|
||||
@ -50,6 +67,7 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
||||
var token;
|
||||
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
|
||||
@ -57,6 +75,7 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
||||
if (node.end === token.end) {
|
||||
startToken = token;
|
||||
endToken = tokens[i + 1];
|
||||
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7,9 +7,16 @@ t.NATIVE_TYPE_NAMES = ["Array", "Object", "Number", "Boolean", "Date", "Array",
|
||||
|
||||
//
|
||||
|
||||
function registerType(type, skipAliases) {
|
||||
/**
|
||||
* Registers `is[Type]` and `assert[Type]` generated functions for a given `type`.
|
||||
* Pass `skipAliasCheck` to force it to directly compare `node.type` with `type`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {Boolean?} skipAliasCheck
|
||||
*/
|
||||
function registerType(type, skipAliasCheck) {
|
||||
var is = t["is" + type] = function (node, opts) {
|
||||
return t.is(type, node, opts, skipAliases);
|
||||
return t.is(type, node, opts, skipAliasCheck);
|
||||
};
|
||||
|
||||
t["assert" + type] = function (node, opts) {
|
||||
@ -46,12 +53,23 @@ _.each(t.FLIPPED_ALIAS_KEYS, function (types, type) {
|
||||
registerType(type, false);
|
||||
});
|
||||
|
||||
t.is = function (type, node, opts, skipAliases) {
|
||||
/**
|
||||
* Returns whether `node` is of given `type`.
|
||||
* For better performance, use this instead of `is[Type]` when `type` is unknown.
|
||||
* Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {Node} node
|
||||
* @param {Object?} opts
|
||||
* @param {Boolean?} skipAliasCheck
|
||||
* @returns {Boolean} isOfType
|
||||
*/
|
||||
t.is = function (type, node, opts, skipAliasCheck) {
|
||||
if (!node) return;
|
||||
|
||||
var typeMatches = (type === node.type);
|
||||
|
||||
if (!typeMatches && !skipAliases) {
|
||||
if (!typeMatches && !skipAliasCheck) {
|
||||
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
||||
|
||||
if (typeof aliases !== 'undefined')
|
||||
|
||||
@ -204,6 +204,24 @@ exports.repeat = function (width, cha) {
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Merges a range of integers defined by `start` and `end` into an existing
|
||||
* array of `ranges`, optimizing for common cases and attempting to keep them
|
||||
* sorted. Returns the count of integers that have been added to `ranges` during
|
||||
* the call.
|
||||
*
|
||||
* @example
|
||||
* > var ranges = [{ start: 1, end: 3}, { start: 8, end : 10 }];
|
||||
* > mergeIntegerRange(ranges, 6, 9);
|
||||
* 2
|
||||
* > ranges
|
||||
* [{ start: 1, end: 3}, { start: 6, end : 10 }];
|
||||
*
|
||||
* @param {Array} ranges An array of ranges that function will mutate
|
||||
* @param {Number} start Beginning of range being added
|
||||
* @param {Number} end End of range being added
|
||||
* @returns {Number} pointsAdded How many new integers have been added
|
||||
*/
|
||||
exports.mergeIntegerRange = function (ranges, start, end) {
|
||||
var pointsAdded = 0;
|
||||
var insertIndex;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user