Commit 8ee08a32 authored by wenmo's avatar wenmo

自动补全支持上下文提示元数据

parent 2e5f576f
This diff is collapsed.
......@@ -2,13 +2,14 @@ import React, {useEffect, useImperativeHandle, useRef} from 'react';
import * as _monaco from "monaco-editor";
import MonacoEditor from "react-monaco-editor";
import {BaseDataSourceField, BaseDataSourceHeader, CompletionItem} from "./data";
import Completion from "./completion";
import styles from './index.less';
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import {DocumentStateType} from "@/pages/Document/model";
import {DocumentTableListItem} from "@/pages/Document/data";
import {parseSqlMetaData} from "@/components/Studio/StudioEvent/Utils";
import {Column, MetaData} from "@/components/Studio/StudioEvent/data";
let provider = {
dispose: () => {},
......@@ -93,6 +94,14 @@ const FlinkSqlEditor = (props:any) => {
};
const onChangeHandle = (val: string, event: { changes: { text: any }[] }) => {
let sqlMetaData = parseSqlMetaData(val);
dispatch({
type: "Studio/saveSqlMetaData",
payload: {
activeKey:tabs.panes[tabIndex].key,
sqlMetaData
},
});
onChange(val,event);
/*const curWord = event.changes[0].text;
if (curWord === ';') {
......@@ -105,63 +114,63 @@ const FlinkSqlEditor = (props:any) => {
type: "Studio/saveSql",
payload: val,
});
};
const editorDidMountHandle = (editor: any, monaco: any) => {
monacoInstance.current = monaco;
editorInstance.current = editor;
const newSecondRightFields: BaseDataSourceHeader[] = [];
(secondRightData as BaseDataSourceHeader[]).forEach((record) => {
if (record.fields && Array.isArray(record.fields)) {
record.fields.forEach((item: any) => {
newSecondRightFields.push(item);
const buildSuggestions = () => {
let suggestions: ISuggestions[] = [];
tabs.panes[tabIndex].sqlMetaData?.metaData?.forEach((item:MetaData) => {
suggestions.push({
label: item.table,
kind: _monaco.languages.CompletionItemKind.Constant,
insertText: item.table,
insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: 'FlinkSQL Connector => '+item.connector
});
item.columns.forEach((column:Column) => {
suggestions.push({
label: column.name,
kind: _monaco.languages.CompletionItemKind.Field,
insertText: column.name,
insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: 'Column => '+column.type +' from '+item.table
});
})
});
fillDocuments.forEach((item:DocumentTableListItem) => {
if(_monaco.languages.CompletionItemKind[item.category]) {
suggestions.push({
label: item.name,
kind: _monaco.languages.CompletionItemKind[item.category],
insertText: item.fillValue,
insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: item.description
});
}else {
suggestions.push({
label: item.name,
kind: _monaco.languages.CompletionItemKind.Text,
insertText: item.fillValue,
insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: item.description
});
}
});
code.current = newSecondRightFields; // 数组长度永远为1
return suggestions;
};
const editorDidMountHandle = (editor: any, monaco: any) => {
monacoInstance.current = monaco;
editorInstance.current = editor;
provider.dispose();// 清空提示项
// 提示项设值
provider = monaco.languages.registerCompletionItemProvider('sql', {
provideCompletionItems() {
let suggestions: ISuggestions[] = [];
if (code && code.current) {
code.current.forEach((record:any) => {
suggestions.push({
// label未写错 中间加空格为了隐藏大写字段名称 大写字段名称用于规避自定义提示不匹配小写的bug
label:
record.label ||
`${record.displayName} (${
record.aliasName
}) ${''}(${record.aliasName.toUpperCase()})`, // 显示名称
kind: record.kind || monaco.languages.CompletionItemKind.Field, // 这里Function也可以是别的值,主要用来显示不同的图标
insertText: record.insertText || record.aliasName, // 实际粘贴上的值
detail: record.detail || `(property) ${record.aliasName}: String`,
});
});
}
fillDocuments.forEach((item:DocumentTableListItem) => {
if(monaco.languages.CompletionItemKind[item.category]) {
suggestions.push({
label: item.name,
kind: monaco.languages.CompletionItemKind[item.category],
insertText: item.fillValue,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: item.description
});
}else {
suggestions.push({
label: item.name,
kind: monaco.languages.CompletionItemKind.Text,
insertText: item.fillValue,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: item.description
});
}
});
return {
suggestions,
suggestions:buildSuggestions(),
};
},
quickSuggestions: false,
// quickSuggestions: false,
// triggerCharacters: ['$', '.', '='],
});
editor.focus();
......
import {MetaData} from "@/components/Studio/StudioEvent/data";
export function parseSqlMetaData(sql:string) {
if(!sql||sql===''){
return false;
}
sql = sql.replaceAll('\r\n','').replaceAll(',',' ,').replaceAll(/\s+/g,' ');
let statements = getStatements(sql);
let metaDatas:MetaData[]=[];
for(let i in statements){
if(!statements[i]||statements[i]===''){
continue;
}
if(!/create\s+table/i.test(statements[i])){
continue;
}
metaDatas.push(regMetaData(statements[i]));
}
return {
statement: sql,
metaData: metaDatas,
}
}
function RegStr(text:string,reg:any){
let temp = [],data = [];
while ((temp = reg.exec(text)) !== null) {
data.push(temp[1]);
}
return data;
}
function getStatements(sql:string){
return sql.split(';');
}
function regMetaData(statement:string){
const regTable = new RegExp(/create\s+table\s+(\w+?)\s*\(/, 'ig');
let table = RegStr(statement,regTable);
const regConnector = new RegExp(/connector'\s*=\s*'(\w+?)'/, 'ig');
let connector = RegStr(statement,regConnector);
const regColumn = new RegExp(/\s+(\w+?)\s+(\w+)\s+[\)|,]/, 'ig');
let temp = [],columns = [];
while ((temp = regColumn.exec(statement)) !== null) {
columns.push({
name:temp[1],
type:temp[2]
});
}
return {
table:table[0],
connector:connector[0],
columns:columns
}
}
export type SqlMetaData = {
statement: string,
metaData: MetaData[],
};
export type MetaData = {
table: string,
connector: string,
columns: Column[],
};
export type Column = {
name: string,
type: string,
};
......@@ -12,7 +12,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
return (
<Modal
destroyOnClose
title="添加 Flink 集群"
title="添加文档内容"
visible={modalVisible}
onCancel={() => onCancel()}
footer={null}
......
......@@ -2,6 +2,7 @@ import {Effect, Reducer} from "umi";
import {
handleAddOrUpdate
} from "@/components/Common/crud";
import {SqlMetaData} from "@/components/Studio/StudioEvent/data";
export type ClusterType = {
id: number,
......@@ -75,6 +76,7 @@ export type TabsItemType = {
task?: TaskType;
console: ConsoleType;
monaco?: any;
sqlMetaData?:SqlMetaData;
}
export type TabsType = {
......@@ -127,6 +129,7 @@ export type ModelType = {
saveSql: Reducer<StateType>;
saveCurrentPath: Reducer<StateType>;
saveMonaco: Reducer<StateType>;
saveSqlMetaData: Reducer<StateType>;
saveTabs: Reducer<StateType>;
changeActiveKey: Reducer<StateType>;
saveTaskData: Reducer<StateType>;
......@@ -174,6 +177,7 @@ const Model: ModelType = {
result: {},
},
monaco: {},
sqlMetaData: undefined,
},
sql: '',
monaco: {},
......@@ -206,6 +210,7 @@ const Model: ModelType = {
result: {},
},
monaco: {},
sqlMetaData: undefined,
}],
},
session: [],
......@@ -261,6 +266,24 @@ const Model: ModelType = {
},
};
},
saveSqlMetaData(state, {payload}) {
let newCurrent = state.current;
let newTabs = state.tabs;
if(newCurrent.key == payload.activeKey){
newCurrent.sqlMetaData = payload.sqlMetaData;
}
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload.activeKey) {
newTabs.panes[i].sqlMetaData = payload.sqlMetaData;
break;
}
}
return {
...state,
current: newCurrent,
tabs: newTabs,
};
},
saveTabs(state, {payload}) {
let newCurrent = state.current;
for (let i = 0; i < payload.panes.length; i++) {
......
......@@ -344,6 +344,19 @@ export default (): React.ReactNode => {
</ul>
</Paragraph>
</Timeline.Item>
<Timeline.Item><Text code>0.3.3</Text> <Text type="secondary">2021-11-?</Text>
<p> </p>
<Paragraph>
<ul>
<li>
<Link>修复 FlinkSQL 代码提示会因为打开多个选项卡而重复的问题</Link>
</li>
<li>
<Link>新增 FlinkSQL 自动补全可以根据 sql 上下文来提示已注册的元数据的功能</Link>
</li>
</ul>
</Paragraph>
</Timeline.Item>
</Timeline>
</Card>
</PageContainer>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment