UNPKG

monaco-editor

Version:
333 lines (332 loc) • 12.8 kB
/*--------------------------------------------------------------------------------------------- * 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; }