greybel-languageserver-core
Version:
Core functionality of language server for GreyScript
381 lines • 16.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildTokens = exports.TokenHandler = exports.semanticTokensLegend = exports.SemanticTokenModifier = exports.SemanticTokenType = void 0;
const greybel_core_1 = require("greybel-core");
const greyscript_core_1 = require("greyscript-core");
const greyscript_meta_1 = require("greyscript-meta");
const miniscript_core_1 = require("miniscript-core");
var SemanticTokenType;
(function (SemanticTokenType) {
SemanticTokenType[SemanticTokenType["Keyword"] = 0] = "Keyword";
SemanticTokenType[SemanticTokenType["String"] = 1] = "String";
SemanticTokenType[SemanticTokenType["Number"] = 2] = "Number";
SemanticTokenType[SemanticTokenType["Variable"] = 3] = "Variable";
SemanticTokenType[SemanticTokenType["Property"] = 4] = "Property";
SemanticTokenType[SemanticTokenType["Function"] = 5] = "Function";
SemanticTokenType[SemanticTokenType["Parameter"] = 6] = "Parameter";
SemanticTokenType[SemanticTokenType["Operator"] = 7] = "Operator";
SemanticTokenType[SemanticTokenType["Comment"] = 8] = "Comment";
SemanticTokenType[SemanticTokenType["Constant"] = 9] = "Constant";
SemanticTokenType[SemanticTokenType["Punctuator"] = 10] = "Punctuator";
})(SemanticTokenType = exports.SemanticTokenType || (exports.SemanticTokenType = {}));
var SemanticTokenModifier;
(function (SemanticTokenModifier) {
SemanticTokenModifier[SemanticTokenModifier["Declaration"] = 0] = "Declaration";
SemanticTokenModifier[SemanticTokenModifier["Definition"] = 1] = "Definition";
SemanticTokenModifier[SemanticTokenModifier["Readonly"] = 2] = "Readonly";
SemanticTokenModifier[SemanticTokenModifier["Static"] = 3] = "Static";
SemanticTokenModifier[SemanticTokenModifier["Deprecated"] = 4] = "Deprecated";
SemanticTokenModifier[SemanticTokenModifier["Abstract"] = 5] = "Abstract";
SemanticTokenModifier[SemanticTokenModifier["Async"] = 6] = "Async";
SemanticTokenModifier[SemanticTokenModifier["Modification"] = 7] = "Modification";
SemanticTokenModifier[SemanticTokenModifier["Documentation"] = 8] = "Documentation";
SemanticTokenModifier[SemanticTokenModifier["DefaultLibrary"] = 9] = "DefaultLibrary";
})(SemanticTokenModifier = exports.SemanticTokenModifier || (exports.SemanticTokenModifier = {}));
exports.semanticTokensLegend = {
tokenTypes: [
'keyword',
'string',
'number',
'variable',
'property',
'function',
'parameter',
'operator',
'comment',
'constant',
'punctuator'
],
tokenModifiers: [
'declaration',
'definition',
'readonly',
'static',
'deprecated',
'abstract',
'async',
'modification',
'documentation',
'defaultLibrary'
]
};
const getSingularModifier = (modifier) => {
return 1 << modifier;
};
class TokenHandler {
constructor(lexer, builder) {
this._lexer = lexer;
this._builder = builder;
}
next() {
this.previousToken = this.token;
this.token = this._lexer.next();
}
isType(type) {
return this.token !== null && type === this.token.type;
}
consume(selector) {
if (selector(this.token)) {
this.next();
return true;
}
return false;
}
consumeMany(selectorGroup) {
if (selectorGroup(this.token)) {
this.next();
return true;
}
return false;
}
processMultilineToken(token, lines, type) {
if (lines.length > 1) {
this._builder.push(token.start.line - 1, token.start.character - 1, lines[0].length, type, 0);
for (let offset = 1; offset < lines.length; offset++) {
this._builder.push(token.start.line + offset - 1, 0, lines[offset].length, type, 0);
}
}
else {
this._builder.push(token.start.line - 1, token.start.character - 1, lines[0].length, type, 0);
}
}
processFunction() {
const me = this;
if (!miniscript_core_1.SelectorGroups.BlockEndOfLine(me.token)) {
if (!me.consume(miniscript_core_1.Selectors.LParenthesis))
return;
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
while (!miniscript_core_1.SelectorGroups.FunctionDeclarationArgEnd(me.token)) {
if (me.token.type !== miniscript_core_1.TokenType.Identifier) {
return;
}
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.value.length, SemanticTokenType.Parameter, 0);
me.next();
if (me.consume(miniscript_core_1.Selectors.Assign)) {
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Operator, 0);
while (!miniscript_core_1.Selectors.ArgumentSeperator(me.token) &&
!miniscript_core_1.Selectors.RParenthesis(me.token) &&
!miniscript_core_1.Selectors.EndOfLine(me.token)) {
me.process();
}
}
if (!miniscript_core_1.Selectors.RParenthesis(me.token)) {
if (!miniscript_core_1.Selectors.ArgumentSeperator(me.token))
return;
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.value.length, SemanticTokenType.Punctuator, 0);
me.next();
}
}
if (me.consume(miniscript_core_1.Selectors.RParenthesis)) {
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
}
}
}
processPathSegment() {
const me = this;
if (this.token.type === miniscript_core_1.ASTType.StringLiteral) {
const token = this.token;
me._builder.push(token.start.line - 1, token.start.character - 1, token.raw.length, SemanticTokenType.String, 0);
this.next();
return;
}
let path = '';
while (!greybel_core_1.SelectorGroups.PathSegmentEnd(me.token)) {
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.value.length, SemanticTokenType.String, 0);
path = path + me.token.value;
me.next();
}
if (me.consumeMany(greybel_core_1.SelectorGroups.PathSegmentEnd)) {
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
}
return path;
}
processFeatureEnvarExpression() {
const me = this;
if (me.token.type !== miniscript_core_1.TokenType.StringLiteral) {
return;
}
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.value.length, SemanticTokenType.String, 0);
me.next();
}
processFeatureInjectExpression() {
const me = this;
me.processPathSegment();
}
processFeatureImportStatement() {
const me = this;
if (me.token.type !== miniscript_core_1.TokenType.Identifier) {
return;
}
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.value.length, SemanticTokenType.Variable, 0);
me.next();
if (!me.consume(greybel_core_1.Selectors.From)) {
return;
}
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Keyword, 0);
me.processPathSegment();
}
processFeatureIncludeStatement() {
const me = this;
me.processPathSegment();
}
processNativeImportCodeStatement() {
const me = this;
if (!me.consume(miniscript_core_1.Selectors.LParenthesis)) {
return;
}
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
if (miniscript_core_1.TokenType.StringLiteral !== me.token.type) {
return;
}
me._builder.push(me.token.start.line - 1, me.token.start.character - 1, me.token.raw.length, SemanticTokenType.String, 0);
me.next();
if (me.consume(miniscript_core_1.Selectors.ImportCodeSeperator)) {
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
if (!me.isType(miniscript_core_1.TokenType.StringLiteral)) {
return;
}
const token = me.token;
me._builder.push(token.start.line - 1, token.start.character - 1, token.raw.length, SemanticTokenType.String, 0);
me.next();
}
if (!me.consume(miniscript_core_1.Selectors.RParenthesis)) {
return;
}
me._builder.push(me.previousToken.start.line - 1, me.previousToken.start.character - 1, me.previousToken.value.length, SemanticTokenType.Punctuator, 0);
}
processKeyword() {
const token = this.token;
this._builder.push(token.start.line - 1, token.start.character - 1, token.value.length, SemanticTokenType.Keyword, 0);
this.next();
switch (token.value) {
case miniscript_core_1.Keyword.Function: {
this.processFunction();
return;
}
case greybel_core_1.GreybelKeyword.Include:
case greybel_core_1.GreybelKeyword.IncludeWithComment: {
this.processFeatureIncludeStatement();
return;
}
case greybel_core_1.GreybelKeyword.Import:
case greybel_core_1.GreybelKeyword.ImportWithComment: {
this.processFeatureImportStatement();
return;
}
case greybel_core_1.GreybelKeyword.Envar: {
this.processFeatureEnvarExpression();
return;
}
case greybel_core_1.GreybelKeyword.Inject: {
this.processFeatureInjectExpression();
return;
}
case greybel_core_1.GreybelKeyword.Debugger: {
return;
}
case greyscript_core_1.GreyScriptKeyword.ImportCode: {
this.processNativeImportCodeStatement();
}
}
}
processStringLiteral() {
const token = this.token;
this.processMultilineToken(token, token.raw.split('\n'), SemanticTokenType.String);
this.next();
}
processNumericLiteral() {
const token = this.token;
this._builder.push(token.start.line - 1, token.start.character - 1, token.raw.length, SemanticTokenType.Number, 0);
this.next();
}
processBooleanLiteral() {
const token = this.token;
this._builder.push(token.start.line - 1, token.start.character - 1, token.raw.length, SemanticTokenType.Constant, 0);
this.next();
}
processNilLiteral() {
const token = this.token;
this._builder.push(token.start.line - 1, token.start.character - 1, token.raw.length, SemanticTokenType.Constant, 0);
this.next();
}
processIdentifier() {
const token = this.token;
if (miniscript_core_1.Selectors.MemberSeperator(this.previousToken)) {
const isNativeIdentifier = (0, greyscript_meta_1.isNative)(['any'], token.value);
const modifier = isNativeIdentifier
? getSingularModifier(SemanticTokenModifier.DefaultLibrary)
: 0;
this._builder.push(token.start.line - 1, token.start.character - 1, token.value.length, SemanticTokenType.Property, modifier);
this.next();
return;
}
const isNativeIdentifier = (0, greyscript_meta_1.isNative)(['general'], token.value);
const modifier = isNativeIdentifier
? getSingularModifier(SemanticTokenModifier.DefaultLibrary)
: 0;
this._builder.push(token.start.line - 1, token.start.character - 1, token.value.length, SemanticTokenType.Variable, modifier);
this.next();
}
processPunctuator() {
const token = this.token;
switch (token.value) {
case miniscript_core_1.Operator.Plus:
case miniscript_core_1.Operator.Asterik:
case miniscript_core_1.Operator.Minus:
case miniscript_core_1.Operator.Slash:
case miniscript_core_1.Operator.Power:
case miniscript_core_1.Operator.Modulo:
case miniscript_core_1.Operator.LessThan:
case miniscript_core_1.Operator.LessThanOrEqual:
case miniscript_core_1.Operator.GreaterThan:
case miniscript_core_1.Operator.GreaterThanOrEqual:
case miniscript_core_1.Operator.Equal:
case miniscript_core_1.Operator.NotEqual:
case miniscript_core_1.Operator.Assign:
case miniscript_core_1.Operator.AddShorthand:
case miniscript_core_1.Operator.SubtractShorthand:
case miniscript_core_1.Operator.MultiplyShorthand:
case miniscript_core_1.Operator.DivideShorthand:
case miniscript_core_1.Operator.ModuloShorthand:
case miniscript_core_1.Operator.PowerShorthand:
case miniscript_core_1.Operator.Reference: {
this._builder.push(token.start.line - 1, token.start.character - 1, token.value.length, SemanticTokenType.Operator, 0);
break;
}
default: {
this._builder.push(token.start.line - 1, token.start.character - 1, token.value.length, SemanticTokenType.Punctuator, 0);
break;
}
}
this.next();
}
processComment() {
if (this.token.lastLine != null) {
this.processMultilineToken(this.token, `/*${this.token.value}*/`.split('\n'), SemanticTokenType.Comment);
}
else {
this.processMultilineToken(this.token, `//${this.token.value}`.split('\n'), SemanticTokenType.Comment);
}
this.next();
}
process() {
const me = this;
switch (me.token.type) {
case miniscript_core_1.TokenType.Keyword: {
this.processKeyword();
break;
}
case miniscript_core_1.TokenType.StringLiteral: {
this.processStringLiteral();
break;
}
case miniscript_core_1.TokenType.Identifier: {
this.processIdentifier();
break;
}
case miniscript_core_1.TokenType.NumericLiteral: {
this.processNumericLiteral();
break;
}
case miniscript_core_1.TokenType.Punctuator:
case miniscript_core_1.TokenType.SliceOperator: {
this.processPunctuator();
break;
}
case miniscript_core_1.TokenType.BooleanLiteral: {
this.processBooleanLiteral();
break;
}
case miniscript_core_1.TokenType.NilLiteral: {
this.processNilLiteral();
break;
}
case miniscript_core_1.TokenType.Comment: {
this.processComment();
break;
}
default: {
me.next();
}
}
}
digest() {
const me = this;
me.next();
while (!miniscript_core_1.Selectors.EndOfFile(me.token)) {
me.process();
}
}
}
exports.TokenHandler = TokenHandler;
function buildTokens(builder, document) {
const lexer = new greyscript_core_1.Lexer(document.textDocument.getText(), {
unsafe: true
});
const handler = new TokenHandler(lexer, builder);
handler.digest();
return builder;
}
exports.buildTokens = buildTokens;
//# sourceMappingURL=semantic-token-builder.js.map