UNPKG

flink-sql-language-server

Version:

A LSP-based language server for Apache Flink SQL

226 lines (225 loc) 8.85 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeEdgesByNodeId = exports.addFromCreateContext = exports.ignoreInsertSource = exports.FlinkStructureListener = exports.StructureNodeTypeEnum = void 0; const lsp = __importStar(require("vscode-languageserver")); const protocol_translation_1 = require("../protocol-translation"); const utils_1 = require("../utils"); var StructureNodeTypeEnum; (function (StructureNodeTypeEnum) { StructureNodeTypeEnum["SINK"] = "sink"; StructureNodeTypeEnum["SINK_DB"] = "sink_db"; StructureNodeTypeEnum["SOURCE"] = "source"; StructureNodeTypeEnum["SOURCE_DB"] = "source_db"; StructureNodeTypeEnum["DIM"] = "dim"; StructureNodeTypeEnum["SNAPSHOT"] = "snapshot"; StructureNodeTypeEnum["VIEW"] = "view"; StructureNodeTypeEnum["SELECT"] = "select"; StructureNodeTypeEnum["FILTER"] = "filter"; StructureNodeTypeEnum["GROUP"] = "group"; StructureNodeTypeEnum["UNION"] = "union"; StructureNodeTypeEnum["EXCEPT"] = "except"; StructureNodeTypeEnum["INTERSECT"] = "intersect"; StructureNodeTypeEnum["JOIN"] = "join"; StructureNodeTypeEnum["TOP_N"] = "top_n"; StructureNodeTypeEnum["CORRELATE"] = "correlate"; StructureNodeTypeEnum["UD_TF"] = "ud_tf"; StructureNodeTypeEnum["CEP"] = "cep"; })(StructureNodeTypeEnum = exports.StructureNodeTypeEnum || (exports.StructureNodeTypeEnum = {})); class FlinkStructureListener { constructor(document) { this.document = document; this.nodes = []; this.edges = []; this.id = 0; this.originalText = document.getText(); } getId() { this.id++; return this.id; } addStructureNode(ctx, type, customName) { if (!ctx.stop) { return; } const range = lsp.Range.create(this.document.positionAt(ctx.start.startIndex), this.document.positionAt(ctx.stop.stopIndex + 1)); const newNode = { id: this.getId(), name: customName ?? this.document.getText(range).trim(), type, range }; this.nodes.forEach(node => { if ((0, protocol_translation_1.rangeInRange)(this.document, node.range, newNode.range)) { const distance = (0, protocol_translation_1.rangeDistance)(this.document, node.range, newNode.range); const existingEdges = this.edges.filter(e => e.to === newNode.id); if (existingEdges.length === 0) { this.edges.push({ from: node.id, to: newNode.id, distance }); } else { let minDistance = Infinity; let directEdge; existingEdges.forEach(edge => { if (distance < edge.distance && minDistance > edge.distance) { minDistance = edge.distance; directEdge = edge; } }); if (directEdge) { const index = this.edges.findIndex(e => e === directEdge); this.edges.splice(index, 1); this.edges.push({ from: node.id, to: newNode.id, distance }); } } } }); this.nodes.push(newNode); } getNodes() { return this.nodes; } getEdges() { return this.edges.map(edge => ({ from: edge.from, to: edge.to })); } enterInsert(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.SINK); } enterQuery(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.SELECT); } enterWhere(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.FILTER); } enterGroupBy(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.GROUP); } enterOrderBy(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.TOP_N); } enterMatchRecognize(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.CEP); } enterMapQuery(ctx) { if (ctx.UNION()) { this.addStructureNode(ctx, StructureNodeTypeEnum.UNION); } else if (ctx.INTERSECT()) { this.addStructureNode(ctx, StructureNodeTypeEnum.INTERSECT); } else if (ctx.EXCEPT()) { this.addStructureNode(ctx, StructureNodeTypeEnum.EXCEPT); } } enterMapTable(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.JOIN); } enterTableReference(ctx) { if (ctx.tablePrimary().tableSource()?.tableDim()) { this.addStructureNode(ctx, StructureNodeTypeEnum.DIM); } } enterTableSource(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.SOURCE); } enterTableLateral(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.UD_TF); } enterCommaTable(ctx) { if (ctx.tableExpr().tableReference().tablePrimary().tableSource()?.tableDim()) { this.addStructureNode(ctx, StructureNodeTypeEnum.CORRELATE); } else { this.addStructureNode(ctx, StructureNodeTypeEnum.JOIN); } } enterAsTable(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.SOURCE); } enterCreateTable(ctx) { if (ctx.asTable()) { this.addStructureNode(ctx, StructureNodeTypeEnum.SINK); } } enterAsDatabase(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.SOURCE_DB); } enterCreateDatabase(ctx) { if (ctx.asDatabase()) { this.addStructureNode(ctx, StructureNodeTypeEnum.SINK_DB); } } enterCreateView(ctx) { this.addStructureNode(ctx, StructureNodeTypeEnum.VIEW, ctx.view().text.trim()); } } exports.FlinkStructureListener = FlinkStructureListener; function ignoreInsertSource(nodes, edges) { for (let i = 0; i < edges.length; i++) { const edge = edges[i]; const fromNode = nodes.find(node => node.id === edge.from); const toNode = nodes.find(node => node.id === edge.to); if (!fromNode || !toNode) { return { nodes, edges }; } if (fromNode.type === StructureNodeTypeEnum.SINK && toNode.type === StructureNodeTypeEnum.SOURCE) { const newEdges = [...edges]; newEdges.splice(i, 1); return { edges: newEdges, nodes: nodes.filter(n => n.id !== toNode.id) }; } } return { nodes, edges }; } exports.ignoreInsertSource = ignoreInsertSource; function addFromCreateContext(nodes, edges) { const viewNodes = nodes.filter(node => node.type === StructureNodeTypeEnum.VIEW); if (viewNodes.length > 0) { nodes.forEach(node => { if (node.type === StructureNodeTypeEnum.SOURCE) { const matchedViewNode = viewNodes.find(view => view.name === node.name); if (matchedViewNode) { const sourceEdge = edges.find(edge => edge.to === node.id); if (sourceEdge) { const newEdge = { from: sourceEdge.from, to: matchedViewNode.id }; (0, utils_1.removeElement)(node, nodes); edges = removeEdgesByNodeId([node.id], [...edges]); edges.push(newEdge); } } } }); } return { nodes, edges }; } exports.addFromCreateContext = addFromCreateContext; function removeEdgesByNodeId(ids, edges) { return edges.filter(edge => !ids.includes(edge.to) && !ids.includes(edge.from)); } exports.removeEdgesByNodeId = removeEdgesByNodeId;