UNPKG

@kusto/monaco-kusto

Version:

CSL, KQL plugin for the Monaco Editor

864 lines 94.7 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var _a; import XRegExp from 'xregexp'; import * as ls from 'vscode-languageserver-types'; import * as s from './schema'; // Replaced with @kusto/language-server imports at build time import 'language-service'; var k = Kusto.Data.IntelliSense; var parsing = Kusto.Language.Parsing; var k2 = Kusto.Language.Editor; var sym = Kusto.Language.Symbols; var GlobalState = Kusto.Language.GlobalState; import { getCslTypeNameFromClrType, getEntityDataTypeFromCslType } from './schema'; var List = System.Collections.Generic.List$1; function assertNever(x) { throw new Error('Unexpected object: ' + x); } var ParseProperties = /** @class */ (function () { function ParseProperties(version, uri, rulesProvider, parseMode) { this.version = version; this.uri = uri; this.rulesProvider = rulesProvider; this.parseMode = parseMode; } ParseProperties.prototype.isParseNeeded = function (document, rulesProvider, parseMode) { if (document.uri === this.uri && (!rulesProvider || rulesProvider === this.rulesProvider) && document.version <= this.version && parseMode && parseMode <= this.parseMode) { return false; } return true; }; return ParseProperties; }()); export var TokenKind; (function (TokenKind) { TokenKind[TokenKind["TableToken"] = 2] = "TableToken"; TokenKind[TokenKind["TableColumnToken"] = 4] = "TableColumnToken"; TokenKind[TokenKind["OperatorToken"] = 8] = "OperatorToken"; TokenKind[TokenKind["SubOperatorToken"] = 16] = "SubOperatorToken"; TokenKind[TokenKind["CalculatedColumnToken"] = 32] = "CalculatedColumnToken"; TokenKind[TokenKind["StringLiteralToken"] = 64] = "StringLiteralToken"; TokenKind[TokenKind["FunctionNameToken"] = 128] = "FunctionNameToken"; TokenKind[TokenKind["UnknownToken"] = 256] = "UnknownToken"; TokenKind[TokenKind["CommentToken"] = 512] = "CommentToken"; TokenKind[TokenKind["PlainTextToken"] = 1024] = "PlainTextToken"; TokenKind[TokenKind["DataTypeToken"] = 2048] = "DataTypeToken"; TokenKind[TokenKind["ControlCommandToken"] = 4096] = "ControlCommandToken"; TokenKind[TokenKind["CommandPartToken"] = 8192] = "CommandPartToken"; TokenKind[TokenKind["QueryParametersToken"] = 16384] = "QueryParametersToken"; TokenKind[TokenKind["CslCommandToken"] = 32768] = "CslCommandToken"; TokenKind[TokenKind["LetVariablesToken"] = 65536] = "LetVariablesToken"; TokenKind[TokenKind["PluginToken"] = 131072] = "PluginToken"; TokenKind[TokenKind["BracketRangeToken"] = 262144] = "BracketRangeToken"; TokenKind[TokenKind["ClientDirectiveToken"] = 524288] = "ClientDirectiveToken"; })(TokenKind || (TokenKind = {})); var symbolKindToName = (_a = {}, _a[sym.SymbolKind.Cluster] = 'Cluster', _a[sym.SymbolKind.Column] = 'Column', _a[sym.SymbolKind.Command] = 'Command', _a[sym.SymbolKind.Database] = 'Database', _a[sym.SymbolKind.EntityGroup] = 'EntityGroup', _a[sym.SymbolKind.EntityGroupElement] = 'EntityGroupElement', _a[sym.SymbolKind.Error] = 'Error', _a[sym.SymbolKind.Function] = 'Function', _a[sym.SymbolKind.Graph] = 'Graph', _a[sym.SymbolKind.Group] = 'Group', _a[sym.SymbolKind.MaterializedView] = 'MaterializedView', _a[sym.SymbolKind.None] = 'None', _a[sym.SymbolKind.Operator] = 'Operator', _a[sym.SymbolKind.Option] = 'Option', _a[sym.SymbolKind.Parameter] = 'Parameter', _a[sym.SymbolKind.Pattern] = 'Pattern', _a[sym.SymbolKind.QueryOperatorParameter] = 'QueryOperatorParameter', _a[sym.SymbolKind.Primitive] = 'Primitive', _a[sym.SymbolKind.Table] = 'Table', _a[sym.SymbolKind.Tuple] = 'Tuple', _a[sym.SymbolKind.Variable] = 'Variable', _a[sym.SymbolKind.Void] = 'Void', _a); /** * Kusto Language service translates the kusto object model (transpiled from C# by Bridge.Net) * to the vscode language server types, which are used by vscode language extensions. * This should make things easier in the future to provide a vscode extension based on this translation layer. * * Further translations, if needed, to support specific editors (Atom, sublime, Etc) * should be done on top of this API, since it is (at least meant to be) a standard that is supported by multiple editors. * * Note1: Currently monaco isn't using this object model so further translation will be necessary on calling modules. * * Note2: This file is responsible for interacting with the kusto object model and exposing Microsoft language service types. * An exception to that rule is tokenization (and syntax highlighting which depends on it) - * since it's not currently part of the Microsoft language service protocol. Thus tokenize() _does_ 'leak' kusto types to the callers. */ var KustoLanguageService = /** @class */ (function () { function KustoLanguageService(schema, languageSettings) { var _a, _b, _c, _d; /** * Taken from: * https://msazure.visualstudio.com/One/_git/Azure-Kusto-Service?path=/Src/Tools/Kusto.Explorer.Control/QueryEditors/KustoScriptEditor/KustoScriptEditorControl2.xaml.cs&version=GBdev&line=2075&lineEnd=2075&lineStartColumn=9&lineEndColumn=77&lineStyle=plain&_a=contents */ this._toOptionKind = (_a = {}, _a[k2.CompletionKind.AggregateFunction] = k.OptionKind.FunctionAggregation, _a[k2.CompletionKind.BuiltInFunction] = k.OptionKind.FunctionScalar, _a[k2.CompletionKind.Cluster] = k.OptionKind.Database, _a[k2.CompletionKind.Column] = k.OptionKind.Column, _a[k2.CompletionKind.CommandPrefix] = k.OptionKind.Command, _a[k2.CompletionKind.Database] = k.OptionKind.Database, _a[k2.CompletionKind.DatabaseFunction] = k.OptionKind.FunctionServerSide, _a[k2.CompletionKind.Example] = k.OptionKind.Literal, _a[k2.CompletionKind.Identifier] = k.OptionKind.None, _a[k2.CompletionKind.Keyword] = k.OptionKind.Option, _a[k2.CompletionKind.LocalFunction] = k.OptionKind.FunctionLocal, _a[k2.CompletionKind.MaterialiedView] = k.OptionKind.MaterializedView, _a[k2.CompletionKind.Parameter] = k.OptionKind.Parameter, _a[k2.CompletionKind.Punctuation] = k.OptionKind.None, _a[k2.CompletionKind.QueryPrefix] = k.OptionKind.Operator, _a[k2.CompletionKind.RenderChart] = k.OptionKind.OptionRender, _a[k2.CompletionKind.ScalarInfix] = k.OptionKind.None, _a[k2.CompletionKind.ScalarPrefix] = k.OptionKind.Literal, _a[k2.CompletionKind.ScalarType] = k.OptionKind.DataType, _a[k2.CompletionKind.Syntax] = k.OptionKind.None, _a[k2.CompletionKind.Table] = k.OptionKind.Table, _a[k2.CompletionKind.TabularPrefix] = k.OptionKind.None, _a[k2.CompletionKind.TabularSuffix] = k.OptionKind.None, _a[k2.CompletionKind.Unknown] = k.OptionKind.None, _a[k2.CompletionKind.Variable] = k.OptionKind.Parameter, _a[k2.CompletionKind.Option] = k.OptionKind.Option, _a[k2.CompletionKind.Graph] = k.OptionKind.Graph, _a[k2.CompletionKind.EntityGroup] = k.OptionKind.EntityGroup, _a[k2.CompletionKind.StoredQueryResult] = k.OptionKind.StoredQueryResult, _a); this.disabledCompletionItemsV2 = { // render charts ladderchart: k2.CompletionKind.RenderChart, pivotchart: k2.CompletionKind.RenderChart, timeline: k2.CompletionKind.RenderChart, timepivot: k2.CompletionKind.RenderChart, '3Dchart': k2.CompletionKind.RenderChart, list: k2.CompletionKind.RenderChart, }; this._kustoKindtolsKind = (_b = {}, _b[k.OptionKind.None] = ls.CompletionItemKind.Interface, _b[k.OptionKind.Operator] = ls.CompletionItemKind.Method, _b[k.OptionKind.Command] = ls.CompletionItemKind.Method, _b[k.OptionKind.Service] = ls.CompletionItemKind.Class, _b[k.OptionKind.Policy] = ls.CompletionItemKind.Reference, _b[k.OptionKind.Database] = ls.CompletionItemKind.Class, _b[k.OptionKind.Table] = ls.CompletionItemKind.Class, _b[k.OptionKind.DataType] = ls.CompletionItemKind.Class, _b[k.OptionKind.Literal] = ls.CompletionItemKind.Property, _b[k.OptionKind.Parameter] = ls.CompletionItemKind.Variable, _b[k.OptionKind.IngestionMapping] = ls.CompletionItemKind.Variable, _b[k.OptionKind.ExpressionFunction] = ls.CompletionItemKind.Variable, _b[k.OptionKind.Option] = ls.CompletionItemKind.Interface, _b[k.OptionKind.OptionKind] = ls.CompletionItemKind.Interface, _b[k.OptionKind.OptionRender] = ls.CompletionItemKind.Interface, _b[k.OptionKind.Column] = ls.CompletionItemKind.Function, _b[k.OptionKind.ColumnString] = ls.CompletionItemKind.Field, _b[k.OptionKind.ColumnNumeric] = ls.CompletionItemKind.Field, _b[k.OptionKind.ColumnDateTime] = ls.CompletionItemKind.Field, _b[k.OptionKind.ColumnTimespan] = ls.CompletionItemKind.Field, _b[k.OptionKind.FunctionServerSide] = ls.CompletionItemKind.Field, _b[k.OptionKind.FunctionAggregation] = ls.CompletionItemKind.Field, _b[k.OptionKind.FunctionFilter] = ls.CompletionItemKind.Field, _b[k.OptionKind.FunctionScalar] = ls.CompletionItemKind.Field, _b[k.OptionKind.ClientDirective] = ls.CompletionItemKind.Enum, _b); this._kustoKindToLsKindV2 = (_c = {}, _c[k2.CompletionKind.AggregateFunction] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.BuiltInFunction] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.Cluster] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.Column] = ls.CompletionItemKind.Function, _c[k2.CompletionKind.CommandPrefix] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.Database] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.DatabaseFunction] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.Example] = ls.CompletionItemKind.Text, _c[k2.CompletionKind.Identifier] = ls.CompletionItemKind.Method, _c[k2.CompletionKind.Keyword] = ls.CompletionItemKind.Method, _c[k2.CompletionKind.LocalFunction] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.MaterialiedView] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.Parameter] = ls.CompletionItemKind.Variable, _c[k2.CompletionKind.Punctuation] = ls.CompletionItemKind.Interface, _c[k2.CompletionKind.QueryPrefix] = ls.CompletionItemKind.Function, _c[k2.CompletionKind.RenderChart] = ls.CompletionItemKind.Method, _c[k2.CompletionKind.ScalarInfix] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.ScalarPrefix] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.ScalarType] = ls.CompletionItemKind.TypeParameter, _c[k2.CompletionKind.Syntax] = ls.CompletionItemKind.Method, _c[k2.CompletionKind.Table] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.TabularPrefix] = ls.CompletionItemKind.Field, // datatable, externaldata _c[k2.CompletionKind.TabularSuffix] = ls.CompletionItemKind.Field, _c[k2.CompletionKind.Unknown] = ls.CompletionItemKind.Interface, _c[k2.CompletionKind.Variable] = ls.CompletionItemKind.Variable, _c[k2.CompletionKind.Option] = ls.CompletionItemKind.Text, _c[k2.CompletionKind.Graph] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.EntityGroup] = ls.CompletionItemKind.Class, _c[k2.CompletionKind.StoredQueryResult] = ls.CompletionItemKind.Field, _c); this._tokenKindToClassificationKind = (_d = {}, _d[TokenKind.TableToken] = k2.ClassificationKind.Table, _d[TokenKind.TableColumnToken] = k2.ClassificationKind.Column, _d[TokenKind.OperatorToken] = k2.ClassificationKind.QueryOperator, _d[TokenKind.SubOperatorToken] = k2.ClassificationKind.Function, _d[TokenKind.CalculatedColumnToken] = k2.ClassificationKind.Column, _d[TokenKind.StringLiteralToken] = k2.ClassificationKind.Literal, _d[TokenKind.FunctionNameToken] = k2.ClassificationKind.Function, _d[TokenKind.UnknownToken] = k2.ClassificationKind.PlainText, _d[TokenKind.CommentToken] = k2.ClassificationKind.Comment, _d[TokenKind.PlainTextToken] = k2.ClassificationKind.PlainText, _d[TokenKind.DataTypeToken] = k2.ClassificationKind.Type, _d[TokenKind.ControlCommandToken] = k2.ClassificationKind.PlainText, // TODO ? _d[TokenKind.CommandPartToken] = k2.ClassificationKind.PlainText, // TODO ? _d[TokenKind.QueryParametersToken] = k2.ClassificationKind.QueryParameter, _d[TokenKind.CslCommandToken] = k2.ClassificationKind.Keyword, // TODO ? _d[TokenKind.LetVariablesToken] = k2.ClassificationKind.Identifier, // TODO ? _d[TokenKind.PluginToken] = k2.ClassificationKind.Function, _d[TokenKind.BracketRangeToken] = k2.ClassificationKind.Keyword, // TODO ? _d[TokenKind.ClientDirectiveToken] = k2.ClassificationKind.Keyword, _d); this._schemaCache = {}; this._kustoJsSchema = KustoLanguageService.convertToKustoJsSchema(schema); this.__kustoJsSchemaV2 = this.convertToKustoJsSchemaV2(schema); this._schema = schema; this._clustersSetInGlobalState = new Set(); this._nonEmptyDatabaseSetInGlobalState = new Set(); // used to remove clusters that are already in the global state this.configure(languageSettings); this._newlineAppendPipePolicy = new Kusto.Data.IntelliSense.ApplyPolicy(); this._newlineAppendPipePolicy.Text = '\n| '; } KustoLanguageService.prototype.createDatabaseUniqueName = function (clusterName, databaseName) { return "".concat(clusterName, "_").concat(databaseName); }; Object.defineProperty(KustoLanguageService.prototype, "_kustoJsSchemaV2", { /** * A getter for __kustoJsSchemaV2 */ get: function () { return this.__kustoJsSchemaV2; }, /** * A setter for _kustoJsSchemaV2. After a schema (global state) is set, create 2 sets of cluster and database names. */ set: function (globalState) { this.__kustoJsSchemaV2 = globalState; this._clustersSetInGlobalState.clear(); this._nonEmptyDatabaseSetInGlobalState.clear(); // create 2 Sets with cluster names and database names based on the updated Global State. for (var i = 0; i < globalState.Clusters.Count; i++) { var clusterSymbol = this._kustoJsSchemaV2.Clusters.getItem(i); this._clustersSetInGlobalState.add(clusterSymbol.Name); for (var i2 = 0; i2 < clusterSymbol.Databases.Count; i2++) { var databaseSymbol = clusterSymbol.Databases.getItem(i2); if (databaseSymbol.Tables.Count > 0) { // only include database with tables this._nonEmptyDatabaseSetInGlobalState.add(this.createDatabaseUniqueName(clusterSymbol.Name, databaseSymbol.Name)); } } } }, enumerable: false, configurable: true }); KustoLanguageService.prototype.configure = function (languageSettings) { this._languageSettings = languageSettings; var includeExtendedSyntax = this._languageSettings.completionOptions.includeExtendedSyntax; this._completionOptions = Kusto.Language.Editor.CompletionOptions.Default.WithIncludeExtendedSyntax(includeExtendedSyntax).WithIncludePunctuationOnlySyntax(false); // Since we're still reverting to V1 intellisense for control commands, we need to update the rules provider // (which is a notion of V1 intellisense). this.createRulesProvider(this._kustoJsSchema, this._schema.clusterType); }; KustoLanguageService.prototype.doComplete = function (document, position) { return this.doCompleteV2(document, position); }; /** * important: Only use during development to test Global State. * Prints clusters, databases and tables that are currently in the GlobalState. */ KustoLanguageService.prototype.debugGlobalState = function (globals) { // iterate over clusters console.log("globals.Clusters.Count: ".concat(globals.Clusters.Count)); for (var i = 0; i < globals.Clusters.Count; i++) { var cluster = globals.Clusters.getItem(i); console.log("cluster: ".concat(cluster.Name)); // iterate over databases console.log("cluster.Databases.Count: ".concat(cluster.Databases.Count)); for (var i2 = 0; i2 < cluster.Databases.Count; i2++) { var database = cluster.Databases.getItem(i2); console.log("cluster.database: [".concat(cluster.Name, "].[").concat(database.Name, "]")); // iterate over tables console.log("cluster.Databases.Tables.Count: ".concat(database.Tables.Count)); for (var i3 = 0; i3 < database.Tables.Count; i3++) { var table = database.Tables.getItem(i3); console.log("cluster.database.table: [".concat(cluster.Name, "].[").concat(database.Name, "].[").concat(table.Name, "]")); } } } }; /** * Prepending the doc of the actual topic at the top */ KustoLanguageService.prototype.formatHelpTopic = function (helpTopic) { return "**".concat(helpTopic.Name, " [(view online)](").concat(helpTopic.Url, ")**\n\n").concat(helpTopic.LongDescription); }; KustoLanguageService.prototype.doCompleteV2 = function (document, position) { var _this = this; if (!document) { return Promise.resolve(ls.CompletionList.create([])); } var script = this.parseDocumentV2(document); // print cluster/database/tables from CodeScript.Globals // this.debugGlobalState(script.Globals); // get current command var cursorOffset = document.offsetAt(position); var currentCommand = script.GetBlockAtPosition(cursorOffset); var completionItems = currentCommand.Service.GetCompletionItems(cursorOffset, this._completionOptions); var disabledItems = this.disabledCompletionItemsV2; if (this._languageSettings.disabledCompletionItems) { this._languageSettings.disabledCompletionItems.map(function (item) { // logic will treat unknown as a '*' wildcard, meaning that if the key is in the object // the completion item will be suppressed. disabledItems[item] = k2.CompletionKind.Unknown; }); } var itemsAsArray = this.toArray(completionItems.Items); var items = itemsAsArray .filter(function (item) { return !(item && item.MatchText && disabledItems[item.MatchText] !== undefined && (disabledItems[item.MatchText] === k2.CompletionKind.Unknown || disabledItems[item.MatchText] === item.Kind)); }) .map(function (kItem, index) { var v1CompletionOption = new k.CompletionOption(_this._toOptionKind[kItem.Kind] || k.OptionKind.None, kItem.DisplayText); var helpTopic = _this.getTopic(v1CompletionOption); // If we have AfterText it means that the cursor should not be placed at end of suggested text. // In that case we switch to snippet format and represent the point where the cursor should be as // as '\$0' var _a = kItem.AfterText && kItem.AfterText.length > 0 ? { // Need to escape dollar sign since it is used as a placeholder in snippet. // Usually dollar sign is not a valid character in a function name, but grafana uses macros that start with dollars. textToInsert: "".concat(kItem.EditText.replace('$', '\\$'), "$0").concat(kItem.AfterText), format: ls.InsertTextFormat.Snippet, } : { textToInsert: kItem.EditText, format: ls.InsertTextFormat.PlainText, }, textToInsert = _a.textToInsert, format = _a.format; var lsItem = ls.CompletionItem.create(kItem.DisplayText); var startPosition = document.positionAt(completionItems.EditStart); var endPosition = document.positionAt(completionItems.EditStart + completionItems.EditLength); lsItem.textEdit = ls.TextEdit.replace(ls.Range.create(startPosition, endPosition), textToInsert); // Changing the first letter to be lower case, to ignore case-sensitive matching lsItem.filterText = kItem.MatchText.charAt(0).toLowerCase() + kItem.MatchText.slice(1); lsItem.kind = _this.kustoKindToLsKindV2(kItem.Kind); lsItem.sortText = kItem.OrderText; lsItem.insertTextFormat = format; lsItem.detail = helpTopic ? helpTopic.ShortDescription : undefined; lsItem.documentation = helpTopic ? { value: _this.formatHelpTopic(helpTopic), kind: ls.MarkupKind.Markdown } : undefined; return lsItem; }); return Promise.resolve(ls.CompletionList.create(items)); }; /** * when trying to get a topic we need the function name (abs, toLower, ETC). * The problem is that the 'Value' string also contains the arguments (e.g abs(number)), which means that we are * not able to correlate the option with its documentation. * This piece of code tries to strip this hwne getting topic. * @param completionOption the Completion option */ KustoLanguageService.prototype.getTopic = function (completionOption) { if (completionOption.Kind == k.OptionKind.FunctionScalar || completionOption.Kind == k.OptionKind.FunctionAggregation) { // from a value like 'abs(number)' remove the '(number)' so that only 'abs' will remain var indexOfParen = completionOption.Value.indexOf('('); if (indexOfParen >= 0) { completionOption = new k.CompletionOption(completionOption.Kind, completionOption.Value.substring(0, indexOfParen)); } } return k.CslDocumentation.Instance.GetTopic(completionOption); }; KustoLanguageService.prototype.doRangeFormat = function (document, range) { if (!document) { return Promise.resolve([]); } var rangeStartOffset = document.offsetAt(range.start); var rangeEndOffset = document.offsetAt(range.end); var commands = this.getFormattedCommandsInDocumentV2(document, rangeStartOffset, rangeEndOffset); if (!commands.originalRange || commands.formattedCommands.length === 0) { return Promise.resolve([]); } return Promise.resolve([ls.TextEdit.replace(commands.originalRange, commands.formattedCommands.join(''))]); }; KustoLanguageService.prototype.doDocumentFormat = function (document) { if (!document) { return Promise.resolve([]); } var startPos = document.positionAt(0); var endPos = document.positionAt(document.getText().length); var fullDocRange = ls.Range.create(startPos, endPos); var formattedDoc = this.getFormattedCommandsInDocumentV2(document).formattedCommands.join(''); return Promise.resolve([ls.TextEdit.replace(fullDocRange, formattedDoc)]); }; // Method is not triggered, instead doRangeFormat is invoked with the range of the caret's line. KustoLanguageService.prototype.doCurrentCommandFormat = function (document, caretPosition) { var offset = document.offsetAt(caretPosition); var range = this.createRange(document, offset - 1, offset + 1); return this.doRangeFormat(document, range); }; KustoLanguageService.prototype.doFolding = function (document) { if (!document) { return Promise.resolve([]); } return this.getCommandsInDocument(document).then(function (commands) { return commands.map(function (command) { // don't count the last empty line as part of the folded range (consider linux, mac, pc newlines) if (command.text.endsWith('\r\n')) { command.absoluteEnd -= 2; } else if (command.text.endsWith('\r') || command.text.endsWith('\n')) { --command.absoluteEnd; } var startPosition = document.positionAt(command.absoluteStart); var endPosition = document.positionAt(command.absoluteEnd); return { startLine: startPosition.line, startCharacter: startPosition.character, endLine: endPosition.line, endCharacter: endPosition.character, }; }); }); }; KustoLanguageService.prototype.getClusterReferences = function (document, cursorOffset) { var _a; var script = this.parseDocumentV2(document); var currentBlock = this.getCurrentCommandV2(script, cursorOffset); var clusterReferences = (_a = currentBlock === null || currentBlock === void 0 ? void 0 : currentBlock.Service) === null || _a === void 0 ? void 0 : _a.GetClusterReferences(); if (!clusterReferences) { return Promise.resolve([]); } var newClustersReferencesSet = new Set(); // used to remove duplicates // Keep only unique clusters that aren't already exist in the Global State for (var i = 0; i < clusterReferences.Count; i++) { var clusterReference = clusterReferences.getItem(i); // Because the engine client adds suffix anyway // const clusterName = Kusto.Language.KustoFacts.GetFullHostName(clusterReference.Cluster, Kusto.Language.KustoFacts.KustoWindowsNet); var clusterName = Kusto.Language.KustoFacts.GetFullHostName(clusterReference.Cluster, null); if (!this._clustersSetInGlobalState.has(clusterName)) { newClustersReferencesSet.add(clusterName); } } return Promise.resolve(Array.from(newClustersReferencesSet).map(function (clusterName) { return ({ clusterName: clusterName }); })); }; KustoLanguageService.prototype.getDatabaseReferences = function (document, cursorOffset) { var _a; var script = this.parseDocumentV2(document); var currentBlock = this.getCurrentCommandV2(script, cursorOffset); var databasesReferences = (_a = currentBlock === null || currentBlock === void 0 ? void 0 : currentBlock.Service) === null || _a === void 0 ? void 0 : _a.GetDatabaseReferences(); if (!databasesReferences) { return Promise.resolve([]); } var newDatabasesReferences = []; var newDatabasesReferencesSet = new Set(); for (var i1 = 0; i1 < databasesReferences.Count; i1++) { var databaseReference = databasesReferences.getItem(i1); var clusterHostName = Kusto.Language.KustoFacts.GetFullHostName(databaseReference.Cluster, null); // ignore duplicates var databaseReferenceUniqueId = this.createDatabaseUniqueName(clusterHostName, databaseReference.Database); if (newDatabasesReferencesSet.has(databaseReferenceUniqueId)) { continue; } newDatabasesReferencesSet.add(databaseReferenceUniqueId); // ignore references that are already in the GlobalState. var foundInGlobalState = this._nonEmptyDatabaseSetInGlobalState.has(databaseReferenceUniqueId); if (!foundInGlobalState) { newDatabasesReferences.push({ databaseName: databaseReference.Database, clusterName: clusterHostName, }); } } return Promise.resolve(newDatabasesReferences); }; KustoLanguageService.prototype.doValidation = function (document, changeIntervals, includeWarnings, includeSuggestions) { var _this = this; // didn't implement validation for v1. if (!document) { return Promise.resolve([]); } var script = this.parseDocumentV2(document); var blocks = this.toArray(script.Blocks); if (changeIntervals.length > 0) { blocks = this.getAffectedBlocks(blocks, changeIntervals); } var diagnostics = blocks .map(function (block) { // GetDiagnostics returns the errors in the block var diagnostics = _this.toArray(block.Service.GetDiagnostics()); var enableWarnings = includeWarnings !== null && includeWarnings !== void 0 ? includeWarnings : _this._languageSettings.enableQueryWarnings; var enableSuggestions = includeSuggestions !== null && includeSuggestions !== void 0 ? includeSuggestions : _this._languageSettings.enableQuerySuggestions; if (enableWarnings || enableSuggestions) { // Concat Warnings and suggestions to the diagnostics var warningAndSuggestionDiagnostics = block.Service.GetAnalyzerDiagnostics(true); var filterredDiagnostics = _this.toArray(warningAndSuggestionDiagnostics).filter(function (d) { var _a; var allowSeverity = (enableWarnings && d.Severity === 'Warning') || (enableSuggestions && d.Severity === 'Suggestion'); var allowCode = !((_a = _this._languageSettings.disabledDiagnosticCodes) === null || _a === void 0 ? void 0 : _a.includes(d.Code)); return allowSeverity && allowCode; }); diagnostics = diagnostics.concat(filterredDiagnostics); } return diagnostics; }) .reduce(function (prev, curr) { return prev.concat(curr); }, []); var lsDiagnostics = this.toLsDiagnostics(diagnostics, document); return Promise.resolve(lsDiagnostics); }; KustoLanguageService.prototype.getApplyCodeActions = function (document, start, end) { var script = this.parseDocumentV2(document); var block = this.getAffectedBlocks(this.toArray(script.Blocks), [{ start: start, end: end }])[0]; var codeActionInfo = block.Service.GetCodeActions(start, start, 0, null, true, null, new Kusto.Language.Utils.CancellationToken()); var codeActions = this.toArray(codeActionInfo.Actions); // Some code actions are of type "MenuAction". We want to flat them out, to show them seperately. var flatCodeActions = []; for (var i = 0; i < codeActions.length; i++) { flatCodeActions.push.apply(flatCodeActions, this.flattenCodeActions(codeActions[i], null)); } return flatCodeActions; }; KustoLanguageService.prototype.getResultActions = function (document, start, end) { var _this = this; var script = this.parseDocumentV2(document); var block = this.getAffectedBlocks(this.toArray(script.Blocks), [{ start: start, end: end }])[0]; var applyCodeActions = this.getApplyCodeActions(document, start, end); var resultActionsMap = applyCodeActions .map(function (applyCodeAction) { var changes = []; var codeActionResults = _this.toArray(block.Service.ApplyCodeAction(applyCodeAction, start).Actions); var changeTextAction = codeActionResults.find(function (c) { return c instanceof Kusto.Language.Editor.ChangeTextAction; }); if (changeTextAction) { changes = _this.toArray(changeTextAction.Changes).map(function (change) { return ({ start: change.Start + block.Start, deleteLength: change.DeleteLength, insertText: change.InsertText, }); }); } return { title: applyCodeAction.Title, changes: changes, kind: applyCodeAction.Kind }; }) .filter(function (resultAction) { return resultAction.changes.length; }); return Promise.resolve(resultActionsMap); }; KustoLanguageService.prototype.transformCodeActionTitle = function (currentActionTitle, parentActionTitle) { var title = currentActionTitle; switch (title) { case 'Apply': title = 'Apply once'; break; case 'Fix All': title = 'Apply to all'; break; case 'Extract Value': title = 'Extract value'; break; } if (parentActionTitle) { // We want to lower case the first character since it's going to be in brackets var parentActionTitleLowerCased = parentActionTitle.charAt(0).toUpperCase() + parentActionTitle.slice(1); title = "".concat(title, " (").concat(parentActionTitleLowerCased, ")"); } return title; }; KustoLanguageService.prototype.flattenCodeActions = function (codeAction, parentTitle) { var applyActions = []; if (codeAction instanceof k2.ApplyAction) { codeAction.Title = this.transformCodeActionTitle(codeAction.Title, parentTitle); applyActions.push(codeAction); } else if (codeAction instanceof k2.MenuAction) { var nestedCodeActions = this.toArray(codeAction.Actions); for (var i = 0; i < nestedCodeActions.length; i++) { applyActions.push.apply(applyActions, this.flattenCodeActions(nestedCodeActions[i], codeAction.Title)); } } return applyActions; }; KustoLanguageService.prototype.toLsDiagnostics = function (diagnostics, document) { return diagnostics .filter(function (diag) { return diag.HasLocation; }) .map(function (diag) { var start = document.positionAt(diag.Start); var end = document.positionAt(diag.Start + diag.Length); var range = ls.Range.create(start, end); var severity; switch (diag.Severity) { case 'Suggestion': severity = ls.DiagnosticSeverity.Information; break; case 'Warning': severity = ls.DiagnosticSeverity.Warning; break; default: severity = ls.DiagnosticSeverity.Error; } return ls.Diagnostic.create(range, diag.Message, severity, diag.Code); }); }; KustoLanguageService.prototype.getClassifications = function (document) { return __awaiter(this, void 0, void 0, function () { var codeScript, codeBlocks, classificationRanges; var _this = this; return __generator(this, function (_a) { codeScript = this.parseDocumentV2(document); codeBlocks = this.toArray(codeScript.Blocks); classificationRanges = codeBlocks.map(function (block) { var Classifications = block.Service.GetClassifications(block.Start, block.Length).Classifications; return _this.toArray(Classifications); }); return [2 /*return*/, classificationRanges.flatMap(function (ranges) { return ranges.map(function (range) { var _a = document.positionAt(range.Start), line = _a.line, character = _a.character; var length = range.Length; var kind = range.Kind; return { line: line, character: character, length: length, kind: kind }; }); })]; }); }); }; KustoLanguageService.prototype.getAffectedBlocks = function (blocks, changeIntervals) { return blocks.filter(function (block) { // a command is affected if it intersects at least on of changed ranges. return block // command can be null. we're filtering all nulls in the array. ? changeIntervals.some(function (_a) { var changeStart = _a.start, changeEnd = _a.end; // both intervals intersect if either the start or the end of interval A is inside interval B. return (block.Start >= changeStart && block.Start <= changeEnd) || (changeStart >= block.Start && changeStart <= block.End + 1); }) : false; }); }; KustoLanguageService.prototype.addClusterToSchema = function (document, clusterName, databases) { var clusterNameOnly = Kusto.Language.KustoFacts.GetHostName(clusterName); var cluster = this._kustoJsSchemaV2.GetCluster$1(clusterNameOnly); if (cluster) { // add databases that are not already in the cluster. databases .filter(function (_a) { var name = _a.name; return !cluster.GetDatabase(name); }) .forEach(function (_a) { var name = _a.name, alternativeName = _a.alternativeName; var symbol = new sym.DatabaseSymbol.$ctor3(name, alternativeName || null, undefined, false); cluster = cluster.AddDatabase(symbol); }); } if (!cluster) { var databaseSymbols = databases.map(function (_a) { var name = _a.name, alternativeName = _a.alternativeName; return new sym.DatabaseSymbol.$ctor3(name, alternativeName || null, undefined, false); }); var databaseSymbolsList = new (List(sym.DatabaseSymbol).$ctor1)(databaseSymbols); cluster = new sym.ClusterSymbol.$ctor1(clusterNameOnly, databaseSymbolsList, false); } this._kustoJsSchemaV2 = this._kustoJsSchemaV2.AddOrReplaceCluster(cluster); this._script = k2.CodeScript.From$1(document.getText(), this._kustoJsSchemaV2); return Promise.resolve(); }; KustoLanguageService.prototype.addDatabaseToSchema = function (document, clusterName, databaseSchema) { var clusterHostName = Kusto.Language.KustoFacts.GetHostName(clusterName); var cluster = this._kustoJsSchemaV2.GetCluster$1(clusterHostName); if (!cluster) { cluster = new sym.ClusterSymbol.$ctor1(clusterHostName, null, false); } var databaseSymbol = KustoLanguageService.convertToDatabaseSymbol(databaseSchema); cluster = cluster.AddOrUpdateDatabase(databaseSymbol); this._kustoJsSchemaV2 = this._kustoJsSchemaV2.AddOrReplaceCluster(cluster); this._script = k2.CodeScript.From$1(document.getText(), this._kustoJsSchemaV2); return Promise.resolve(); }; KustoLanguageService.prototype.setSchema = function (schema) { this._schema = schema; // We support intellisenseV2 only if the clusterType is "Engine", even if the setting is enabled if (schema && schema.clusterType === 'Engine') { var kustoJsSchemaV2 = this.convertToKustoJsSchemaV2(schema); this._kustoJsSchemaV2 = kustoJsSchemaV2; this._script = undefined; this._parsePropertiesV2 = undefined; } // since V2 doesn't support control commands, we're initializing V1 intellisense for both cases and we'll going to use V1 intellisense for control commands. var kustoJsSchema = schema ? KustoLanguageService.convertToKustoJsSchema(schema) : undefined; this._kustoJsSchema = kustoJsSchema; this.createRulesProvider(kustoJsSchema, schema.clusterType); return Promise.resolve(); }; KustoLanguageService.prototype.setParameters = function (scalarParameters, tabularParameters) { var _a; if (this._schema.clusterType !== 'Engine') { throw new Error('setParameters requires intellisense V2 and Engine cluster'); } this._schema.globalScalarParameters = scalarParameters; this._schema.globalTabularParameters = tabularParameters; var scalarSymbols = scalarParameters.map(function (param) { return KustoLanguageService.createParameterSymbol(param); }); var tabularSymbols = tabularParameters.map(function (param) { return KustoLanguageService.createTabularParameterSymbol(param); }); this._kustoJsSchemaV2 = this._kustoJsSchemaV2.WithParameters(KustoLanguageService.toBridgeList(__spreadArray(__spreadArray([], scalarSymbols, true), tabularSymbols, true))); this._script = (_a = this._script) === null || _a === void 0 ? void 0 : _a.WithGlobals(this._kustoJsSchemaV2); // Set parameters is only working with the below code. It didn't used to need this, why does it now?!? // Copy+pasted from setSchema var kustoJsSchema = KustoLanguageService.convertToKustoJsSchema(this._schema); this._kustoJsSchema = kustoJsSchema; this.createRulesProvider(kustoJsSchema, this._schema.clusterType); return Promise.resolve(undefined); }; /** * A combination of normalizeSchema and setSchema * @param schema schema json as received from .show schema as json * @param clusterConnectionString cluster connection string * @param databaseInContextName name of database in context * @param globalScalarParameters * @param globalTabularParameters * @param databaseInContextAlternateName alternate name of database in context */ KustoLanguageService.prototype.setSchemaFromShowSchema = function (schema, clusterConnectionString, databaseInContextName, globalScalarParameters, globalTabularParameters, databaseInContextAlternateName) { var normalized = this._normalizeSchema(schema, clusterConnectionString, databaseInContextName, databaseInContextAlternateName); return this.setSchema(__assign(__assign({}, normalized), { globalScalarParameters: globalScalarParameters, globalTabularParameters: globalTabularParameters })); }; /** * Converts the result of .show schema as json to a normalized schema used by kusto language service. * @param schema result of show schema * @param clusterConnectionString cluster connection string` * @param databaseInContextName database in context name * @param databaseInContextAlternateName database in context alternate name */ KustoLanguageService.prototype._normalizeSchema = function (schema, clusterConnectionString, databaseInContextName, databaseInContextAlternateName) { var databases = Object.keys(schema.Databases) .map(function (key) { return schema.Databases[key]; }) .map(function (_a) { var Name = _a.Name, Tables = _a.Tables, ExternalTables = _a.ExternalTables, MaterializedViews = _a.MaterializedViews, Functions = _a.Functions, _b = _a.EntityGroups, EntityGroups = _b === void 0 ? {} : _b, MinorVersion = _a.MinorVersion, MajorVersion = _a.MajorVersion; return ({ name: Name, alternateName: databaseInContextAlternateName, minorVersion: MinorVersion, majorVersion: MajorVersion, entityGroups: Object.entries(EntityGroups).map(function (_a) { var name = _a[0], members = _a[1]; return ({ name: name, members: members, }); }), tables: [].concat.apply([], [ [Tables, 'Table'], [MaterializedViews, 'MaterializedView'], [ExternalTables, 'ExternalTable'], ] .filter(function (_a) { var tableContainer = _a[0]; return tableContainer; }) .map(function (_a) { var tableContainer = _a[0], tableEntity = _a[1]; return Object.values(tableContainer).map(function (_a) { var Name = _a.Name, OrderedColumns = _a.OrderedColumns, DocString = _a.DocString; return ({ name: Name, docstring: DocString, entityType: tableEntity, columns: OrderedColumns.map(function (_a) { var Name = _a.Name, Type = _a.Type, DocString = _a.DocString, CslType = _a.CslType, Examples = _a.Examples; return ({ name: Name, type: CslType, docstring: DocString, examples: Examples, }); }), }); }); })), functions: Object.keys(Functions) .map(function (key) { return Functions[key]; }) .map(function (_a) { var Name = _a.Name, Body = _a.Body, DocString = _a.DocString, InputParameters = _a.InputParameters; return ({ name: Nam