Add delphi sql extract

This commit is contained in:
Niels Kooiman
2022-07-01 12:25:35 +02:00
parent 6fd3ed82c2
commit defda8d8f4
5 changed files with 232 additions and 67 deletions

View File

@@ -21,7 +21,8 @@
"onCommand:extension.buildStringCsharp",
"onCommand:extension.reverseBuildStringDoubleQuote",
"onCommand:extension.reverseBuildStringSingleQuote",
"onCommand:extension.createCsharpAutoProperty"
"onCommand:extension.createCsharpAutoProperty",
"onCommand:extension.reverseDelphiQuery"
],
"main": "./out/extension",
"contributes": {
@@ -69,6 +70,10 @@
{
"command": "extension.createCsharpAutoProperty",
"title": "Solidt: Create autoproperty (C#)"
},
{
"command": "extension.reverseDelphiQuery",
"title": "Solidt: Reverse Query (Delphi)"
}
]
},
@@ -84,4 +89,4 @@
"typescript": "^3.5.1",
"@types/vscode": "^1.32.0"
}
}
}

155
src/delphi.ts Normal file
View File

@@ -0,0 +1,155 @@
function* getLinesFromString(source: string) {
let lines = String(source || "").matchAll(/^.+$/gm);
for (const [line] of lines) yield line;
}
interface IPart {
isString: boolean;
value: string;
}
function* getNextStringPartFromLine(source: string, separator?: string): IterableIterator<IPart> {
const line = String(source || "");
const sep = "'";
let inString = false;
let start = 0;
for (var i = 0; i < line.length; i++) {
const char = line[i];
// if (char === sep) {
// console.log("swithing in string");
// }
if (i + 1 === line.length) {
yield {
isString: inString,
value: line.substring(start, i + 1)
};
} else if (char === sep) {
yield {
isString: inString,
value: line.substring(start, i)
};
start = i + 1;
inString = !inString;
}
}
}
function trimAny(str: string, chars: string[]) {
var start = 0,
end = str.length;
while (start < end && chars.indexOf(str[start]) >= 0)
++start;
while (end > start && chars.indexOf(str[end - 1]) >= 0)
--end;
return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}
const reSingleLineComment = /(\/\/.*)/g;
const reMultiLineComment = /\{(.|[\r\n])*?\}/gm;
const reEmptyOrBlankLines = /\n+\s*\n/gm;
const reJoinPlusLinesEnd = /\s*\+\s*?\n/gm;
const reJoinPlusLinesStart = /\s*\n\s*?\+/gm;
function cleanUpCode(str: string) {
str = String(str).replace(reSingleLineComment, "");
str = String(str).replace(reMultiLineComment, "");
str = String(str).replace(reEmptyOrBlankLines, "\n");
str = String(str).replace(reJoinPlusLinesStart, " + ");
str = String(str).replace(reJoinPlusLinesEnd, " + ");
return str;
}
export function reverseDelphiQuery(input: string): string {
const output: string[] = [];
input = cleanUpCode(input);
for (const line of getLinesFromString(input)) {
const outputParts: string[] = [];
for (const part of getNextStringPartFromLine(line)) {
if (part.isString) {
outputParts.push(part.value);
} else {
const matches = part.value.matchAll(/[\+\(]\s*(.*)\s*[\+;]/gm);
for (const match of matches) {
const param = match[1];
const rem = trimAny(param, [' ', '+', '\t', '\r']);
if (rem.length > 0) {
const res = findStringBetweenMatchingBrace('(' + rem + ')', 0, '(', ')');
if (res.trim().length > 0) {
outputParts.push(`[[${res}]]`);
} else {
outputParts.push(`{{${res}}}`);
}
}
}
// const matches = part.value.matchAll(/\((.*)\)/gm);
// for (const match of matches) {
// const param = match[1];
// const rem = trimAny(param, [' ', '+', '\t', '\r']);
// if (rem.length > 0) {
// outputParts.push(rem);
// }
// }
}
//console.log(`part: ${part.isString ? "1" : "0"}`, part.value);
}
output.push(outputParts.join(" "));
}
return input + '\n\n' + output.join("\n");
};
function indexOfAny(str: string, anyOf: string[], startIndex: number): number {
if (!str) return -1;
if (!anyOf) return -1;
let minIndex = -1;
for (let j = 0; j < anyOf.length; j++) {
let index = str.indexOf(anyOf[j], startIndex);
if (index >= 0 && (minIndex === -1 || index < minIndex)) {
minIndex = index;
}
}
return minIndex;
};
function findStringBetweenMatchingBrace(s: string, start: number, startBrace: string, endBrace: string) {
const braces = [startBrace, endBrace];
let pos = start;
let end = start;
let level = 0;
let notStarted = true;
while (true) {
var index = indexOfAny(s, braces, pos);
if (index < 0) break;
if (notStarted) {
notStarted = false;
start = index + 1;
}
if (s[index] == startBrace) level++;
if (s[index] == endBrace) level--;
if (level <= 0) {
end = index;
break;
}
pos = index + 1;
}
return s.substring(start, end);
}

View File

@@ -1,7 +1,7 @@
const slash = "\\";
const slashslash = "\\\\";
function getEscapeChars(quote: string, doubleEscape: boolean) : { [key: string]: string } {
function getEscapeChars(quote: string, doubleEscape: boolean): { [key: string]: string } {
const chars = {
"\b": "\\b",
"\n": "\\n",
@@ -11,14 +11,14 @@ function getEscapeChars(quote: string, doubleEscape: boolean) : { [key: string]:
slash: slashslash
};
if (doubleEscape) {
(chars as any)[quote] = quote + quote;
(chars as any)[quote] = quote + quote;
} else {
(chars as any)[quote] = slash + quote;
}
return chars;
}
function getUnescapeChars(quote: string, doubleEscape: boolean) : { [key: string]: string } {
function getUnescapeChars(quote: string, doubleEscape: boolean): { [key: string]: string } {
const chars = {
"\\b": "\b",
"\\n": "\n",
@@ -28,7 +28,7 @@ function getUnescapeChars(quote: string, doubleEscape: boolean) : { [key: string
slashslash: slash
};
if (doubleEscape) {
(chars as any)[quote + quote] = quote;
(chars as any)[quote + quote] = quote;
} else {
(chars as any)[slash + quote] = quote;
}
@@ -38,79 +38,82 @@ function getUnescapeChars(quote: string, doubleEscape: boolean) : { [key: string
export function escapeStr(str: string, quote: string, doubleEscape: boolean): string {
let res = "";
const chars = getEscapeChars(quote, doubleEscape)
for (const c of String(str)) {
if (c in chars) {
res += chars[c];
} else {
res += c;
}
}
return res;
for (const c of String(str)) {
if (c in chars) {
res += chars[c];
} else {
res += c;
}
}
return res;
}
export function unescapeStr(str: string, quote: string, doubleEscape: boolean): string {
const chars = getUnescapeChars(quote, doubleEscape);
let res = String(str).replace(/(\\.)/gm, (group) => {
if (group in chars) {
return chars[group];
}
return group;
if (group in chars) {
return chars[group];
}
return group;
});
if (doubleEscape)
if (doubleEscape)
res = res.replace(quote + quote, quote);
return res;
}
export function buildString(text: string, quote: string, doubleEscape: boolean): string {
var lines = text.split('\n');
return lines.map(l => '\t' + quote + escapeStr(l, quote, doubleEscape) + quote).join(",\n");
var lines = text.split('\n');
return lines.map(l => '\t' + quote + escapeStr(l, quote, doubleEscape) + quote).join(",\n");
};
export function buildStringCsharp(text: string): string {
const prefix = "var str = string.Join(Environment.NewLine, new string[] {\n";
const postfix = "\n});";
return `${prefix}${buildString(text, '"', false)}${postfix}`;
const prefix = "var str = string.Join(Environment.NewLine, new string[] {\n";
const postfix = "\n});";
return `${prefix}${buildString(text, '"', false)}${postfix}`;
};
export function buildStringJavascript(text: string): string {
const prefix = "var str = [\n";
const postfix = "\n].join('\\n');";
return `${prefix}${buildString(text, '"', false)}${postfix}`;
const postfix = "\n].join('\\n');";
return `${prefix}${buildString(text, '"', false)}${postfix}`;
};
const getMatches = (re: RegExp, str: string): any[] => {
let match, matches = [];
while (match = re.exec(str)) {
matches.push(match);
}
return matches;
let match, matches = [];
while (match = re.exec(str)) {
matches.push(match);
}
return matches;
};
export function reverseBuildString(text: string, quote: string, doubleEscape: boolean): string {
let regEx = new RegExp(quote + "(.*[^"+ slashslash +"])" + quote, "gm");
let regEx = new RegExp(quote + "(.*[^" + slashslash + "])" + quote, "gm");
if (doubleEscape) {
regEx = new RegExp(quote + "(.*[^" + quote + "])" + quote, "gm");
regEx = new RegExp(quote + "(.*[^" + quote + "])" + quote, "gm");
}
return getMatches(regEx, text)
.map(m => unescapeStr(m[1], quote, doubleEscape))
.join("\n");
return getMatches(regEx, text)
.map(m => unescapeStr(m[1], quote, doubleEscape))
.join("\n");
};
function lowerFirst(input: string) {
return input.charAt(0).toLowerCase() + input.slice(1)
}
export function createCsharpAutoProperty(input: string)
{
const [type, name] = input.split(" ");
const pname = "_" + lowerFirst(name);
const output = [
`private ${type} ${pname};`,
`public ${type} ${name}`,
"{",
`\tget => ${pname};`,
`\tset => SetPropertyValue(nameof(${name}), ref ${pname}, value);`,
"}"
].join("\n");
return output;
}
export function createCsharpAutoProperty(input: string) {
const lines = input.split('\n');
const output = [];
for (const line of lines) {
const [type, name] = line.split(" ").map(x => x.trim());
const pname = "_" + lowerFirst(name);
output.push([
`private ${type} ${pname};`,
`public ${type} ${name}`,
"{",
`\tget => ${pname};`,
`\tset => SetPropertyValue(nameof(${name}), ref ${pname}, value);`,
"}"
].join("\n"));
}
return output.join("\n\n");
};

View File

@@ -1,22 +1,21 @@
'use strict';
import * as vscode from 'vscode';
import { reverseDelphiQuery } from "./delphi";
import { escapeStr, unescapeStr, buildString, reverseBuildString, buildStringJavascript, buildStringCsharp, createCsharpAutoProperty } from "./escape";
type Replacer = (a: string) => string;
function run(replacer: Replacer)
{
function run(replacer: Replacer) {
// Get the active text editor
let editor = vscode.window.activeTextEditor;
const editor = vscode.window.activeTextEditor;
if (editor) {
let document = editor.document;
let selection = editor.selection;
let selectedText = document.getText(selection);
let result = replacer(selectedText)
if (editor && editor.document && editor.selection) {
const selectedText = editor.document.getText(editor.selection);
if (String(selectedText).length <= 0) return;
const result = replacer(selectedText);
editor.edit(editBuilder => {
editBuilder.replace(selection, result);
editBuilder.replace(editor!.selection, result);
});
}
}
@@ -27,15 +26,16 @@ const escapeSingleQuote = (str: string): string => escapeStr(str, "'", false);
// const escapeDoubleQuoteDoubled = (str: string): string => escapeStr(str, '"', true);
// const escapeSingleQuoteDoubled = (str: string): string => escapeStr(str, "'", true);
const unescapeDoubleQuote = (str: string): string => unescapeStr(str, '"', false);
const unescapeDoubleQuote = (str: string): string => unescapeStr(str, '"', false);
const unescapeSingleQuote = (str: string): string => unescapeStr(str, "'", false);
const buildStringDoubleQuote = (str: string): string => buildString(str, '"', false);
const buildStringDoubleQuote = (str: string): string => buildString(str, '"', false);
const buildStringSingleQuote = (str: string): string => buildString(str, "'", false);
const reverseBuildStringDoubleQuote = (str: string): string => reverseBuildString(str, '"', false);
const reverseBuildStringDoubleQuote = (str: string): string => reverseBuildString(str, '"', false);
const reverseBuildStringSingleQuote = (str: string): string => reverseBuildString(str, "'", false);
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('extension.escapeDoubleQuote', () => run(escapeDoubleQuote)));
context.subscriptions.push(vscode.commands.registerCommand('extension.escapeSingleQuote', () => run(escapeSingleQuote)));
@@ -53,6 +53,5 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('extension.reverseBuildStringSingleQuote', () => run(reverseBuildStringSingleQuote)));
context.subscriptions.push(vscode.commands.registerCommand('extension.createCsharpAutoProperty', () => run(createCsharpAutoProperty)));
context.subscriptions.push(vscode.commands.registerCommand('extension.reverseDelphiQuery', () => run(reverseDelphiQuery)));
}

View File

@@ -1,11 +1,14 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"target": "es2020",
"outDir": "out",
"sourceMap": true,
"strict": true,
"rootDir": "src"
},
"exclude": ["node_modules", ".vscode-test"]
}
"exclude": [
"node_modules",
".vscode-test"
]
}