Skip to content

Commit ad0b85b

Browse files
committed
feat!: fix compatibility issues with versions prior to 1.90
1 parent 684e47d commit ad0b85b

File tree

6 files changed

+825
-324
lines changed

6 files changed

+825
-324
lines changed

src/constants.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,11 @@ export interface ArraySpecialMember {
503503
}
504504

505505
export function getArraySpecialMembers(): ArraySpecialMember[] {
506-
const _ = (typeName: string, memberName: string, lengthExpr: string) => ({ typeName, memberName, lengthExpr });
506+
const _ = (typeName: string, memberName: string, lengthExpr: string) => ({
507+
typeName,
508+
memberName,
509+
lengthExpr
510+
});
507511

508512
return [
509513
_('PlannerInfo', 'simple_rel_array', 'simple_rel_array_size'),

src/dap.d.ts

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,6 @@ export interface Scope {
154154
*/
155155
name: string;
156156

157-
/**
158-
* A hint for how to present this scope in the UI. If this attribute is
159-
* missing, the scope is shown with a generic UI.
160-
* Values:
161-
* 'arguments': Scope contains method arguments.
162-
* 'locals': Scope contains local variables.
163-
* 'registers': Scope contains registers. Only a single `registers` scope
164-
* should be returned from a `scopes` request.
165-
* 'returnValue': Scope contains one or more return values.
166-
* etc.
167-
*/
168-
presentationHint?: 'arguments' | 'locals' | 'registers' | 'returnValue' | string;
169-
170157
/**
171158
* The variables of this scope can be retrieved by passing the value of
172159
* `variablesReference` to the `variables` request as long as execution
@@ -182,4 +169,65 @@ export interface ScopesResponse {
182169
* scopes available.
183170
*/
184171
scopes: Scope[];
172+
}
173+
174+
export interface ProtocolMessage {
175+
type: 'event' | 'response' | 'request' | string;
176+
177+
/**
178+
* Type of event, if type === 'event'
179+
*/
180+
event?: 'stopped' | string;
181+
182+
/**
183+
* The command requested or executed.
184+
*/
185+
command?: 'continue' | string;
186+
187+
/**
188+
* Event-specific information.
189+
*/
190+
body?: any;
191+
}
192+
193+
export interface StackTraceArguments {
194+
/**
195+
* Retrieve the stacktrace for this thread.
196+
*/
197+
threadId: number;
198+
199+
/**
200+
* The maximum number of frames to return. If levels is not specified or 0,
201+
* all frames are returned.
202+
*/
203+
levels?: number;
204+
205+
}
206+
207+
export interface StackFrame {
208+
/**
209+
* An identifier for the stack frame. It must be unique across all threads.
210+
* This id can be used to retrieve the scopes of the frame with the `scopes`
211+
* request or to restart the execution of a stack frame.
212+
*/
213+
id: number;
214+
}
215+
216+
export interface StackTraceResponse {
217+
/**
218+
* The frames of the stack frame. If the array has length zero, there are no
219+
* stack frames available.
220+
* This means that there is no location information available.
221+
*/
222+
stackFrames: StackFrame[];
223+
224+
/**
225+
* The total number of frames available in the stack. If omitted or if
226+
* `totalFrames` is larger than the available frames, a client is expected
227+
* to request frames until a request returns less frames than requested
228+
* (which indicates the end of the stack). Returning monotonically
229+
* increasing `totalFrames` values for subsequent requests can be used to
230+
* enforce paging in the client.
231+
*/
232+
totalFrames?: number;
185233
}

src/entrypoint.ts

Lines changed: 67 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,31 @@
11
import * as vscode from 'vscode';
22
import * as vars from './variables';
33
import * as utils from './utils';
4-
import { NodePreviewTreeViewProvider, dumpVariableToLogCommand, Configuration as config, setupConfigFiles } from './extension';
4+
import {
5+
NodePreviewTreeViewProvider as PostgresVariablesView,
6+
Configuration as config,
7+
setupExtension
8+
} from './extension';
59

6-
async function setupNodeTagFiles(execCtx: vars.ExecContext, log: utils.ILogger,
7-
context: vscode.ExtensionContext): Promise<undefined> {
8-
const section = vscode.workspace.getConfiguration(config.ConfigSections.TopLevelSection);
9-
const nodeTagFiles = section.get<string[]>(config.ConfigSections.NodeTagFiles);
10-
11-
if (!(nodeTagFiles && 0 < nodeTagFiles.length)) {
12-
const fullSectionName = config.ConfigSections.fullSection(config.ConfigSections.NodeTagFiles);
13-
log.error(`no NodeTag files defined. check ${fullSectionName} setting`);
14-
return;
15-
}
16-
17-
const handleNodeTagFile = async (path: vscode.Uri) => {
18-
if (!await utils.fileExists(path)) {
19-
return;
20-
}
21-
22-
log.debug(`processing ${path.fsPath} NodeTags file`);
23-
const document = await vscode.workspace.openTextDocument(path)
24-
try {
25-
const added = execCtx.nodeVarRegistry.updateNodeTypesFromFile(document);
26-
log.debug(`added ${added} NodeTags from ${path.fsPath} file`);
27-
} catch (err: any) {
28-
log.error(`could not initialize node tags array`, err);
29-
}
30-
}
31-
32-
const setupSingleFolder = async (folder: vscode.WorkspaceFolder) => {
33-
await Promise.all(nodeTagFiles.map(async filePath => {
34-
await handleNodeTagFile(vscode.Uri.file(folder.uri.fsPath + '/' + filePath));
35-
36-
/*
37-
* Create watcher to handle file updates and creations, but not deletions.
38-
* This is required, because extension can be activated before running
39-
* of 'configure' script and NodeTags are not created at that moment.
40-
* We will handle them later
41-
*/
42-
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(folder, filePath), false, false, true);
43-
watcher.onDidChange(uri => {
44-
log.info(`detected change in NodeTag file: ${uri.fsPath}`);
45-
handleNodeTagFile(uri);
46-
}, context.subscriptions);
47-
watcher.onDidCreate(uri => {
48-
log.info(`detected creation of NodeTag file: ${uri.fsPath}`);
49-
handleNodeTagFile(uri);
50-
}, context.subscriptions);
51-
52-
context.subscriptions.push(watcher);
53-
}));
54-
}
55-
56-
if (vscode.workspace.workspaceFolders?.length) {
57-
await Promise.all(
58-
vscode.workspace.workspaceFolders.flatMap(async folder =>
59-
await setupSingleFolder(folder)
60-
)
61-
);
10+
function createDebugFacade(context: vscode.ExtensionContext) {
11+
const debug = new utils.VsCodeDebuggerFacade();
12+
if (!utils.Features.hasEvaluateArrayLength()) {
13+
debug.switchToManualArrayExpansion();
6214
}
63-
64-
vscode.workspace.onDidChangeWorkspaceFolders(async e => {
65-
for (let i = 0; i < e.added.length; i++) {
66-
const folder = e.added[i];
67-
await setupSingleFolder(folder);
68-
}
69-
}, undefined, context.subscriptions);
15+
context.subscriptions.push(debug);
16+
return debug;
7017
}
7118

72-
function createNodeVariablesDataProvider(logger: utils.VsCodeLogger, debug: utils.VsCodeDebuggerFacade, context: vscode.ExtensionContext) {
73-
const nodeRegistry = new vars.NodeVarRegistry();
74-
const execCtx: vars.ExecContext = {
75-
debug,
76-
nodeVarRegistry: nodeRegistry,
77-
specialMemberRegistry: new vars.SpecialMemberRegistry(),
19+
function createOutputChannel() {
20+
if (utils.Features.logOutputLanguageEnabled()) {
21+
return vscode.window.createOutputChannel(config.ExtensionPrettyName, 'log');
22+
} else {
23+
return vscode.window.createOutputChannel(config.ExtensionPrettyName);
7824
}
79-
80-
/* Support for configuration files */
81-
setupConfigFiles(execCtx, logger, context);
82-
83-
/* Support for NodeTag files */
84-
setupNodeTagFiles(execCtx, logger, context);
85-
86-
return new NodePreviewTreeViewProvider(logger, execCtx);
8725
}
8826

8927
function createLogger(context: vscode.ExtensionContext): utils.VsCodeLogger {
90-
const outputChannel = vscode.window.createOutputChannel(config.ExtensionPrettyName, 'log');
28+
const outputChannel = createOutputChannel();
9129
const configuration = vscode.workspace.getConfiguration(config.ConfigSections.TopLevelSection);
9230
const getLogLevel = () => {
9331
const configValue = configuration.get(config.ConfigSections.LogLevel);
@@ -111,7 +49,8 @@ function createLogger(context: vscode.ExtensionContext): utils.VsCodeLogger {
11149
}
11250
}
11351
const logger = new utils.VsCodeLogger(outputChannel, getLogLevel());
114-
const fullConfigSectionName = config.ConfigSections.fullSection(config.ConfigSections.LogLevel);
52+
const logLevel = config.ConfigSections.LogLevel;
53+
const fullConfigSectionName = config.ConfigSections.fullSection(logLevel);
11554
vscode.workspace.onDidChangeConfiguration(event => {
11655
if (!event.affectsConfiguration(fullConfigSectionName)) {
11756
return;
@@ -124,40 +63,58 @@ function createLogger(context: vscode.ExtensionContext): utils.VsCodeLogger {
12463
return logger;
12564
}
12665

127-
export function activate(context: vscode.ExtensionContext) {
128-
const logger = createLogger(context);
129-
logger.info('Extension is activating');
130-
const debug = new utils.VsCodeDebuggerFacade();
131-
132-
/* Register command to dump variable to log */
133-
const dumpVarsToLogCmd = vscode.commands.registerCommand(config.Commands.DumpNodeToLog, async (args) => {
134-
try {
135-
await dumpVariableToLogCommand(args, logger, debug);
136-
} catch (err: any) {
137-
logger.error(`could not dump node to log`, err);
138-
}
139-
});
140-
141-
/* Setup Node variable support */
142-
143-
const dataProvider = createNodeVariablesDataProvider(logger, debug, context);
66+
function createPostgresVariablesView(context: vscode.ExtensionContext, logger: utils.ILogger,
67+
execContext: vars.ExecContext) {
68+
const nodesView = new PostgresVariablesView(logger, execContext);
69+
const treeDisposable = vscode.window.registerTreeDataProvider(config.Views.NodePreviewTreeView,
70+
nodesView);
71+
context.subscriptions.push(treeDisposable);
72+
return nodesView;
73+
}
14474

145-
const treeDisposable = vscode.window.registerTreeDataProvider(config.Views.NodePreviewTreeView, dataProvider);
146-
const asiDisposable = vscode.debug.onDidChangeActiveStackItem(() => dataProvider.refresh());
147-
const refreshVariablesCommand = vscode.commands.registerCommand(config.Commands.RefreshPostgresVariables, () => {
148-
dataProvider.refresh();
149-
});
75+
function setupDebugger(
76+
dataProvider: PostgresVariablesView,
77+
logger: utils.ILogger,
78+
context: vscode.ExtensionContext) {
79+
80+
if (utils.Features.debugFocusEnabled()) {
81+
vscode.debug.onDidChangeActiveStackItem(() => dataProvider.refresh(),
82+
undefined, context.subscriptions);
83+
} else {
84+
logger.warn(
85+
`Current version of VS Code (${vscode.version}) do not support ` +
86+
'debugFocus API, falling back to compatible event-based implementation. ' +
87+
'Some features might be not accessible. ' +
88+
'Please update VS Code to version 1.90 or higher',
89+
);
15090

151-
context.subscriptions.push(refreshVariablesCommand);
152-
context.subscriptions.push(asiDisposable);
153-
context.subscriptions.push(dumpVarsToLogCmd);
154-
context.subscriptions.push(treeDisposable);
155-
context.subscriptions.push(debug);
156-
vscode.commands.executeCommand('setContext', config.Contexts.ExtensionActivated, true);
91+
dataProvider.switchToEventBasedRefresh(context);
92+
}
93+
return;
94+
}
15795

158-
logger.info('Extension activated');
96+
export function activate(context: vscode.ExtensionContext) {
97+
const logger = createLogger(context);
98+
try {
99+
logger.info('Extension is activating');
100+
const execContext = {
101+
debug: createDebugFacade(context),
102+
nodeVarRegistry: new vars.NodeVarRegistry(),
103+
specialMemberRegistry: new vars.SpecialMemberRegistry(),
104+
} as vars.ExecContext;
105+
const nodesView = createPostgresVariablesView(context, logger, execContext);
106+
107+
setupExtension(context, execContext, logger, nodesView);
108+
109+
setupDebugger(nodesView, logger, context);
110+
111+
vscode.commands.executeCommand('setContext', config.Contexts.ExtensionActivated, true);
112+
logger.info('Extension activated');
113+
} catch (error) {
114+
logger.error('Failed to activate extension', error);
115+
}
159116
}
160117

161118
export function deactivate() {
162119
vscode.commands.executeCommand('setContext', config.Contexts.ExtensionActivated, false);
163-
}
120+
}

0 commit comments

Comments
 (0)