Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit eaf730f

Browse files
author
Akos Kitta
committedMar 17, 2023
fix: propagate monitor errors to the frontend
Closes #1508 Signed-off-by: Akos Kitta <[email protected]>
1 parent 9b49712 commit eaf730f

File tree

8 files changed

+241
-133
lines changed

8 files changed

+241
-133
lines changed
 

‎arduino-ide-extension/src/browser/monitor-manager-proxy-client-impl.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ApplicationError,
23
CommandRegistry,
34
Disposable,
45
Emitter,
@@ -167,7 +168,13 @@ export class MonitorManagerProxyClientImpl
167168
const { selectedBoard, selectedPort } =
168169
this.boardsServiceProvider.boardsConfig;
169170
if (!selectedBoard || !selectedBoard.fqbn || !selectedPort) return;
170-
await this.server().startMonitor(selectedBoard, selectedPort, settings);
171+
try {
172+
await this.server().startMonitor(selectedBoard, selectedPort, settings);
173+
} catch (err) {
174+
this.messageService.error(
175+
ApplicationError.is(err) ? err.message : String(err)
176+
);
177+
}
171178
}
172179

173180
getCurrentSettings(board: Board, port: Port): Promise<MonitorSettings> {

‎arduino-ide-extension/src/browser/monitor-model.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class MonitorModel implements FrontendApplicationContribution {
3939
this._darkTheme = false;
4040
this._wsPort = 0;
4141
this._serialPort = '';
42-
this._connected = true;
42+
this._connected = false;
4343

4444
this.onChangeEmitter = new Emitter<
4545
MonitorModel.State.Change<keyof MonitorModel.State>

‎arduino-ide-extension/src/common/protocol/monitor-service.ts

+125-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Event, JsonRpcServer } from '@theia/core';
1+
import { ApplicationError, Event, JsonRpcServer, nls } from '@theia/core';
22
import {
33
PluggableMonitorSettings,
44
MonitorSettings,
@@ -46,7 +46,7 @@ export interface PluggableMonitorSetting {
4646
readonly id: string;
4747
// A human-readable label of the setting (to be displayed on the GUI)
4848
readonly label: string;
49-
// The setting type (at the moment only "enum" is avaiable)
49+
// The setting type (at the moment only "enum" is available)
5050
readonly type: string;
5151
// The values allowed on "enum" types
5252
readonly values: string[];
@@ -72,24 +72,128 @@ export namespace Monitor {
7272
};
7373
}
7474

75-
export interface Status {}
76-
export type OK = Status;
77-
export interface ErrorStatus extends Status {
78-
readonly message: string;
75+
export const MonitorErrorCodes = {
76+
ConnectionFailed: 6001,
77+
NotConnected: 6002,
78+
AlreadyConnected: 6003,
79+
MissingConfiguration: 6004,
80+
} as const;
81+
82+
export const ConnectionFailedError = createMonitorError(
83+
MonitorErrorCodes.ConnectionFailed
84+
);
85+
export const NotConnectedError = createMonitorError(
86+
MonitorErrorCodes.NotConnected
87+
);
88+
export const AlreadyConnectedError = createMonitorError(
89+
MonitorErrorCodes.AlreadyConnected
90+
);
91+
export const MissingConfigurationError = createMonitorError(
92+
MonitorErrorCodes.MissingConfiguration
93+
);
94+
95+
export function createConnectionFailedError(
96+
port: Port,
97+
details?: string
98+
): ApplicationError<number, PortDescriptor> {
99+
const { protocol, protocolLabel, address, addressLabel } = port;
100+
return ConnectionFailedError(
101+
connectionFailedErrorLabel(addressLabel, protocolLabel, details),
102+
{ protocol, address }
103+
);
79104
}
80-
export namespace Status {
81-
export function isOK(status: Status & { message?: string }): status is OK {
82-
return !!status && typeof status.message !== 'string';
83-
}
84-
export const OK: OK = {};
85-
export const NOT_CONNECTED: ErrorStatus = { message: 'Not connected.' };
86-
export const ALREADY_CONNECTED: ErrorStatus = {
87-
message: 'Already connected.',
88-
};
89-
export const CONFIG_MISSING: ErrorStatus = {
90-
message: 'Serial Config missing.',
91-
};
92-
export const UPLOAD_IN_PROGRESS: ErrorStatus = {
93-
message: 'Upload in progress.',
94-
};
105+
106+
export function createNotConnectedError(
107+
port: Port
108+
): ApplicationError<number, PortDescriptor> {
109+
const { protocol, protocolLabel, address, addressLabel } = port;
110+
return NotConnectedError(
111+
notConnectedErrorLabel(addressLabel, protocolLabel),
112+
{ protocol, address }
113+
);
114+
}
115+
116+
export function createAlreadyConnectedError(
117+
port: Port
118+
): ApplicationError<number, PortDescriptor> {
119+
const { protocol, protocolLabel, address, addressLabel } = port;
120+
return AlreadyConnectedError(
121+
alreadyConnectedErrorLabel(addressLabel, protocolLabel),
122+
{ protocol, address }
123+
);
124+
}
125+
126+
export function createMissingConfigurationError(
127+
port: Port
128+
): ApplicationError<number, PortDescriptor> {
129+
const { protocol, protocolLabel, address, addressLabel } = port;
130+
return MissingConfigurationError(
131+
missingConfigurationErrorLabel(addressLabel, protocolLabel),
132+
{ protocol, address }
133+
);
134+
}
135+
136+
/**
137+
* Bare minimum representation of a port. Supports neither UI labels nor properties.
138+
*/
139+
interface PortDescriptor {
140+
readonly protocol: string;
141+
readonly address: string;
142+
}
143+
144+
function createMonitorError(
145+
code: number
146+
): ApplicationError.Constructor<number, PortDescriptor> {
147+
return ApplicationError.declare(
148+
code,
149+
(message: string, data: PortDescriptor) => ({ data, message })
150+
);
151+
}
152+
153+
export function connectionFailedErrorLabel(
154+
addressLabel: string,
155+
protocolLabel: string,
156+
details?: string
157+
): string {
158+
const formattedDetails = details ? `: ${details}.` : '.';
159+
return nls.localize(
160+
'arduino/monitor/connectionFailedError',
161+
'Could not connect to {0} {1} port{2}',
162+
addressLabel,
163+
protocolLabel,
164+
formattedDetails
165+
);
166+
}
167+
export function notConnectedErrorLabel(
168+
addressLabel: string,
169+
protocolLabel: string
170+
): string {
171+
return nls.localize(
172+
'arduino/monitor/notConnectedError',
173+
'Not connected to {0} {1} port.',
174+
addressLabel,
175+
protocolLabel
176+
);
177+
}
178+
export function alreadyConnectedErrorLabel(
179+
addressLabel: string,
180+
protocolLabel: string
181+
): string {
182+
return nls.localize(
183+
'arduino/monitor/alreadyConnectedError',
184+
'Could not connect to {0} {1} port. Already connected.',
185+
addressLabel,
186+
protocolLabel
187+
);
188+
}
189+
export function missingConfigurationErrorLabel(
190+
addressLabel: string,
191+
protocolLabel: string
192+
): string {
193+
return nls.localize(
194+
'arduino/monitor/missingConfigurationError',
195+
'Could not connect to {0} {1} port. The monitor configuration is missing.',
196+
addressLabel,
197+
protocolLabel
198+
);
95199
}

‎arduino-ide-extension/src/node/core-service-impl.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
UploadUsingProgrammerResponse,
2424
} from './cli-protocol/cc/arduino/cli/commands/v1/upload_pb';
2525
import { ResponseService } from '../common/protocol/response-service';
26-
import { OutputMessage, Port, Status } from '../common/protocol';
26+
import { OutputMessage, Port } from '../common/protocol';
2727
import { ArduinoCoreServiceClient } from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb';
2828
import { Port as RpcPort } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb';
2929
import { ApplicationError, CommandService, Disposable, nls } from '@theia/core';
@@ -392,7 +392,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService {
392392
}: {
393393
fqbn?: string | undefined;
394394
port?: Port | undefined;
395-
}): Promise<Status> {
395+
}): Promise<void> {
396396
this.boardDiscovery.setUploadInProgress(false);
397397
return this.monitorManager.notifyUploadFinished(fqbn, port);
398398
}

‎arduino-ide-extension/src/node/monitor-manager-proxy-impl.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { inject, injectable } from '@theia/core/shared/inversify';
22
import {
33
MonitorManagerProxy,
44
MonitorManagerProxyClient,
5-
Status,
65
} from '../common/protocol';
76
import { Board, Port } from '../common/protocol';
87
import { MonitorManager } from './monitor-manager';
@@ -41,11 +40,8 @@ export class MonitorManagerProxyImpl implements MonitorManagerProxy {
4140
await this.changeMonitorSettings(board, port, settings);
4241
}
4342

44-
const connectToClient = (status: Status) => {
45-
if (status === Status.ALREADY_CONNECTED || status === Status.OK) {
46-
// Monitor started correctly, connect it with the frontend
47-
this.client.connect(this.manager.getWebsocketAddressPort(board, port));
48-
}
43+
const connectToClient = () => {
44+
this.client.connect(this.manager.getWebsocketAddressPort(board, port));
4945
};
5046
return this.manager.startMonitor(board, port, connectToClient);
5147
}

‎arduino-ide-extension/src/node/monitor-manager.ts

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { ILogger } from '@theia/core';
22
import { inject, injectable, named } from '@theia/core/shared/inversify';
3-
import { Board, BoardsService, Port, Status } from '../common/protocol';
3+
import {
4+
AlreadyConnectedError,
5+
Board,
6+
BoardsService,
7+
Port,
8+
} from '../common/protocol';
49
import { CoreClientAware } from './core-client-provider';
510
import { MonitorService } from './monitor-service';
611
import { MonitorServiceFactory } from './monitor-service-factory';
@@ -36,7 +41,7 @@ export class MonitorManager extends CoreClientAware {
3641
private monitorServiceStartQueue: {
3742
monitorID: string;
3843
serviceStartParams: [Board, Port];
39-
connectToClient: (status: Status) => void;
44+
connectToClient: () => void;
4045
}[] = [];
4146

4247
@inject(MonitorServiceFactory)
@@ -104,7 +109,7 @@ export class MonitorManager extends CoreClientAware {
104109
async startMonitor(
105110
board: Board,
106111
port: Port,
107-
connectToClient: (status: Status) => void
112+
connectToClient: () => void
108113
): Promise<void> {
109114
const monitorID = this.monitorID(board.fqbn, port);
110115

@@ -127,8 +132,14 @@ export class MonitorManager extends CoreClientAware {
127132
return;
128133
}
129134

130-
const result = await monitor.start();
131-
connectToClient(result);
135+
try {
136+
await monitor.start();
137+
} catch (err) {
138+
if (!AlreadyConnectedError.is(err)) {
139+
throw err;
140+
}
141+
}
142+
await connectToClient();
132143
}
133144

134145
/**
@@ -202,8 +213,7 @@ export class MonitorManager extends CoreClientAware {
202213
async notifyUploadFinished(
203214
fqbn?: string | undefined,
204215
port?: Port
205-
): Promise<Status> {
206-
let status: Status = Status.NOT_CONNECTED;
216+
): Promise<void> {
207217
let portDidChangeOnUpload = false;
208218

209219
// We have no way of knowing which monitor
@@ -214,7 +224,7 @@ export class MonitorManager extends CoreClientAware {
214224

215225
const monitor = this.monitorServices.get(monitorID);
216226
if (monitor) {
217-
status = await monitor.start();
227+
await monitor.start();
218228
}
219229

220230
// this monitorID will only be present in "disposedForUpload"
@@ -232,7 +242,6 @@ export class MonitorManager extends CoreClientAware {
232242
}
233243

234244
await this.startQueuedServices(portDidChangeOnUpload);
235-
return status;
236245
}
237246

238247
async startQueuedServices(portDidChangeOnUpload: boolean): Promise<void> {
@@ -261,8 +270,8 @@ export class MonitorManager extends CoreClientAware {
261270
const monitorService = this.monitorServices.get(monitorID);
262271

263272
if (monitorService) {
264-
const result = await monitorService.start();
265-
connectToClient(result);
273+
await monitorService.start();
274+
await connectToClient();
266275
}
267276
}
268277
}

‎arduino-ide-extension/src/node/monitor-service.ts

+78-91
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
import { ClientDuplexStream } from '@grpc/grpc-js';
2-
import { Disposable, Emitter, ILogger } from '@theia/core';
2+
import {
3+
ApplicationError,
4+
Disposable,
5+
Emitter,
6+
ILogger,
7+
nls,
8+
} from '@theia/core';
39
import { inject, named, postConstruct } from '@theia/core/shared/inversify';
410
import { diff, Operation } from 'just-diff';
5-
import { Board, Port, Status, Monitor } from '../common/protocol';
11+
import {
12+
Board,
13+
Port,
14+
Monitor,
15+
createAlreadyConnectedError,
16+
createMissingConfigurationError,
17+
createNotConnectedError,
18+
createConnectionFailedError,
19+
} from '../common/protocol';
620
import {
721
EnumerateMonitorPortSettingsRequest,
822
EnumerateMonitorPortSettingsResponse,
@@ -19,8 +33,13 @@ import {
1933
PluggableMonitorSettings,
2034
MonitorSettingsProvider,
2135
} from './monitor-settings/monitor-settings-provider';
22-
import { Deferred } from '@theia/core/lib/common/promise-util';
36+
import {
37+
Deferred,
38+
retry,
39+
timeoutReject,
40+
} from '@theia/core/lib/common/promise-util';
2341
import { MonitorServiceFactoryOptions } from './monitor-service-factory';
42+
import { ServiceError } from './service-error';
2443

2544
export const MonitorServiceName = 'monitor-service';
2645
type DuplexHandlerKeys =
@@ -76,7 +95,7 @@ export class MonitorService extends CoreClientAware implements Disposable {
7695
readonly onDispose = this.onDisposeEmitter.event;
7796

7897
private _initialized = new Deferred<void>();
79-
private creating: Deferred<Status>;
98+
private creating: Deferred<void>;
8099
private readonly board: Board;
81100
private readonly port: Port;
82101
private readonly monitorID: string;
@@ -156,23 +175,22 @@ export class MonitorService extends CoreClientAware implements Disposable {
156175
* Start and connects a monitor using currently set board and port.
157176
* If a monitor is already started or board fqbn, port address and/or protocol
158177
* are missing nothing happens.
159-
* @returns a status to verify connection has been established.
160178
*/
161-
async start(): Promise<Status> {
179+
async start(): Promise<void> {
162180
if (this.creating?.state === 'unresolved') return this.creating.promise;
163181
this.creating = new Deferred();
164182
if (this.duplex) {
165183
this.updateClientsSettings({
166184
monitorUISettings: { connected: true, serialPort: this.port.address },
167185
});
168-
this.creating.resolve(Status.ALREADY_CONNECTED);
186+
this.creating.reject(createAlreadyConnectedError(this.port));
169187
return this.creating.promise;
170188
}
171189

172190
if (!this.board?.fqbn || !this.port?.address || !this.port?.protocol) {
173191
this.updateClientsSettings({ monitorUISettings: { connected: false } });
174192

175-
this.creating.resolve(Status.CONFIG_MISSING);
193+
this.creating.reject(createMissingConfigurationError(this.port));
176194
return this.creating.promise;
177195
}
178196

@@ -218,10 +236,8 @@ export class MonitorService extends CoreClientAware implements Disposable {
218236
}
219237
monitorRequest.setPortConfiguration(config);
220238

221-
const wroteToStreamSuccessfully = await this.pollWriteToStream(
222-
monitorRequest
223-
);
224-
if (wroteToStreamSuccessfully) {
239+
try {
240+
await this.pollWriteToStream(monitorRequest);
225241
// Only store the config, if the monitor has successfully started.
226242
this.currentPortConfigSnapshot = MonitorPortConfiguration.toObject(
227243
false,
@@ -239,13 +255,20 @@ export class MonitorService extends CoreClientAware implements Disposable {
239255
this.updateClientsSettings({
240256
monitorUISettings: { connected: true, serialPort: this.port.address },
241257
});
242-
this.creating.resolve(Status.OK);
258+
this.creating.resolve();
243259
return this.creating.promise;
244-
} else {
260+
} catch (err) {
245261
this.logger.warn(
246262
`failed starting monitor to ${this.port?.address} using ${this.port?.protocol}`
247263
);
248-
this.creating.resolve(Status.NOT_CONNECTED);
264+
this.creating.reject(
265+
ApplicationError.is(err)
266+
? err
267+
: createConnectionFailedError(
268+
this.port,
269+
err instanceof Error ? err.message : String(err)
270+
)
271+
);
249272
return this.creating.promise;
250273
}
251274
}
@@ -287,21 +310,20 @@ export class MonitorService extends CoreClientAware implements Disposable {
287310
}
288311
}
289312

290-
pollWriteToStream(request: MonitorRequest): Promise<boolean> {
291-
let attemptsRemaining = MAX_WRITE_TO_STREAM_TRIES;
292-
const writeTimeoutMs = WRITE_TO_STREAM_TIMEOUT_MS;
293-
313+
pollWriteToStream(request: MonitorRequest): Promise<void> {
294314
const createWriteToStreamExecutor =
295315
(duplex: ClientDuplexStream<MonitorRequest, MonitorResponse>) =>
296-
(resolve: (value: boolean) => void, reject: () => void) => {
316+
(
317+
resolve: (value?: unknown) => void,
318+
reject: (reason?: unknown) => void
319+
) => {
297320
const resolvingDuplexHandlers: DuplexHandler[] = [
298321
{
299322
key: 'error',
300323
callback: async (err: Error) => {
301324
this.logger.error(err);
302-
resolve(false);
303-
// TODO
304-
// this.theiaFEClient?.notifyError()
325+
const details = ServiceError.is(err) ? err.details : err.message;
326+
reject(createConnectionFailedError(this.port, details));
305327
},
306328
},
307329
{
@@ -313,79 +335,47 @@ export class MonitorService extends CoreClientAware implements Disposable {
313335
return;
314336
}
315337
if (monitorResponse.getSuccess()) {
316-
resolve(true);
338+
resolve();
317339
return;
318340
}
319341
const data = monitorResponse.getRxData();
320342
const message =
321343
typeof data === 'string'
322344
? data
323-
: this.streamingTextDecoder.decode(data, {stream:true});
345+
: this.streamingTextDecoder.decode(data, { stream: true });
324346
this.messages.push(...splitLines(message));
325347
},
326348
},
327349
];
328350

329351
this.setDuplexHandlers(duplex, resolvingDuplexHandlers);
330-
331-
setTimeout(() => {
332-
reject();
333-
}, writeTimeoutMs);
334352
duplex.write(request);
335353
};
336354

337-
const pollWriteToStream = new Promise<boolean>((resolve) => {
338-
const startPolling = async () => {
339-
// here we create a new duplex but we don't yet
340-
// set "this.duplex", nor do we use "this.duplex" in our poll
341-
// as duplex 'end' / 'close' events (which we do not "await")
342-
// will set "this.duplex" to null
343-
const createdDuplex = await this.createDuplex();
344-
345-
let pollingIsSuccessful;
346-
// attempt a "writeToStream" and "await" CLI response: success (true) or error (false)
347-
// if we get neither within WRITE_TO_STREAM_TIMEOUT_MS or an error we get undefined
348-
try {
349-
const writeToStream = createWriteToStreamExecutor(createdDuplex);
350-
pollingIsSuccessful = await new Promise(writeToStream);
351-
} catch (error) {
352-
this.logger.error(error);
353-
}
354-
355-
// CLI confirmed port opened successfully
356-
if (pollingIsSuccessful) {
357-
this.duplex = createdDuplex;
358-
resolve(true);
359-
return;
360-
}
361-
362-
// if "pollingIsSuccessful" is false
363-
// the CLI gave us an error, lets try again
364-
// after waiting 2 seconds if we've not already
365-
// reached MAX_WRITE_TO_STREAM_TRIES
366-
if (pollingIsSuccessful === false) {
367-
attemptsRemaining -= 1;
368-
if (attemptsRemaining > 0) {
369-
setTimeout(startPolling, 2000);
370-
return;
371-
} else {
372-
resolve(false);
373-
return;
355+
return Promise.race([
356+
retry(
357+
async () => {
358+
let createdDuplex = undefined;
359+
try {
360+
createdDuplex = await this.createDuplex();
361+
await new Promise(createWriteToStreamExecutor(createdDuplex));
362+
this.duplex = createdDuplex;
363+
} catch (err) {
364+
createdDuplex?.end();
365+
throw err;
374366
}
375-
}
376-
377-
// "pollingIsSuccessful" remains undefined:
378-
// we got no response from the CLI within 30 seconds
379-
// resolve to false and end the duplex connection
380-
resolve(false);
381-
createdDuplex.end();
382-
return;
383-
};
384-
385-
startPolling();
386-
});
387-
388-
return pollWriteToStream;
367+
},
368+
2_000,
369+
MAX_WRITE_TO_STREAM_TRIES
370+
),
371+
timeoutReject(
372+
WRITE_TO_STREAM_TIMEOUT_MS,
373+
nls.localize(
374+
'arduino/monitor/connectionTimeout',
375+
"Timeout. The IDE has not received the 'success' message from the monitor after successfully connecting to it."
376+
)
377+
),
378+
]) as Promise<unknown> as Promise<void>;
389379
}
390380

391381
/**
@@ -429,24 +419,22 @@ export class MonitorService extends CoreClientAware implements Disposable {
429419
* @param message string sent to running monitor
430420
* @returns a status to verify message has been sent.
431421
*/
432-
async send(message: string): Promise<Status> {
422+
async send(message: string): Promise<void> {
433423
if (!this.duplex) {
434-
return Status.NOT_CONNECTED;
424+
throw createNotConnectedError(this.port);
435425
}
436426
const coreClient = await this.coreClient;
437427
const { instance } = coreClient;
438428

439429
const req = new MonitorRequest();
440430
req.setInstance(instance);
441431
req.setTxData(new TextEncoder().encode(message));
442-
return new Promise<Status>((resolve) => {
432+
return new Promise<void>((resolve, reject) => {
443433
if (this.duplex) {
444-
this.duplex?.write(req, () => {
445-
resolve(Status.OK);
446-
});
434+
this.duplex?.write(req, resolve);
447435
return;
448436
}
449-
this.stop().then(() => resolve(Status.NOT_CONNECTED));
437+
this.stop().then(() => reject(createNotConnectedError(this.port)));
450438
});
451439
}
452440

@@ -510,7 +498,7 @@ export class MonitorService extends CoreClientAware implements Disposable {
510498
* @param settings map of monitor settings to change
511499
* @returns a status to verify settings have been sent.
512500
*/
513-
async changeSettings(settings: MonitorSettings): Promise<Status> {
501+
async changeSettings(settings: MonitorSettings): Promise<void> {
514502
const config = new MonitorPortConfiguration();
515503
const { pluggableMonitorSettings } = settings;
516504
const reconciledSettings = await this.monitorSettingsProvider.setSettings(
@@ -537,15 +525,15 @@ export class MonitorService extends CoreClientAware implements Disposable {
537525
});
538526

539527
if (!this.duplex) {
540-
return Status.NOT_CONNECTED;
528+
throw createNotConnectedError(this.port);
541529
}
542530

543531
const diffConfig = this.maybeUpdatePortConfigSnapshot(config);
544532
if (!diffConfig) {
545533
this.logger.info(
546534
`No port configuration changes have been detected. No need to send configure commands to the running monitor ${this.port.protocol}:${this.port.address}.`
547535
);
548-
return Status.OK;
536+
return;
549537
}
550538

551539
const coreClient = await this.coreClient;
@@ -560,7 +548,6 @@ export class MonitorService extends CoreClientAware implements Disposable {
560548
req.setInstance(instance);
561549
req.setPortConfiguration(diffConfig);
562550
this.duplex.write(req);
563-
return Status.OK;
564551
}
565552

566553
/**

‎i18n/en.json

+5
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@
328328
"tools": "Tools"
329329
},
330330
"monitor": {
331+
"alreadyConnectedError": "Could not connect to {0} {1} port. Already connected.",
332+
"connectionFailedError": "Could not connect to {0} {1} port{2}",
333+
"connectionTimeout": "Timeout. The IDE has not received the 'success' message from the monitor after successfully connecting to it.",
334+
"missingConfigurationError": "Could not connect to {0} {1} port. The monitor configuration is missing.",
335+
"notConnectedError": "Not connected to {0} {1} port.",
331336
"unableToCloseWebSocket": "Unable to close websocket",
332337
"unableToConnectToWebSocket": "Unable to connect to websocket"
333338
},

0 commit comments

Comments
 (0)
Please sign in to comment.