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(" ");
|
this.removeLast(" ");
|
||||||
|
|
||||||
// remove whitespace if last character was a newline
|
// remove whitespace if last character was a newline
|
||||||
var trimStart = this._getPostNewlineTrailingSpaceStart();
|
this._removeSpacesAfterLastNewline();
|
||||||
if (trimStart) {
|
|
||||||
this.buf = this.buf.substring(0, trimStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._push("\n");
|
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');
|
var lastNewlineIndex = this.buf.lastIndexOf('\n');
|
||||||
if (lastNewlineIndex === -1)
|
if (lastNewlineIndex === -1)
|
||||||
return;
|
return;
|
||||||
@ -115,7 +114,7 @@ Buffer.prototype._getPostNewlineTrailingSpaceStart = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index === lastNewlineIndex) {
|
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 _ = require("lodash");
|
||||||
var util = require("../util");
|
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) {
|
function getLookupIndex(i, base, max) {
|
||||||
i += base;
|
i += base;
|
||||||
|
|
||||||
@ -17,7 +25,14 @@ function Whitespace(tokens, comments) {
|
|||||||
this.tokens = _.sortBy(tokens.concat(comments), "start");
|
this.tokens = _.sortBy(tokens.concat(comments), "start");
|
||||||
this.used = [];
|
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;
|
this._lastFoundIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +43,7 @@ Whitespace.prototype.getNewlinesBefore = function (node) {
|
|||||||
var token;
|
var token;
|
||||||
|
|
||||||
for (var j = 0; j < tokens.length; j++) {
|
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);
|
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||||
token = tokens[i];
|
token = tokens[i];
|
||||||
|
|
||||||
@ -35,6 +51,7 @@ Whitespace.prototype.getNewlinesBefore = function (node) {
|
|||||||
if (node.start === token.start) {
|
if (node.start === token.start) {
|
||||||
startToken = tokens[i - 1];
|
startToken = tokens[i - 1];
|
||||||
endToken = token;
|
endToken = token;
|
||||||
|
|
||||||
this._lastFoundIndex = i;
|
this._lastFoundIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -50,6 +67,7 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
|||||||
var token;
|
var token;
|
||||||
|
|
||||||
for (var j = 0; j < tokens.length; j++) {
|
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);
|
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||||
token = tokens[i];
|
token = tokens[i];
|
||||||
|
|
||||||
@ -57,6 +75,7 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
|||||||
if (node.end === token.end) {
|
if (node.end === token.end) {
|
||||||
startToken = token;
|
startToken = token;
|
||||||
endToken = tokens[i + 1];
|
endToken = tokens[i + 1];
|
||||||
|
|
||||||
this._lastFoundIndex = i;
|
this._lastFoundIndex = i;
|
||||||
break;
|
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) {
|
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) {
|
t["assert" + type] = function (node, opts) {
|
||||||
@ -46,12 +53,23 @@ _.each(t.FLIPPED_ALIAS_KEYS, function (types, type) {
|
|||||||
registerType(type, false);
|
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;
|
if (!node) return;
|
||||||
|
|
||||||
var typeMatches = (type === node.type);
|
var typeMatches = (type === node.type);
|
||||||
|
|
||||||
if (!typeMatches && !skipAliases) {
|
if (!typeMatches && !skipAliasCheck) {
|
||||||
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
||||||
|
|
||||||
if (typeof aliases !== 'undefined')
|
if (typeof aliases !== 'undefined')
|
||||||
|
|||||||
@ -204,6 +204,24 @@ exports.repeat = function (width, cha) {
|
|||||||
return result;
|
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) {
|
exports.mergeIntegerRange = function (ranges, start, end) {
|
||||||
var pointsAdded = 0;
|
var pointsAdded = 0;
|
||||||
var insertIndex;
|
var insertIndex;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user