From d8354963e2cd306ab0c5ab7142619783921eec2d Mon Sep 17 00:00:00 2001 From: Michele Alberti <michele.alberti@cea.fr> Date: Mon, 27 Apr 2020 11:19:19 +0200 Subject: [PATCH] [frama-c/server] Rework requests. --- ivette/src/frama-c/server.ts | 49 +++++++++++-- ivette/src/frama-c/states.ts | 121 +++++++++++++++++++------------- ivette/src/renderer/ASTview.tsx | 27 ++++--- 3 files changed, 133 insertions(+), 64 deletions(-) diff --git a/ivette/src/frama-c/server.ts b/ivette/src/frama-c/server.ts index 84bf3f2d20d..65d770957fd 100644 --- a/ivette/src/frama-c/server.ts +++ b/ivette/src/frama-c/server.ts @@ -651,14 +651,49 @@ Dome.on(SHUTDOWN, () => { * - `SET` Used to write data into the server * - `EXEC` Used to make the server execute a task */ -export enum RqKind { +enum RqKind { GET = 'GET', SET = 'SET', EXEC = 'EXEC' } /** - * @summary Send request to the server. + * @typedef ServerRequest + * @summary Server request. + * @param {string} endpoint - the request identifier + * @param {any} params - the request parameters + */ +export interface ServerRequest { + endpoint: string; + params: any; +} + +/** + * @summary Get data from the server. + * @param sr - the server request description. + */ +async function GET(sr: ServerRequest) { + return _create(RqKind.GET, sr.endpoint, sr.params); +} + +/** + * @summary Set data into the server. + * @param sr - the server request description. + */ +async function SET(sr: ServerRequest) { + return _create(RqKind.SET, sr.endpoint, sr.params); +} + +/** + * @summary Make the server execute a task. + * @param sr - the server request description. + */ +async function EXEC(sr: ServerRequest) { + return _create(RqKind.EXEC, sr.endpoint, sr.params); +} + +/** + * @summary Create request to send to the server. * @param {RqKind} kind - the request kind * @param {string} rq - the request identifier * @param {object} params - request parameters @@ -667,9 +702,9 @@ export enum RqKind { * You may _kill_ the request before its normal termination by * invoking `kill()` on the returned promised. */ -function send(kind: RqKind, rq: string, params: any) { - if (!isRunning()) return Promise.reject('Server not running'); - if (!rq) return Promise.reject('Undefined request'); +function _create(kind: RqKind, rq: string, params: any) { + if (!isRunning()) return Promise.reject(new Error('Server not running')); + if (!rq) return Promise.reject(new Error('Undefined request')); const rid = `RQ.${rqid}`; rqid += 1; const data = JSON.stringify(params); @@ -830,7 +865,9 @@ export default { kill, restart, clear, - send, + GET, + SET, + EXEC, onReady, onShutdown, onActivity, diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts index 9e63255e1b4..9c757e7fd7d 100644 --- a/ivette/src/frama-c/states.ts +++ b/ivette/src/frama-c/states.ts @@ -11,7 +11,7 @@ import _ from 'lodash'; import React from 'react'; import Dome from 'dome'; -import Server, { RqKind } from './server'; +import Server, { ServerRequest } from './server'; /** * @event @@ -40,12 +40,15 @@ let currentProject = '<None>'; let states: any = {}; const stateDefaults: any = {}; -Server.onReady(() => { - Server.send(RqKind.GET, 'kernel.project.getCurrent', null) - .then((current: { id: string }) => { - currentProject = current.id; - Dome.emit(PROJECT); - }); +Server.onReady(async () => { + const sr: ServerRequest = { + endpoint: 'kernel.project.getCurrent', + params: {}, + }; + const current: { id: string } = await Server.GET(sr); + currentProject = current.id; + Dome.emit(PROJECT); + return; }); Server.onShutdown(() => { @@ -74,11 +77,16 @@ export function useProject() { * Make all states switching to their projectified value. * Emits `PROJECT`. */ -export function setProject(project: string) { +export async function setProject(project: string) { if (Server.isRunning()) { - Server.send(RqKind.SET, 'kernel.project.setCurrent', project); + const sr: ServerRequest = { + endpoint: 'kernel.project.setCurrent', + params: project, + }; + await Server.SET(sr); currentProject = project; Dome.emit(PROJECT); + return; } } @@ -153,22 +161,36 @@ export function useState(id: string) { export function useRequest(rq: string, params: any, options: any = {}) { const project = useProject(); const [value, setValue] = React.useState(options.offline); + React.useEffect(() => { if (project) { const pending = options.prending; - if (pending !== null) setValue(pending); - Server.send(RqKind.GET, rq, params) - .then(setValue) - .catch((err: string) => { - if (Dome.DEVEL) console.warn(`[Server] use request '${rq}':`, err); + if (pending !== null) { + setValue(pending); + } + (async () => { + try { + const sr: ServerRequest = { endpoint: rq, params }; + const v = await Server.GET(sr); + setValue(v); + } catch (err) { + if (Dome.DEVEL) { + console.warn(`[Server] use request '${rq}':`, err); + } const { error } = options; - if (error !== null) setValue(error); - }); + if (error !== null) { + setValue(error); + } + } + })(); } else { const v = options.offline; - if (value !== v) setValue(v); + if (value !== v) { + setValue(v); + } } }, [project, rq, JSON.stringify(params)]); + return value; } @@ -257,19 +279,20 @@ class SyncState { return this.value; } - setValue(v: any) { + async setValue(v: any) { this.insync = true; this.value = v; - Server.send(RqKind.SET, this.setRq, v); + const sr: ServerRequest = { endpoint: this.setRq, params: v }; + await Server.SET(sr); Dome.emit(this.UPDATE); } - update() { + async update() { this.insync = true; - Server.send(RqKind.GET, this.getRq, null).then((v: any) => { - this.value = v; - Dome.emit(this.UPDATE); - }); + const sr: ServerRequest = { endpoint: this.getRq, params: {} }; + const v = await Server.GET(sr); + this.value = v; + Dome.emit(this.UPDATE); } } @@ -360,33 +383,35 @@ class SyncArray { return _.find(this.index, () => true) !== undefined; } - fetch() { + async fetch() { this.insync = true; - Server.send(RqKind.GET, this.fetchRq, 50) - .then(({ reload = false, removed = [], updated = [], pending = 0 }) => { - let reloaded = false; - if (reload) { - reloaded = this.isEmpty(); - this.index = {}; - } - removed.forEach((key) => { - delete this.index[key]; - }); - updated.forEach((item: any) => { - this.index[item.key] = item; - }); - if (reloaded || removed.length || updated.length) { - this.index = { ...this.index }; - Dome.emit(this.UPDATE); - } - if (pending > 0) { - this.fetch(); - } - }); + const sr: ServerRequest = { endpoint: this.fetchRq, params: 50 }; + const data = await Server.GET(sr); + const { reload = false, removed = [], updated = [], pending = 0 } = data; + let reloaded = false; + if (reload) { + reloaded = this.isEmpty(); + this.index = {}; + } + removed.forEach((key: any) => { + delete this.index[key]; + }); + updated.forEach((item: any) => { + this.index[item.key] = item; + }); + if (reloaded || removed.length || updated.length) { + this.index = { ...this.index }; + Dome.emit(this.UPDATE); + } + if (pending > 0) { + this.fetch(); + } + return; } - reload() { - Server.send(RqKind.SET, this.reloadRq, null); + async reload() { + const sr: ServerRequest = { endpoint: this.reloadRq, params: {} }; + await Server.SET(sr); this.index = {}; this.insync = false; Dome.emit(this.UPDATE); diff --git a/ivette/src/renderer/ASTview.tsx b/ivette/src/renderer/ASTview.tsx index 1fd9d1befb4..6cf68490ac3 100644 --- a/ivette/src/renderer/ASTview.tsx +++ b/ivette/src/renderer/ASTview.tsx @@ -3,7 +3,7 @@ // -------------------------------------------------------------------------- import React from 'react'; -import Server, { RqKind } from 'frama-c/server'; +import Server, { ServerRequest } from 'frama-c/server'; import States from 'frama-c/states'; import { Vfill } from 'dome/layout/boxes'; @@ -49,15 +49,22 @@ const ASTview = () => { buffer.clear(); if (theFunction) { buffer.log('// Loading', theFunction, '…'); - Server.send(RqKind.GET, 'kernel.ast.printFunction', theFunction) - .then((data: string) => { - buffer.clear(); - if (!data) { - buffer.log('// No code for function ', theFunction); - } - print(buffer, data); - if (theMarker) buffer.scroll(theMarker, undefined); - }); + (async () => { + const sr: ServerRequest = { + endpoint: 'kernel.ast.printFunction', + params: theFunction, + }; + const data = await Server.GET(sr); + buffer.clear(); + if (!data) { + buffer.log('// No code for function ', theFunction); + } + print(buffer, data); + if (theMarker) { + buffer.scroll(theMarker, undefined); + } + return; + })(); } }, [theFunction]); -- GitLab