Skip to content

Commit cc79d53

Browse files
author
Christian Weichel
committed
First stop towards compile/verify
1 parent c48d80b commit cc79d53

12 files changed

+145
-31
lines changed

arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ArduinoCommands } from './arduino-commands';
1111
import { ConnectedBoards } from './components/connected-boards';
1212
import { CoreService } from '../common/protocol/core-service';
1313
import { WorkspaceServiceExt } from './workspace-service-ext';
14+
import { ToolOutputServiceClient } from '../common/protocol/tool-output-service';
1415

1516

1617
@injectable()
@@ -28,6 +29,9 @@ export class ArduinoFrontendContribution extends DefaultFrontendApplicationContr
2829
@inject(WorkspaceServiceExt)
2930
protected readonly workspaceServiceExt: WorkspaceServiceExt;
3031

32+
@inject(ToolOutputServiceClient)
33+
protected readonly toolOutputServiceClient: ToolOutputServiceClient;
34+
3135
@postConstruct()
3236
protected async init(): Promise<void> {
3337
// This is a hack. Otherwise, the backend services won't bind.

arduino-ide-extension/src/browser/arduino-frontend-module.ts

+11
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ import { BoardsListWidget } from './boards/boards-list-widget';
1717
import { BoardsListWidgetFrontendContribution } from './boards/boards-widget-frontend-contribution';
1818
import { WorkspaceServiceExt, WorkspaceServiceExtPath } from './workspace-service-ext';
1919
import { WorkspaceServiceExtImpl } from './workspace-service-ext-impl';
20+
import { ToolOutputServiceClient } from '../common/protocol/tool-output-service';
2021

2122
import '../../src/browser/style/index.css';
23+
import { ToolOutputService } from '../common/protocol/tool-output-service';
24+
import { ToolOutputServiceClientImpl } from './tool-output/client-service-impl';
2225

2326
export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
2427
// Commands and toolbar items
@@ -58,6 +61,14 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
5861
.toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, CoreServicePath))
5962
.inSingletonScope();
6063

