Skip to content

Commit b067f46

Browse files
committed
chore: remove using cached typedefs.list file
If we maintain our own typedefs.list file, then we should constantly monitor its relevance, but such code will become too messy and complex. Instead of setting listeners on file changes we just do not use our own typedefs.list file. Now, each file specified in 'typedefs' configuration parameter will be just passed to pgindent and it will create it's own temp copy. Actually, the fact that pgindent created new temp copies each time was the main reason to copy it's logic, but now it becomes more clear that this is more pragratic way. Anyway, it's not that performance critical.
1 parent 2e32eda commit b067f46

File tree

4 files changed

+72
-167
lines changed

4 files changed

+72
-167
lines changed

docs/config_file.md

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,13 @@ Example:
135135

136136
### Custom `typedefs.list` files
137137

138-
`typedefs.list` file is required for correct `pg_bsd_indent` work. It contains list of types that treated by formatter differently. Usually, it does not change, but sometimes you may want to change it manually. i.e. when creating new patches or writing contribs with `typedef` types.
138+
`typedefs.list` file is required for correct `pg_bsd_indent` work. It contains list of types that treated by formatter differently. During extension development you may want to create your own `typedefs.list` for your extension to later pass it to `./pgindent --list-of-typedefs=my.custom.typedefs.list`.
139139

140-
Extension creates it's own copy of `typedefs.list` in `.vscode` directory (`.vscode/pg-hacker-helper.typedefs.list`):
141-
142-
1. Take builtin `src/tools/pgindent/typedefs.list` file
143-
2. Add all custom `typedefs.list` files from `typedefs` setting
144-
3. Store into `.vscode/pg-hacker-helper.typedefs.list` file
145-
146-
After that this file will be used for all formattings.
140+
You can specify your custom `typedefs.list` files in configuration using `typedefs` setting.
147141

148142
> If `pg_bsd_indent` is not available extension will try to build it.
149-
> For this `pg_config` is required, but if it is missing, then extension will ask you to enter path to it manually.
143+
> It will perform all necessary work: building, patching, downloading (if necessary).
144+
> To build old versions `pg_config` is required - it will be searched in `./src`, but if it missing will ask you to enter path to it manually.
150145

151146
`typedefs` setting can be either plain string or array of strings - each string is a path which can be in 2 forms:
152147

@@ -167,7 +162,7 @@ Read global typedefs file stored in temporary directory.
167162

168163
```json
169164
{
170-
"typedefs": "/tmp/cached.custom.typedefs.list"
165+
"typedefs": "/tmp/custom.typedefs.list"
171166
}
172167
```
173168

src/extension.ts

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as vars from './variables';
55
import * as constants from './constants';
66
import * as dbg from './debugger';
77
import * as dap from './dap';
8-
import path from 'path';
8+
import { FormatterConfiguration, PgindentConfiguration } from './formatter';
99

1010

