Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go to Definition support #278

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions .github/workflows/webpack_ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
cat $GITHUB_ENV

- name: Upload dist artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test_vsix
path: ${{env.vsix_name}}
Expand Down Expand Up @@ -70,4 +70,4 @@ jobs:
👋 A new build is available for this PR based on ${{ github.event.pull_request.head.sha }}.

* [Download here.](https://github.com/codefori/vscode-db2i/actions/runs/${{ github.run_id }})
* [Read more about how to test](https://github.com/codefori/vscode-db2i/blob/master/.github/pr_testing_template.md)
* [Read more about how to test](https://github.com/codefori/vscode-db2i/blob/master/.github/pr_testing_template.md)
53 changes: 44 additions & 9 deletions src/database/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ const typeMap = {

export const AllSQLTypes: SQLType[] = ["tables", "views", "aliases", "constraints", "functions", "variables", "indexes", "procedures", "sequences", "packages", "triggers", "types", "logicals"];

export const InternalTypes: {[t: string]: string} = {
"tables": `table`,
"views": `view`,
"aliases": `alias`,
"constraints": `constraint`,
"functions": `function`,
"variables": `variable`,
"indexes": `index`,
"procedures": `procedure`,
"sequences": `sequence`,
"packages": `package`,
"triggers": `trigger`,
"types": `type`,
"logicals": `logical`
}

export const SQL_ESCAPE_CHAR = `\\`;

type BasicColumnType = string|number;
Expand Down Expand Up @@ -212,27 +228,46 @@ export default class Schemas {
schema: object.BASE_SCHEMA || undefined,
name: object.BASE_OBJ || undefined
}
}));
} as BasicSQLObject));
}

