Skip to content

Commit

Permalink
fix: bugs and code-review
Browse files Browse the repository at this point in the history
  • Loading branch information
Raubzeug committed Mar 13, 2024
1 parent feed63e commit 7615856
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 56 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"@gravity-ui/paranoid": "^1.4.0",
"@gravity-ui/react-data-table": "^1.2.0",
"@gravity-ui/uikit": "^5.30.1",
"@gravity-ui/websql-autocomplete": "^8.0.2",
"@reduxjs/toolkit": "^2.2.1",
"@gravity-ui/websql-autocomplete": "^8.0.1",
"axios": "^0.21.2",
"bem-cn-lite": "^4.1.0",
"copy-to-clipboard": "^3.3.3",
Expand Down
9 changes: 9 additions & 0 deletions src/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {useRef} from 'react';
import {useLocation} from 'react-router';
import cn from 'bem-cn-lite';

Expand All @@ -14,6 +15,7 @@ import {Query} from '../Query/Query';
import Diagnostics from '../Diagnostics/Diagnostics';

import './ObjectGeneral.scss';
import {registerYQLCompletionItemProvider} from '../../../utils/monaco';

const b = cn('object-general');

Expand All @@ -27,11 +29,18 @@ function ObjectGeneral(props: ObjectGeneralProps) {
const location = useLocation();
const theme = useThemeValue();

const previousTenant = useRef<string>();

const [initialPage] = useSetting<string>(TENANT_INITIAL_PAGE_KEY);

const queryParams = parseQuery(location);
const {name: tenantName, tenantPage = initialPage} = queryParams;

if (tenantName && typeof tenantName === 'string' && previousTenant.current !== tenantName) {
registerYQLCompletionItemProvider(tenantName);
previousTenant.current = tenantName;
}

const renderTabContent = () => {
const {type, additionalTenantProps, additionalNodesProps} = props;
switch (tenantPage) {
Expand Down
16 changes: 12 additions & 4 deletions src/utils/monaco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,22 @@ function registerSExpressionLanguage() {
});
}

function registerYQLCompletionItemProvider() {
monaco.languages.registerCompletionItemProvider('sql', {
let completionProvider: monaco.IDisposable | undefined;

function disableCodeSuggestions(): void {
if (completionProvider) {
completionProvider.dispose();
}
}

export function registerYQLCompletionItemProvider(database: string) {
disableCodeSuggestions();
completionProvider = monaco.languages.registerCompletionItemProvider('sql', {
triggerCharacters: [' ', '\n', '', ',', '.', '`', '('],
provideCompletionItems: createProvideSuggestionsFunction(),
provideCompletionItems: createProvideSuggestionsFunction(database),
});
}

export function registerLanguages() {
registerSExpressionLanguage();
registerYQLCompletionItemProvider();
}
60 changes: 29 additions & 31 deletions src/utils/yqlSuggestions/generateSuggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,48 +25,44 @@ function wrapStringToBackticks(value: string) {
return result;
}

type Entity = {
type: 'binding' | 'connection';
name: string;
id: string;
};
function removeBackticks(value: string) {
let normalizedValue = value;
if (value.startsWith('`')) {
normalizedValue = value.slice(1, -1);
}
return normalizedValue;
}

type SuggestionType =
| keyof Omit<YqlAutocompleteResult, 'errors' | 'suggestEntity' | 'suggestDatabases'>
| Entity['type'];
type SuggestionType = keyof Omit<YqlAutocompleteResult, 'errors' | 'suggestDatabases'>;

const SuggestionsWeight: Record<SuggestionType, number> = {
suggestTemplates: 0,
suggestPragmas: 1,
binding: 2,
connection: 3,
suggestColumns: 4,
suggestColumnAliases: 5,
suggestKeywords: 6,
suggestAggregateFunctions: 7,
suggestTableFunctions: 8,
suggestWindowFunctions: 9,
suggestFunctions: 10,
suggestUdfs: 11,
suggestSimpleTypes: 12,
suggestEntity: 2,
suggestColumns: 3,
suggestColumnAliases: 4,
suggestKeywords: 5,
suggestAggregateFunctions: 6,
suggestTableFunctions: 7,
suggestWindowFunctions: 8,
suggestFunctions: 9,
suggestUdfs: 10,
suggestSimpleTypes: 11,
};

const KEEP_CACHE_MILLIS = 5 * 60 * 1000;

function getColumnsWithCache() {
const cache = new Map<string, string[]>();
return async (path: string) => {
let normalizedPath = path;
if (path.startsWith('`')) {
normalizedPath = path.slice(1, -1);
}
const normalizedPath = removeBackticks(path);
const existed = cache.get(path);
if (existed) {
return existed;
}
const columns = [];
const data = await window.api.getDescribe({path: normalizedPath});
if (data.Status === 'StatusSuccess') {
if (data?.Status === 'StatusSuccess') {
const desc = data.PathDescription;
if (desc?.Table?.Columns) {
for (const c of desc.Table.Columns) {
Expand Down Expand Up @@ -130,10 +126,16 @@ async function getSimpleTypes() {
export async function generateColumnsSuggestion(
rangeToInsertSuggestion: monaco.IRange,
suggestColumns: YqlAutocompleteResult['suggestColumns'] | undefined,
database: string,
): Promise<monaco.languages.CompletionItem[]> {
const suggestions: monaco.languages.CompletionItem[] = [];
for (const entity of suggestColumns?.tables ?? []) {
const fields = await getColumns(entity.name);
let normalizedEntityName = removeBackticks(entity.name);
// if it's relative entity path
if (!normalizedEntityName.startsWith('/')) {
normalizedEntityName = `${database}/${normalizedEntityName}`;
}
const fields = await getColumns(normalizedEntityName);
fields.forEach((columnName: string) => {
const normalizedName = wrapStringToBackticks(columnName);
let columnNameSuggestion = normalizedName;
Expand Down Expand Up @@ -283,7 +285,7 @@ export async function generatePragmasSuggestion(
}));
}

const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
const alphabet = 'abcdefghijklmnopqrstuvwxyz';

function suggestionIndexToWeight(index: number): string {
const characterInsideAlphabet = alphabet[index];
Expand All @@ -294,11 +296,7 @@ function suggestionIndexToWeight(index: number): string {
const duplicateTimes = Math.floor(index / alphabet.length);
const remains = index % alphabet.length;

const lastCharacter = alphabet[alphabet.length - 1];
if (lastCharacter === undefined) {
console.error('[unexpected error]: unable to get last alphabet character');
return '';
}
const lastCharacter = alphabet.slice(-1);

return lastCharacter.repeat(duplicateTimes) + alphabet[remains];
}
27 changes: 11 additions & 16 deletions src/utils/yqlSuggestions/yqlSuggestions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import {
CursorPosition,
YqlAutocompleteResult,
parseYqlQuery,
} from '@gravity-ui/websql-autocomplete';
import {CursorPosition, parseYqlQuery} from '@gravity-ui/websql-autocomplete';

import {
generateAggregateFunctionsSuggestion,
Expand All @@ -19,7 +15,7 @@ import {
generateWindowFunctionsSuggestion,
} from './generateSuggestions';

export function createProvideSuggestionsFunction() {
export function createProvideSuggestionsFunction(database: string) {
return async (
model: monaco.editor.ITextModel,
monacoCursorPosition: monaco.Position,
Expand All @@ -32,7 +28,12 @@ export function createProvideSuggestionsFunction() {
};
const rangeToInsertSuggestion = getRangeToInsertSuggestion(model, monacoCursorPosition);

const suggestions = await getSuggestions(model, cursorPosition, rangeToInsertSuggestion);
const suggestions = await getSuggestions(
model,
cursorPosition,
rangeToInsertSuggestion,
database,
);

return {suggestions};
};
Expand All @@ -42,9 +43,9 @@ async function getSuggestions(
model: monaco.editor.ITextModel,
cursorPosition: CursorPosition,
rangeToInsertSuggestion: monaco.IRange,
database: string,
): Promise<monaco.languages.CompletionItem[]> {
const parseResult = parseYqlQuery(model.getValue(), cursorPosition);

let entitiesSuggestions: monaco.languages.CompletionItem[] = [];
let functionsSuggestions: monaco.languages.CompletionItem[] = [];
let aggregateFunctionsSuggestions: monaco.languages.CompletionItem[] = [];
Expand All @@ -54,7 +55,7 @@ async function getSuggestions(
let simpleTypesSuggestions: monaco.languages.CompletionItem[] = [];
let pragmasSuggestions: monaco.languages.CompletionItem[] = [];

if (shouldSuggestEntities(parseResult)) {
if (parseResult.suggestEntity) {
entitiesSuggestions = await generateEntitiesSuggestion(rangeToInsertSuggestion);
}
if (parseResult.suggestFunctions) {
Expand Down Expand Up @@ -91,6 +92,7 @@ async function getSuggestions(
const columnsSuggestions = await generateColumnsSuggestion(
rangeToInsertSuggestion,
parseResult.suggestColumns,
database,
);

const keywordsSuggestions = generateKeywordsSuggestion(
Expand All @@ -115,13 +117,6 @@ async function getSuggestions(
return suggestions;
}

function shouldSuggestEntities({suggestEntity}: YqlAutocompleteResult): boolean {
if (suggestEntity) {
return true;
}
return false;
}

function getRangeToInsertSuggestion(
model: monaco.editor.ITextModel,
cursorPosition: monaco.Position,
Expand Down

0 comments on commit 7615856

Please sign in to comment.