1111
function createDebuggerFacade(type: string, provider: NodePreviewTreeViewProvider): dbg.GenericDebuggerFacade | undefined {
@@ -40,7 +40,7 @@ export class NodePreviewTreeViewProvider implements vscode.TreeDataProvider<vars
4040
* Representation of parsed configuration file.
4141
* Used to seed ExecContext during initialization.
4242
*/
43-
configFile?: ConfigFile;
43+
configFile?: VariablesConfiguration;
4444

4545
/**
4646
* ExecContext used to pass to all members.
@@ -401,13 +401,11 @@ export async function dumpVariableToDocumentCommand(variable: dap.DebugVariable,
401401
vscode.window.showTextDocument(document);
402402
}
403403

404-
export class ConfigFile {
404+
interface VariablesConfiguration {
405405
/* Array special members */
406406
arrayInfos?: vars.ArraySpecialMemberInfo[];
407407
/* Information about type aliases */
408408
aliasInfos?: vars.AliasInfo[];
409-
/* Path to custom typedef's file */
410-
typedefs?: string[];
411409
/* Custom List types */
412410
customListTypes?: vars.ListPtrSpecialMemberInfo[];
413411
/* Types stored in HTABs */
@@ -418,6 +416,11 @@ export class ConfigFile {
418416
bitmaskEnumMembers?: vars.BitmaskMemberInfo[];
419417
}
420418

419+
class ConfigFile {
420+
variables?: VariablesConfiguration;
421+
formatter?: PgindentConfiguration;
422+
}
423+
421424
function parseConfigurationFile(configFile: any): ConfigFile | undefined {
422425
const parseArrayMember = (obj: any): vars.ArraySpecialMemberInfo | undefined => {
423426
if (!(obj && typeof obj === 'object' && obj !== null)) {
@@ -825,20 +828,38 @@ function parseConfigurationFile(configFile: any): ConfigFile | undefined {
825828
? configFile.aliases.map(parseSingleAlias).filter((a: any) => a !== undefined)
826829
: undefined;
827830

828-
const typedefs = parseTypedefs(configFile.typedefs);
829831
const customListTypes = parseListTypes(configFile.customListTypes);
830832
const htabTypes = parseHtabTypes(configFile.htab);
831833
const simpleHashTableTypes = parseSimplehashTypes(configFile.simplehash);
832834
const bitmaskEnumMembers = parseEnumBitmasks(configFile.enums);
835+
const typedefs = parseTypedefs(configFile.typedefs);
836+
837+
let variables = undefined;
838+
if ( arrayInfos?.length
839+
|| aliasInfos?.length
840+
|| customListTypes?.length
841+
|| htabTypes?.length
842+
|| simpleHashTableTypes?.length
843+
|| bitmaskEnumMembers?.length) {
844+
variables = {
845+
arrayInfos,
846+
aliasInfos,
847+
customListTypes,
848+
htabTypes,
849+
simpleHashTableTypes,
850+
bitmaskEnumMembers,
851+
}
852+
}
853+
let formatter = undefined;
854+
if (typedefs?.length) {
855+
formatter = {
856+
typedefs,
857+
}
858+
}
833859

834860
return {
835-
arrayInfos,
836-
aliasInfos,
837-
typedefs,
838-
customListTypes,
839-
htabTypes,
840-
simpleHashTableTypes,
841-
bitmaskEnumMembers,
861+
variables,
862+
formatter,
842863
}
843864
}
844865

@@ -1156,38 +1177,12 @@ export function setupExtension(context: vscode.ExtensionContext,
11561177
return;
11571178
}
11581179

1159-
if (parsedConfigFile) {
1160-
nodesView.configFile = parsedConfigFile;
1180+
if (parsedConfigFile?.variables) {
1181+
nodesView.configFile = parsedConfigFile.variables;
11611182
}
1162-
1163-
if (parsedConfigFile?.typedefs?.length) {
1164-
const typedefs = [];
1165-
for (const typedef of parsedConfigFile.typedefs) {
1166-
let p;
1167-
if (path.isAbsolute(typedef)) {
1168-
p = vscode.Uri.file(typedef);
1169-
} else {
1170-
const workspace = vscode.workspace.workspaceFolders?.length
1171-
? vscode.workspace.workspaceFolders[0]
1172-
: undefined;
1173-
if (!workspace) {
1174-
logger.warn('could not determine workspace for file %s to add typedef file', typedef);
1175-
continue;
1176-
}
11771183

1178-
p = utils.joinPath(workspace.uri, typedef);
1179-
}
1180-
1181-
if (await utils.fileExists(p)) {
1182-
typedefs.push(p);
1183-
} else {
1184-
logger.warn('typedef file %s does not exist', p.fsPath);
1185-
}
1186-
}
1187-
1188-
if (typedefs.length) {
1189-
Configuration.CustomTypedefsFiles = typedefs;
1190-
}
1184+
if (parsedConfigFile?.formatter) {
1185+
FormatterConfiguration.typedefs = parsedConfigFile.formatter.typedefs;
11911186
}
11921187
}
11931188

@@ -1550,9 +1545,6 @@ export class Configuration {
15501545
};
15511546
static ExtensionSettingsFileName = 'pgsql_hacker_helper.json';
15521547

1553-
/* Paths to custom typedefs.list files in pgsql_hacker_helper.json file */
1554-
static CustomTypedefsFiles: vscode.Uri[] | undefined = undefined;
1555-
15561548
static getLogLevel() {
15571549
return this.getConfig<string>(this.ConfigSections.LogLevel);
15581550
};

src/formatter.ts

Lines changed: 28 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,14 @@ function findSuitableWorkspace(document: vscode.TextDocument) {
2323
return vscode.workspace.workspaceFolders[0];
2424
}
2525

26-
export const typedefFile = 'pg-hacker-helper.typedefs.list';
26+
export interface PgindentConfiguration {
27+
typedefs?: string[];
28+
}
29+
export const FormatterConfiguration: PgindentConfiguration = {}
2730

2831
class PgindentDocumentFormatterProvider implements vscode.DocumentFormattingEditProvider {
29-
/* Flags found in pgindent */
30-
static pg_bsd_indentDefaultFlags = [
31-
'-bad', '-bap', '-bbb', '-bc', '-bl', '-cli1', '-cp33', '-cdb',
32-
'-nce', '-d0', '-di12', '-nfc1', '-i4', '-l79', '-lp', '-lpl',
33-
'-nip', '-npro', '-sac', '-tpg', '-ts4'
34-
];
35-
3632
private savedPgindentPath?: vscode.Uri;
3733
private savedPgbsdPath?: vscode.Uri;
38-
private savedProcessedTypedef?: vscode.Uri;
3934
constructor(private logger: utils.ILogger) {}
4035

4136
private async getPgConfigPath(workspace: vscode.WorkspaceFolder) {
@@ -236,28 +231,6 @@ class PgindentDocumentFormatterProvider implements vscode.DocumentFormattingEdit
236231
return pgBsdIndent;
237232
}
238233

239-
private getProcessedTypedefFilePath(workspace: vscode.WorkspaceFolder) {
240-
/*
241-
* Formatter module supports custom typedef.lists which are added
242-
* to builtin in 'src/tools/pgindent'. But formatter tool does not
243-
* allow specifying list of typedef.lists, so I have to merge all
244-
* files and for performance reasons this file is cached.
245-
*
246-
* Currently, it's located in '/tmp/pg-hacker-helper.typedefs.list'.
247-
*
248-
* XXX: when you are working with multiple pg versions you may have
249-
* different set of custom typedef.lists, so this can mess
250-
* everything up, so it would be more nice to store it i.e. in
251-
* '.vscode' directory.
252-
*
253-
* XXX: if you change location - do not forget to update try/catch block
254-
* where file is saved (catch block creates .vscode directory and
255-
* perform second attempt to save file).
256-
*/
257-
258-
return utils.joinPath(workspace.uri, '.vscode', typedefFile);
259-
}
260-
261234
private async saveCachedTypedefFile(content: string, typedefsFile: vscode.Uri,
262235
workspace: vscode.WorkspaceFolder) {
263236
/*
@@ -287,72 +260,30 @@ class PgindentDocumentFormatterProvider implements vscode.DocumentFormattingEdit
287260
await utils.writeFile(typedefsFile, content);
288261
}
289262

290-
private async enrichTypedefs(typedefs: Set<string>) {
291-
const customTypedefFiles = Configuration.CustomTypedefsFiles;
292-
if (!customTypedefFiles || customTypedefFiles.length === 0) {
293-
return;
263+
private async getListOfTypedefs(workspace: vscode.WorkspaceFolder) {
264+
const files = FormatterConfiguration.typedefs;
265+
if (!files?.length) {
266+
return '';
294267
}
295268

296-
for (const typedef of customTypedefFiles) {
297-
let content;
298-
try {
299-
content = await utils.readFile(typedef);
300-
} catch (err) {
301-
this.logger.warn('failed to read custom typedefs.list file %s', typedef.fsPath);
302-
continue;
269+
const typedefs = [];
270+
for (const f of files) {
271+
let typedefFile;
272+
if (path.isAbsolute(f)) {
273+
typedefFile = vscode.Uri.file(f);
274+
} else {
275+
typedefFile = utils.getWorkspacePgSrcFile(workspace.uri, f);
303276
}
304-
305-
content.split('\n').forEach(x => typedefs.add(x.trim()));
306-
}
307-
}
308-
309-
private async getProcessedTypedefs(workspace: vscode.WorkspaceFolder) {
310-
if (this.savedProcessedTypedef) {
311-
if (await utils.fileExists(this.savedProcessedTypedef)) {
312-
return this.savedProcessedTypedef;
277+
278+
if (!await utils.fileExists(typedefFile)) {
279+
this.logger.warn('could not find file %s', typedefFile);
280+
continue;
313281
}
314-
315-
this.savedProcessedTypedef = undefined;
316-
}
317-
318-
const processedTypedef = this.getProcessedTypedefFilePath(workspace);
319-
if (await utils.fileExists(processedTypedef)) {
320-
/*
321-
* This file is cache in /tmp, so may be created from another
322-
* workspace which can have different content - delete it
323-
* to prevent formatting errors.
324-
*/
325-
this.logger.info('found existing typedefs.list in .vscode directory');
326-
this.savedProcessedTypedef = processedTypedef;
327-
return processedTypedef;
282+
283+
typedefs.push(`--typedefs=${typedefFile.fsPath}`);
328284
}
329285

330-
/*
331-
* Add and remove some entries from `typedefs.list` file
332-
* downloaded from buildfarm.
333-
*
334-
* This data did not change since PG 10 and i don't think
335-
* it will change in near future.
336-
*/
337-
const rawTypedefs = await this.getDefaultTypedefs(workspace);
338-
const entries = new Set(rawTypedefs.split('\n'));
339-
340-
[
341-
'ANY', 'FD_SET', 'U', 'abs', 'allocfunc', 'boolean', 'date',
342-
'digit', 'ilist', 'interval', 'iterator', 'other', 'pointer',
343-
'printfunc', 'reference', 'string', 'timestamp', 'type', 'wrap'
344-
].forEach(e => entries.delete(e));
345-
entries.add('bool');
346-
entries.delete('');
347-
await this.enrichTypedefs(entries);
348-
349-
const arr = Array.from(entries.values());
350-
arr.sort();
351-
352-
await this.saveCachedTypedefFile(arr.join('\n'), processedTypedef, workspace);
353-
354-
this.savedProcessedTypedef = processedTypedef;
355-
return processedTypedef;
286+
return typedefs;
356287
}
357288

358289
private async getPgBsdIndent(workspace: vscode.WorkspaceFolder, pgindent: vscode.Uri) {
@@ -394,22 +325,18 @@ class PgindentDocumentFormatterProvider implements vscode.DocumentFormattingEdit
394325
pg_bsd_indent: vscode.Uri,
395326
pgindent: vscode.Uri,
396327
workspace: vscode.WorkspaceFolder) {
397-
/*
398-
* We use pg_bsd_indent directly instead of pgindent because:
399-
* - different pgindent versions behaves differently
400-
* - direct call to pg_bsd_indent is faster
401-
* - pgindent creates temp files which are not removed if error
402-
* happens - we can not track these files (main reason)
403-
*/
404-
const typedefs = await this.getProcessedTypedefs(workspace);
328+
const typedefs = await this.getListOfTypedefs(workspace);
329+
330+
/* Work in pgindent dir, so it can find default typedefs.list */
331+
const cwd = path.resolve(pgindent.fsPath, '..');
405332
try {
406333
await utils.execShell(
407334
pgindent.fsPath, [
335+
...typedefs,
408336
`--indent=${pg_bsd_indent.fsPath}`,
409-
`--typedefs=${typedefs.fsPath}`,
410337
document.fsPath,
411338
],
412-
{cwd: utils.getWorkspacePgSrcFile(workspace.uri).fsPath},
339+
{cwd},
413340
);
414341
} catch (err) {
415342
if (!(err instanceof utils.ShellExecError)) {

src/test/suite/formatting.test.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as assert from 'assert';
22
import * as vscode from 'vscode';
33
import { getTestEnv, TestEnv } from './env';
4-
import {typedefFile} from '../../formatter';
54
import * as utils from '../../utils';
65
import * as fs from 'fs';
76
import path from 'path';
@@ -33,15 +32,7 @@ suite('Formatting', async function () {
3332
/* skip */
3433
}
3534
}
36-
37-
/* Remove compiled typedef.list file after previous run */
38-
await swallow(async () => {
39-
const typedef = env.getWorkspaceFile('.vscode', typedefFile);
40-
fs.rmSync(typedef, {
41-
force: true,
42-
});
43-
});
44-
35+
4536
/* Remove cloned pg_bsd_indent */
4637
await swallow(async () => {
4738
const pgBsdIndentDir =

0 commit comments

Comments
 (0)