monaco-editor
Version:
A browser based code editor
333 lines (332 loc) • 12.8 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { Range } from '../../common/core/range.js';
import { ignoreBracketsInToken } from '../../common/modes/supports.js';
import { BracketsUtils } from '../../common/modes/supports/richEditBrackets.js';
import { LanguageConfigurationRegistry } from '../../common/modes/languageConfigurationRegistry.js';
var Node = /** @class */ (function () {
function Node() {
}
Object.defineProperty(Node.prototype, "range", {
get: function () {
return new Range(this.start.lineNumber, this.start.column, this.end.lineNumber, this.end.column);
},
enumerable: true,
configurable: true
});
return Node;
}());
export { Node };
var NodeList = /** @class */ (function (_super) {
__extends(NodeList, _super);
function NodeList() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(NodeList.prototype, "hasChildren", {
get: function () {
return this.children && this.children.length > 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NodeList.prototype, "isEmpty", {
get: function () {
return !this.hasChildren && !this.parent;
},
enumerable: true,
configurable: true
});
NodeList.prototype.append = function (node) {
if (!node) {
return false;
}
node.parent = this;
if (!this.children) {
this.children = [];
}
if (node instanceof NodeList) {
if (node.children) {
this.children.push.apply(this.children, node.children);
}
}
else {
this.children.push(node);
}
return true;
};
return NodeList;
}(Node));
export { NodeList };
var Block = /** @class */ (function (_super) {
__extends(Block, _super);
function Block() {
var _this = _super.call(this) || this;
_this.elements = new NodeList();
_this.elements.parent = _this;
return _this;
}
return Block;
}(Node));
export { Block };
var Token = /** @class */ (function () {
function Token(range, bracket, bracketType) {
this.range = range;
this.bracket = bracket;
this.bracketType = bracketType;
}
return Token;
}());
function newNode(token) {
var node = new Node();
node.start = token.range.getStartPosition();
node.end = token.range.getEndPosition();
return node;
}
var RawToken = /** @class */ (function () {
function RawToken(source, tokenIndex, lineNumber) {
this.lineNumber = lineNumber;
this.lineText = source.getLineContent();
this.startOffset = source.getStartOffset(tokenIndex);
this.endOffset = source.getEndOffset(tokenIndex);
this.type = source.getStandardTokenType(tokenIndex);
this.languageId = source.getLanguageId(tokenIndex);
}
return RawToken;
}());
var ModelRawTokenScanner = /** @class */ (function () {
function ModelRawTokenScanner(model) {
this._model = model;
this._lineCount = this._model.getLineCount();
this._versionId = this._model.getVersionId();
this._lineNumber = 0;
this._tokenIndex = 0;
this._lineTokens = null;
this._advance();
}
ModelRawTokenScanner.prototype._advance = function () {
if (this._lineTokens) {
this._tokenIndex++;
if (this._tokenIndex >= this._lineTokens.getCount()) {
this._lineTokens = null;
}
}
while (this._lineNumber < this._lineCount && !this._lineTokens) {
this._lineNumber++;
this._model.forceTokenization(this._lineNumber);
this._lineTokens = this._model.getLineTokens(this._lineNumber);
this._tokenIndex = 0;
if (this._lineTokens.getLineContent().length === 0) {
// Skip empty lines
this._lineTokens = null;
}
}
};
ModelRawTokenScanner.prototype.next = function () {
if (!this._lineTokens) {
return null;
}
if (this._model.getVersionId() !== this._versionId) {
return null;
}
var result = new RawToken(this._lineTokens, this._tokenIndex, this._lineNumber);
this._advance();
return result;
};
return ModelRawTokenScanner;
}());
var TokenScanner = /** @class */ (function () {
function TokenScanner(model) {
this._rawTokenScanner = new ModelRawTokenScanner(model);
this._nextBuff = [];
this._cachedLanguageBrackets = null;
this._cachedLanguageId = -1;
}
TokenScanner.prototype.next = function () {
if (this._nextBuff.length > 0) {
return this._nextBuff.shift();
}
var token = this._rawTokenScanner.next();
if (!token) {
return null;
}
var lineNumber = token.lineNumber;
var lineText = token.lineText;
var tokenType = token.type;
var startOffset = token.startOffset;
var endOffset = token.endOffset;
if (this._cachedLanguageId !== token.languageId) {
this._cachedLanguageId = token.languageId;
this._cachedLanguageBrackets = LanguageConfigurationRegistry.getBracketsSupport(this._cachedLanguageId);
}
var modeBrackets = this._cachedLanguageBrackets;
if (!modeBrackets || ignoreBracketsInToken(tokenType)) {
return new Token(new Range(lineNumber, startOffset + 1, lineNumber, endOffset + 1), 0 /* None */, null);
}
var foundBracket;
do {
foundBracket = BracketsUtils.findNextBracketInToken(modeBrackets.forwardRegex, lineNumber, lineText, startOffset, endOffset);
if (foundBracket) {
var foundBracketStartOffset = foundBracket.startColumn - 1;
var foundBracketEndOffset = foundBracket.endColumn - 1;
if (startOffset < foundBracketStartOffset) {
// there is some text before this bracket in this token
this._nextBuff.push(new Token(new Range(lineNumber, startOffset + 1, lineNumber, foundBracketStartOffset + 1), 0 /* None */, null));
}
var bracketText = lineText.substring(foundBracketStartOffset, foundBracketEndOffset);
bracketText = bracketText.toLowerCase();
var bracketData = modeBrackets.textIsBracket[bracketText];
var bracketIsOpen = modeBrackets.textIsOpenBracket[bracketText];
this._nextBuff.push(new Token(new Range(lineNumber, foundBracketStartOffset + 1, lineNumber, foundBracketEndOffset + 1), bracketIsOpen ? 1 /* Open */ : -1 /* Close */, bracketData.languageIdentifier.language + ";" + bracketData.open + ";" + bracketData.close));
startOffset = foundBracketEndOffset;
}
} while (foundBracket);
if (startOffset < endOffset) {
// there is some remaining none-bracket text in this token
this._nextBuff.push(new Token(new Range(lineNumber, startOffset + 1, lineNumber, endOffset + 1), 0 /* None */, null));
}
return this._nextBuff.shift() || null;
};
return TokenScanner;
}());
var TokenTreeBuilder = /** @class */ (function () {
function TokenTreeBuilder(model) {
this._stack = [];
this._scanner = new TokenScanner(model);
}
TokenTreeBuilder.prototype.build = function () {
var node = new NodeList();
while (node.append(this._line() || this._any())) {
// accept all
}
return node;
};
TokenTreeBuilder.prototype._accept = function (condt) {
var token = this._stack.pop() || this._scanner.next();
if (!token) {
return false;
}
var accepted = condt(token);
if (!accepted) {
this._stack.push(token);
// this._currentToken = null;
}
else {
this._currentToken = token;
// console.log('accepted: ' + token.__debugContent);
}
return accepted;
};
TokenTreeBuilder.prototype._peek = function (condt) {
var ret = false;
this._accept(function (info) {
ret = condt(info);
return false;
});
return ret;
};
TokenTreeBuilder.prototype._line = function () {
var node = new NodeList();
var lineNumber;
// capture current linenumber
this._peek(function (info) {
lineNumber = info.range.startLineNumber;
return false;
});
while (this._peek(function (info) { return info.range.startLineNumber === lineNumber; })
&& node.append(this._token() || this._block())) {
// all children that started on this line
}
if (!node.children || node.children.length === 0) {
return null;
}
else if (node.children.length === 1) {
return node.children[0];
}
else {
return node;
}
};
TokenTreeBuilder.prototype._token = function () {
if (!this._accept(function (token) { return token.bracket === 0 /* None */; })) {
return null;
}
return newNode(this._currentToken);
};
TokenTreeBuilder.prototype._block = function () {
var bracketType;
var accepted;
accepted = this._accept(function (token) {
bracketType = token.bracketType;
return token.bracket === 1 /* Open */;
});
if (!accepted) {
return null;
}
var bracket = new Block();
bracket.open = newNode(this._currentToken);
while (bracket.elements.append(this._line())) {
// inside brackets
}
if (!this._accept(function (token) { return token.bracket === -1 /* Close */ && token.bracketType === bracketType; })) {
// missing closing bracket -> return just a node list
var nodelist = new NodeList();
nodelist.append(bracket.open);
nodelist.append(bracket.elements);
return nodelist;
}
bracket.close = newNode(this._currentToken);
return bracket;
};
TokenTreeBuilder.prototype._any = function () {
if (!this._accept(function (_) { return true; })) {
return null;
}
return newNode(this._currentToken);
};
return TokenTreeBuilder;
}());
/**
* Parses this grammar:
* grammer = { line }
* line = { block | "token" }
* block = "open_bracket" { line } "close_bracket"
*/
export function build(model) {
var node = new TokenTreeBuilder(model).build();
return node;
}
export function find(node, position) {
if (node instanceof NodeList && node.isEmpty) {
return null;
}
if (!Range.containsPosition(node.range, position)) {
return null;
}
var result = null;
if (node instanceof NodeList) {
if (node.hasChildren) {
for (var i = 0, len = node.children.length; i < len && !result; i++) {
result = find(node.children[i], position);
}
}
}
else if (node instanceof Block) {
result = find(node.elements, position) || find(node.open, position) || find(node.close, position);
}
return result || node;
}