64+
// Tool output service client
65+
bind(ToolOutputServiceClientImpl).toSelf().inSingletonScope();
66+
bind(ToolOutputServiceClient).toDynamicValue(context => {
67+
const client = context.container.get(ToolOutputServiceClientImpl);
68+
WebSocketConnectionProvider.createProxy(context.container, ToolOutputService.SERVICE_PATH, client);
69+
return client;
70+
}).inSingletonScope();
71+
6172
// The workspace service extension
6273
bind(WorkspaceServiceExt).to(WorkspaceServiceExtImpl).inSingletonScope().onActivation(({ container }, workspaceServiceExt) => {
6374
WebSocketConnectionProvider.createProxy(container, WorkspaceServiceExtPath, workspaceServiceExt);

arduino-ide-extension/src/browser/style/list-widget.css

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
padding: 4px;
5353
font-size: 10px;
5454
font-weight: bold;
55+
max-height: calc(1em + 4px);
5556
}
5657

5758
.component-list-item .footer {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ToolOutputServiceClient } from "../../common/protocol/tool-output-service";
2+
import { injectable, inject } from "inversify";
3+
import { OutputChannelManager } from "@theia/output/lib/common/output-channel";
4+
5+
@injectable()
6+
export class ToolOutputServiceClientImpl implements ToolOutputServiceClient {
7+
8+
@inject(OutputChannelManager)
9+
protected readonly outputChannelManager: OutputChannelManager;
10+
11+
onNewOutput(tool: string, chunk: string): void {
12+
const channel = this.outputChannelManager.getChannel(`Arduino: ${tool}`);
13+
channel.append(chunk);
14+
}
15+
16+
}

arduino-ide-extension/src/common/protocol/core-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export const CoreServicePath = '/services/core-service';
22
export const CoreService = Symbol('CoreService');
33
export interface CoreService {
4-
compile(options: CoreService.Compile.Options): Promise<string>;
4+
compile(options: CoreService.Compile.Options): Promise<void>;
55
upload(): Promise<void>;
66
}
77

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { JsonRpcServer } from "@theia/core";
2+
3+
export const ToolOutputServiceServer = Symbol("ToolOutputServiceServer");
4+
export interface ToolOutputServiceServer extends JsonRpcServer<ToolOutputServiceClient> {
5+
publishNewOutput(tool: string, chunk: string): void;
6+
disposeClient(client: ToolOutputServiceClient): void;
7+
}
8+
9+
export const ToolOutputServiceClient = Symbol("ToolOutputServiceClient");
10+
export interface ToolOutputServiceClient {
11+
onNewOutput(tool: string, chunk: string): void;
12+
}
13+
14+
export namespace ToolOutputService {
15+
export const SERVICE_PATH = "/tool-output-service";
16+
}

arduino-ide-extension/src/node/arduino-backend-module.ts

+14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { ConnectionContainerModule } from '@theia/core/lib/node/messaging/connec
1212
import { WorkspaceServiceExtPath, WorkspaceServiceExt } from '../browser/workspace-service-ext';
1313
import { CoreClientProviderImpl } from './core-client-provider-impl';
1414
import { CoreClientProviderPath, CoreClientProvider } from './core-client-provider';
15+
import { ToolOutputService, ToolOutputServiceClient, ToolOutputServiceServer } from '../common/protocol/tool-output-service';
16+
import { ConnectionHandler, JsonRpcConnectionHandler } from '@theia/core';
17+
import { ToolOutputServiceServerImpl } from './tool-output-service-impl';
1518

1619
export default new ContainerModule((bind, unbind, isBound, rebind) => {
1720
bind(ArduinoDaemon).toSelf().inSingletonScope();
@@ -51,6 +54,17 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
5154
});
5255
bind(ConnectionContainerModule).toConstantValue(connectionConnectionModule);
5356

57+
// Tool output service -> feedback from the daemon, compile and flash
58+
bind(ToolOutputServiceServer).to(ToolOutputServiceServerImpl).inSingletonScope();
59+
bind(ConnectionHandler).toDynamicValue(context =>
60+
new JsonRpcConnectionHandler<ToolOutputServiceClient>(ToolOutputService.SERVICE_PATH, client => {
61+
const server = context.container.get<ToolOutputServiceServer>(ToolOutputServiceServer);
62+
server.setClient(client);
63+
client.onDidCloseConnection(() => server.disposeClient(client));
64+
return server;
65+
})
66+
).inSingletonScope();
67+
5468
// Bind the workspace service extension to the backend per Theia connection.
5569
// So that we can access the workspace roots of the frontend.
5670
const workspaceServiceExtConnectionModule = ConnectionContainerModule.create(({ bindFrontendService }) => {

arduino-ide-extension/src/node/arduino-daemon.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ILogger } from '@theia/core/lib/common/logger';
66
import { BackendApplicationContribution } from '@theia/core/lib/node';
77
import { Deferred } from '@theia/core/lib/common/promise-util';
88
import { DaemonLog } from './daemon-log';
9+
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
910

1011
const EXECUTABLE_PATH = resolve(join(__dirname, '..', '..', 'build', `arduino-cli.${os.platform()}`))
1112

@@ -16,6 +17,9 @@ export class ArduinoDaemon implements BackendApplicationContribution {
1617
@named('daemon')
1718
protected readonly logger: ILogger
1819

20+
@inject(ToolOutputServiceServer)
21+
protected readonly toolOutputService: ToolOutputServiceServer;
22+
1923
protected isReady = new Deferred<boolean>();
2024

2125
async onStart() {
@@ -28,10 +32,16 @@ export class ArduinoDaemon implements BackendApplicationContribution {
2832
console.log(stdout);
2933
});
3034
if (daemon.stdout) {
31-
daemon.stdout.on('data', data => DaemonLog.log(this.logger, data.toString()));
35+
daemon.stdout.on('data', data => {
36+
this.toolOutputService.publishNewOutput("daeomn", data.toString());
37+
DaemonLog.log(this.logger, data.toString());
38+
});
3239
}
3340
if (daemon.stderr) {
34-
daemon.stderr.on('data', data => DaemonLog.log(this.logger, data.toString()));
41+
daemon.stderr.on('data', data => {
42+
this.toolOutputService.publishNewOutput("daeomn error", data.toString());
43+
DaemonLog.log(this.logger, data.toString());
44+
});
3545
}
3646
if (daemon.stderr) {
3747
daemon.on('exit', (code, signal) => DaemonLog.log(this.logger, `Daemon exited with code: ${code}. Signal was: ${signal}.`));

arduino-ide-extension/src/node/boards-service-impl.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ export class BoardsServiceImpl implements BoardsService {
6666
const [ platform, boardName ] = board.id.split(":");
6767

6868
const req = new PlatformInstallReq();
69+
req.setInstance(instance);
6970
req.setArchitecture(boardName);
7071
req.setPlatformPackage(platform);
7172
req.setVersion(board.availableVersions[0]);
72-
req.setInstance(instance);
7373

7474
console.info("Starting board installation", board);
7575
const resp = client.platformInstall(req);

arduino-ide-extension/src/node/core-client-provider-impl.ts

+18
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@ export class CoreClientProviderImpl implements CoreClientProvider {
8484
updateResp.on('end', resolve);
8585
});
8686
}
87+
88+
// {
89+
// const installBuiltinPkgReq = new PlatformInstallReq();
90+
// installBuiltinPkgReq.setInstance(instance);
91+
// installBuiltinPkgReq.setPlatformPackage("builtin");
92+
// const resp = client.platformInstall(installBuiltinPkgReq);
93+
// resp.on('data', (r: PlatformInstallResp) => {
94+
// const prog = r.getProgress();
95+
// if (prog) {
96+
// console.info(`downloading ${prog.getFile()}: ${prog.getCompleted()}%`)
97+
// }
98+
// });
99+
// await new Promise<void>((resolve, reject) => {
100+
// resp.on('end', resolve);
101+
// resp.on('error', reject);
102+
// });
103+
// }
104+
87105
// TODO: revisit this!!!
88106
// `updateResp.on('data'` is called only when running, for instance, `compile`. It does not run eagerly.
89107
// await new Promise<void>((resolve, reject) => {

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

+23-27
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { inject, injectable } from 'inversify';
22
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
33
import { CoreService } from '../common/protocol/core-service';
4-
import { CompileReq } from './cli-protocol/compile_pb';
4+
import { CompileReq, CompileResp } from './cli-protocol/compile_pb';
55
import { BoardsService } from '../common/protocol/boards-service';
66
import { CoreClientProvider } from './core-client-provider';
7-
import { PlatformInstallReq } from './cli-protocol/core_pb';
8-
import { LibraryInstallReq } from './cli-protocol/lib_pb';
7+
import * as path from 'path';
8+
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
99

1010
@injectable()
1111
export class CoreServiceImpl implements CoreService {
@@ -19,13 +19,17 @@ export class CoreServiceImpl implements CoreService {
1919
@inject(BoardsService)
2020
protected readonly boardsService: BoardsService;
2121

22-
async compile(options: CoreService.Compile.Options): Promise<string> {
22+
@inject(ToolOutputServiceServer)
23+
protected readonly toolOutputService: ToolOutputServiceServer;
24+
25+
async compile(options: CoreService.Compile.Options): Promise<void> {
2326
console.log('compile', options);
2427
const { uri } = options;
25-
const sketchpath = await this.fileSystem.getFsPath(options.uri);
26-
if (!sketchpath) {
28+
const sketchFilePath = await this.fileSystem.getFsPath(options.uri);
29+
if (!sketchFilePath) {
2730
throw new Error(`Cannot resolve filesystem path for URI: ${uri}.`);
2831
}
32+
const sketchpath = path.dirname(sketchFilePath);
2933

3034
const { client, instance } = await this.coreClientProvider.getClient(uri);
3135
// const boards = await this.boardsService.connectedBoards();
@@ -34,38 +38,30 @@ export class CoreServiceImpl implements CoreService {
3438
// }
3539
// https://github.com/cmaglie/arduino-cli/blob/bd5e78701e7546787649d3cca6b21c5d22d0e438/cli/compile/compile.go#L78-L88
3640

37-
const installLibReq = new LibraryInstallReq();
38-
installLibReq.setInstance(instance);
39-
installLibReq.setName('arduino:samd');
40-
const installResp = client.libraryInstall(installLibReq);
41-
const xxx = await new Promise<string>((resolve, reject) => {
42-
const chunks: Buffer[] = [];
43-
installResp.on('data', (chunk: Buffer) => chunks.push(chunk));
44-
installResp.on('error', error => reject(error));
45-
installResp.on('end', () => resolve(Buffer.concat(chunks).toString('utf8').trim()))
46-
});
47-
console.log('xxx', xxx);
48-
4941
const compilerReq = new CompileReq();
5042
compilerReq.setInstance(instance);
5143
compilerReq.setSketchpath(sketchpath);
52-
compilerReq.setFqbn('arduino:samd'/*boards.current.name*/);
44+
compilerReq.setFqbn('arduino:avr:uno'/*boards.current.name*/);
5345
// request.setShowproperties(false);
54-
// request.setPreprocess(false);
46+
compilerReq.setPreprocess(false);
5547
// request.setBuildcachepath('');
56-
// request.setBuildpath('');
48+
// compilerReq.setBuildpath('/tmp/build');
49+
// compilerReq.setShowproperties(true);
5750
// request.setBuildpropertiesList([]);
5851
// request.setWarnings('none');
59-
// request.setVerbose(true);
60-
// request.setQuiet(false);
52+
compilerReq.setVerbose(true);
53+
compilerReq.setQuiet(false);
6154
// request.setVidpid('');
6255
// request.setExportfile('');
56+
6357
const result = client.compile(compilerReq);
64-
return new Promise<string>((resolve, reject) => {
65-
const chunks: Buffer[] = [];
66-
result.on('data', (chunk: Buffer) => chunks.push(chunk));
58+
return new Promise<void>((resolve, reject) => {
59+
result.on('data', (cr: CompileResp) => {
60+
this.toolOutputService.publishNewOutput("compile", new Buffer(cr.getOutStream_asU8()).toString());
61+
console.error(cr.getErrStream().toString());
62+
});
6763
result.on('error', error => reject(error));
68-
result.on('end', () => resolve(Buffer.concat(chunks).toString('utf8').trim()))
64+
result.on('end', () => resolve());
6965
});
7066
}
7167

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { injectable } from "inversify";
2+
import { ToolOutputServiceServer, ToolOutputServiceClient } from "../common/protocol/tool-output-service";
3+
4+
@injectable()
5+
export class ToolOutputServiceServerImpl implements ToolOutputServiceServer {
6+
protected clients: ToolOutputServiceClient[] = [];
7+
8+
publishNewOutput(tool: string, chunk: string): void {
9+
this.clients.forEach(c => c.onNewOutput(tool, chunk));
10+
}
11+
12+
setClient(client: ToolOutputServiceClient | undefined): void {
13+
if (!client) {
14+
return;
15+
}
16+
17+
this.clients.push(client);
18+
}
19+
20+
disposeClient(client: ToolOutputServiceClient): void {
21+
22+
}
23+
24+
dispose(): void {
25+
this.clients = [];
26+
}
27+
28+
}

0 commit comments

Comments
 (0)