feat: support pgsql code completion (#205)

* feat: pgsql: complete sql, upgrade syntax file and complete autoImprove

* feat: pgsql: complete unit test

* feat: pgsql: update unit test for autocomplete

* feat(pgsql: update split's context type ): pgsql: update split's context type

* feat(pgsql: update schema, table, procedure, tablespace, function, view,database's rule name): pgsql

* feat: pgsql: update usualName's rule realize

* feat: pgsql:update funcName's using

---------

Co-authored-by: zhaoge <>
This commit is contained in:
XCynthia
2023-11-15 15:34:42 +08:00
committed by GitHub
parent 2e6d18e7dc
commit cbb1279f9e
24 changed files with 36285 additions and 23896 deletions

View File

@ -33,6 +33,10 @@ export enum SyntaxContextType {
FUNCTION = 'function',
/** function name that will be created */
FUNCTION_CREATE = 'functionCreate',
/** procedure name */
PROCEDURE = 'procedure',
/** procedure name that will be created */
PROCEDURE_CREATE = 'procedureCreate',
}
export interface WordRange {

View File

@ -1,9 +1,10 @@
import { Token } from 'antlr4ts';
import { CandidatesCollection } from 'antlr4-c3';
import { PostgreSQLLexer } from '../lib/pgsql/PostgreSQLLexer';
import { PostgreSQLParser, ProgramContext } from '../lib/pgsql/PostgreSQLParser';
import { PostgreSQLParser, ProgramContext, StmtContext } from '../lib/pgsql/PostgreSQLParser';
import BasicParser from './common/basicParser';
import { Suggestions } from './common/basic-parser-types';
import { PostgreSQLParserListener } from '../lib/pgsql/PostgreSQLParserListener';
import { SyntaxContextType, Suggestions, SyntaxSuggestion } from './common/basic-parser-types';
export default class PostgresSQL extends BasicParser<
PostgreSQLLexer,
@ -19,20 +20,131 @@ export default class PostgresSQL extends BasicParser<
return new PostgreSQLParser(tokenStream);
}
protected preferredRules: Set<number> = new Set();
protected preferredRules: Set<number> = new Set([
PostgreSQLParser.RULE_createTableName, // table name
PostgreSQLParser.RULE_tableName, // table name that will be created
PostgreSQLParser.RULE_funcName, // function name
PostgreSQLParser.RULE_createFuncName, // function name that will be created
PostgreSQLParser.RULE_createSchemaName, // schema name that will be created
PostgreSQLParser.RULE_schemaName, // schema name
PostgreSQLParser.RULE_createViewName, // view name that will be created
PostgreSQLParser.RULE_viewName, // view name
PostgreSQLParser.RULE_createDatabaseName, // database name that will be created
PostgreSQLParser.RULE_databaseName, // database name
PostgreSQLParser.RULE_createProcedureName, // procedure name that will be created
PostgreSQLParser.RULE_procedureName, // procedure name
]);
protected get splitListener() {
return null as any;
return new PgSqlSplitListener();
}
protected processCandidates(
candidates: CandidatesCollection,
allTokens: Token[],
caretTokenIndex: number
caretTokenIndex: number,
tokenIndexOffset: number
): Suggestions<Token> {
const originalSyntaxSuggestions: SyntaxSuggestion<Token>[] = [];
const keywords: string[] = [];
for (let candidate of candidates.rules) {
const [ruleType, candidateRule] = candidate;
const startTokenIndex = candidateRule.startTokenIndex + tokenIndexOffset;
const tokenRanges = allTokens.slice(
startTokenIndex,
caretTokenIndex + tokenIndexOffset + 1
);
let syntaxContextType: SyntaxContextType;
switch (ruleType) {
case PostgreSQLParser.RULE_createTableName: {
syntaxContextType = SyntaxContextType.TABLE_CREATE;
break;
}
case PostgreSQLParser.RULE_tableName: {
syntaxContextType = SyntaxContextType.TABLE;
break;
}
case PostgreSQLParser.RULE_createFuncName: {
syntaxContextType = SyntaxContextType.FUNCTION_CREATE;
break;
}
case PostgreSQLParser.RULE_funcName: {
syntaxContextType = SyntaxContextType.FUNCTION;
break;
}
case PostgreSQLParser.RULE_createSchemaName: {
syntaxContextType = SyntaxContextType.DATABASE_CREATE;
break;
}
case PostgreSQLParser.RULE_schemaName: {
syntaxContextType = SyntaxContextType.DATABASE;
break;
}
case PostgreSQLParser.RULE_createViewName: {
syntaxContextType = SyntaxContextType.VIEW_CREATE;
break;
}
case PostgreSQLParser.RULE_viewName: {
syntaxContextType = SyntaxContextType.VIEW;
break;
}
case PostgreSQLParser.RULE_createDatabaseName: {
syntaxContextType = SyntaxContextType.DATABASE_CREATE;
break;
}
case PostgreSQLParser.RULE_databaseName: {
syntaxContextType = SyntaxContextType.DATABASE;
break;
}
case PostgreSQLParser.RULE_createProcedureName: {
syntaxContextType = SyntaxContextType.PROCEDURE_CREATE;
break;
}
case PostgreSQLParser.RULE_procedureName: {
syntaxContextType = SyntaxContextType.PROCEDURE;
break;
}
default:
break;
}
if (syntaxContextType) {
originalSyntaxSuggestions.push({
syntaxContextType,
wordRanges: tokenRanges,
});
}
}
for (let candidate of candidates.tokens) {
const symbolicName = this._parser.vocabulary.getSymbolicName(candidate[0]);
const displayName = this._parser.vocabulary.getDisplayName(candidate[0]);
if (symbolicName && symbolicName.startsWith('KW_')) {
const keyword =
displayName.startsWith("'") && displayName.endsWith("'")
? displayName.slice(1, -1)
: displayName;
keywords.push(keyword);
}
}
return {
syntax: [],
keywords: [],
syntax: originalSyntaxSuggestions,
keywords,
};
}
}
export class PgSqlSplitListener implements PostgreSQLParserListener {
private _statementContext: ProgramContext[] = [];
enterProgram = (ctx: ProgramContext) => {
this._statementContext.push(ctx);
};
exitProgram = (ctx: ProgramContext) => {};
get statementsContext() {
return this._statementContext;
}
}