/**
* @param schema Not user input
* @param object Not user input
*/
static async generateSQL(schema: string, object: string, internalType: string): Promise<string> {
static async generateSQL(schema: string, object: string, internalType: string, isBasic?: boolean): Promise<string> {
const instance = getInstance();
const connection = instance.getConnection();

const result = await connection.withTempDirectory<string>(async (tempDir) => {
const tempFilePath = path.posix.join(tempDir, `generatedSql.sql`);

let options = [
`DATABASE_OBJECT_NAME => ?`,
`DATABASE_OBJECT_LIBRARY_NAME => ?`,
`DATABASE_OBJECT_TYPE => ?`,
`DATABASE_SOURCE_FILE_NAME => '*STMF'`,
`STATEMENT_FORMATTING_OPTION => '1'`,
`SOURCE_STREAM_FILE => '${tempFilePath}'`,
`SOURCE_STREAM_FILE_END_OF_LINE => 'LF'`,
`SOURCE_STREAM_FILE_CCSID => 1208`
];

if (isBasic) {
options.push(
`CREATE_OR_REPLACE_OPTION => '0'`,
`PRIVILEGES_OPTION => '0'`,
`COMMENT_OPTION => '0'`,
`LABEL_OPTION => '0'`,
`HEADER_OPTION => '0'`,
`TRIGGER_OPTION => '0'`,
`CONSTRAINT_OPTION => '0'`,
`MASK_AND_PERMISSION_OPTION => '0'`,
);
}

await JobManager.runSQL<{ SRCDTA: string }>([
`CALL QSYS2.GENERATE_SQL( DATABASE_OBJECT_NAME => ?, DATABASE_OBJECT_LIBRARY_NAME => ?, DATABASE_OBJECT_TYPE => ?
, CREATE_OR_REPLACE_OPTION => '1', PRIVILEGES_OPTION => '0'
, DATABASE_SOURCE_FILE_NAME => '*STMF'
, STATEMENT_FORMATTING_OPTION => '0'
, SOURCE_STREAM_FILE => '${tempFilePath}'
, SOURCE_STREAM_FILE_END_OF_LINE => 'LF'
, SOURCE_STREAM_FILE_CCSID => 1208 )`
`CALL QSYS2.GENERATE_SQL( ${options.join(`, `)} )`,
].join(` `), { parameters: [object, schema, internalType] });

// TODO: eventually .content -> .getContent(), it's not available yet
Expand Down
2 changes: 2 additions & 0 deletions src/language/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { completionProvider } from "./completionProvider";
import { formatProvider } from "./formatProvider";
import { hoverProvider, openProvider } from "./hoverProvider";
import { signatureProvider } from "./parameterProvider";
import { peekProvider } from "./peekProvider";
import { checkDocumentDefintion, problemProvider } from "./problemProvider";
import { Db2StatusProvider } from "./statusProvider";

Expand All @@ -16,6 +17,7 @@ export function languageInit() {
signatureProvider,
hoverProvider,
openProvider,
peekProvider,
...problemProvider,
checkDocumentDefintion,
sqlLanguageStatus
Expand Down
67 changes: 67 additions & 0 deletions src/language/providers/peekProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { languages, workspace } from "vscode";
import { getSqlDocument } from "./logic/parse";
import { JobManager } from "../../config";
import Statement from "../../database/statement";
import { StatementType } from "../sql/types";
import { remoteAssistIsEnabled } from "./logic/available";
import Schemas, { AllSQLTypes, InternalTypes, SQLType } from "../../database/schemas";


export const peekProvider = languages.registerDefinitionProvider({ language: `sql` }, {
async provideDefinition(document, position, token) {
const standardObjects: SQLType[] = AllSQLTypes.filter(type => ![`functions`, `procedures`].includes(type));
if (!remoteAssistIsEnabled()) return;

const defaultSchema = getDefaultSchema();
const sqlDoc = getSqlDocument(document);
const offset = document.offsetAt(position);

const tokAt = sqlDoc.getTokenByOffset(offset);
const statementAt = sqlDoc.getStatementByOffset(offset);

if (statementAt) {
const refs = statementAt.getObjectReferences();

const ref = refs.find(ref => ref.tokens[0].range.start && offset <= ref.tokens[ref.tokens.length - 1].range.end);

if (ref) {
const name = Statement.noQuotes(Statement.delimName(ref.object.name, true));
const schema = Statement.noQuotes(Statement.delimName(ref.object.schema || defaultSchema, true));

let types: SQLType[] = standardObjects;

if (ref.isUDTF) {
types = [`functions`];
} else if (statementAt.type === StatementType.Call) {
types = [`procedures`];
}

const possibleObjects = await Schemas.getObjects(schema, types, {filter: name});

if (possibleObjects.length) {
const lines: string[] = [`-- Condensed version of the object definition`];
for (const obj of possibleObjects) {
const type = InternalTypes[obj.type];
if (type) {
const contents = await Schemas.generateSQL(obj.schema, obj.name, type.toUpperCase(), true);
lines.push(contents, ``, ``);
}
}

const document = await workspace.openTextDocument({ content: lines.join(`\n`), language: `sql` });

return {
uri: document.uri,
range: document.lineAt(1).range,
};
}

}
}
}
});

const getDefaultSchema = (): string => {
const currentJob = JobManager.getSelection();
return currentJob && currentJob.job.options.libraries[0] ? currentJob.job.options.libraries[0] : `QGPL`;
}
20 changes: 2 additions & 18 deletions src/views/schemaBrowser/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import { ThemeIcon, TreeItem } from "vscode"
import * as vscode from "vscode"
import Schemas, { AllSQLTypes, SQL_ESCAPE_CHAR, SQLType } from "../../database/schemas";
import Schemas, { AllSQLTypes, InternalTypes, SQL_ESCAPE_CHAR, SQLType } from "../../database/schemas";
import Table from "../../database/table";
import { getInstance, loadBase } from "../../base";

Expand All @@ -12,22 +12,6 @@ import Statement from "../../database/statement";
import { getCopyUi } from "./copyUI";
import { getAdvisedIndexesStatement, getIndexesStatement, getMTIStatement, getAuthoritiesStatement, getObjectLocksStatement } from "./statements";

const viewItem = {
"tables": `table`,
"views": `view`,
"aliases": `alias`,
"constraints": `constraint`,
"functions": `function`,
"variables": `variable`,
"indexes": `index`,
"procedures": `procedure`,
"sequences": `sequence`,
"packages": `package`,
"triggers": `trigger`,
"types": `type`,
"logicals": `logical`
}

const itemIcons = {
"table": `split-horizontal`,
"procedure": `run`,
Expand Down Expand Up @@ -577,7 +561,7 @@ class SQLObject extends vscode.TreeItem {
}

constructor(item: BasicSQLObject) {
const type = viewItem[item.type];
const type = InternalTypes[item.type];
super(Statement.prettyName(item.name), Types[type] ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None);

this.contextValue = type;
Expand Down
Loading