99 lines
2.3 KiB
JavaScript
99 lines
2.3 KiB
JavaScript
/**
|
|
* Get whitespace around tokens.
|
|
*/
|
|
|
|
export default class Whitespace {
|
|
constructor(tokens) {
|
|
this.tokens = tokens;
|
|
this.used = {};
|
|
}
|
|
|
|
/**
|
|
* Count all the newlines before a node.
|
|
*/
|
|
|
|
getNewlinesBefore(node) {
|
|
let startToken;
|
|
let endToken;
|
|
let tokens = this.tokens;
|
|
|
|
let index = this._findToken((token) => token.start - node.start, 0, tokens.length);
|
|
if (index >= 0) {
|
|
while (index && node.start === tokens[index - 1].start) --index;
|
|
startToken = tokens[index - 1];
|
|
endToken = tokens[index];
|
|
}
|
|
|
|
return this.getNewlinesBetween(startToken, endToken);
|
|
}
|
|
|
|
/**
|
|
* Count all the newlines after a node.
|
|
*/
|
|
|
|
getNewlinesAfter(node) {
|
|
let startToken;
|
|
let endToken;
|
|
let tokens = this.tokens;
|
|
|
|
let index = this._findToken((token) => token.end - node.end, 0, tokens.length);
|
|
if (index >= 0) {
|
|
while (index && node.end === tokens[index - 1].end) --index;
|
|
startToken = tokens[index];
|
|
endToken = tokens[index + 1];
|
|
if (endToken.type.label === ",") endToken = tokens[index + 2];
|
|
}
|
|
|
|
if (endToken && endToken.type.label === "eof") {
|
|
return 1;
|
|
} else {
|
|
let lines = this.getNewlinesBetween(startToken, endToken);
|
|
if (node.type === "CommentLine" && !lines) {
|
|
// line comment
|
|
return 1;
|
|
} else {
|
|
return lines;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Count all the newlines between two tokens.
|
|
*/
|
|
|
|
getNewlinesBetween(startToken, endToken) {
|
|
if (!endToken || !endToken.loc) return 0;
|
|
|
|
let start = startToken ? startToken.loc.end.line : 1;
|
|
let end = endToken.loc.start.line;
|
|
let lines = 0;
|
|
|
|
for (let line = start; line < end; line++) {
|
|
if (typeof this.used[line] === "undefined") {
|
|
this.used[line] = true;
|
|
lines++;
|
|
}
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
/**
|
|
* Find a token between start and end.
|
|
*/
|
|
|
|
_findToken(test: Function, start: number, end: number): number {
|
|
if (start >= end) return -1;
|
|
const middle = (start + end) >>> 1;
|
|
const match: number = test(this.tokens[middle]);
|
|
if (match < 0) {
|
|
return this._findToken(test, middle + 1, end);
|
|
} else if (match > 0) {
|
|
return this._findToken(test, start, middle);
|
|
} else if (match === 0) {
|
|
return middle;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|