diff --git a/ivette/src/frama-c/server.ts b/ivette/src/frama-c/server.ts index 4744cd01e28e7054e8e7daff6b553518ce125a31..163b7a6b572f3a472d037ed324f7e12c3f9fc37f 100644 --- a/ivette/src/frama-c/server.ts +++ b/ivette/src/frama-c/server.ts @@ -862,24 +862,25 @@ function _poll() { } } -function _send() { +async function _send() { // when busy, will be eventually re-triggered if (!zmqIsBusy) { const cmds = queueCmd; if (!cmds.length && _waiting()) cmds.push('POLL'); if (cmds.length) { + zmqIsBusy = true; const ids = queueId; queueCmd = []; queueId = []; - if (zmqSocket) { - zmqIsBusy = true; - zmqSocket.send(cmds) - .then(() => zmqSocket?.receive().then((resp: any) => _receive(resp))) - .catch(() => _cancel(ids)) - .finally(() => { zmqIsBusy = false; Dome.emit(STATUS); }); - } else { + try { + await zmqSocket?.send(cmds); + const resp = await zmqSocket?.receive(); + _receive(resp); + } catch (error) { + PP.error(`Error in send/receive on ZMQ socket. ${error.toString()}`); _cancel(ids); } + zmqIsBusy = false; } else { // No pending command nor pending response rqCount = 0; diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts index 13298285713cc3e76c857ee1175240c931a8b06a..1cf0620f980274132c3780c32c0664674269caaa 100644 --- a/ivette/src/frama-c/states.ts +++ b/ivette/src/frama-c/states.ts @@ -33,23 +33,35 @@ export const PROJECT = 'frama-c.project'; */ export const STATE = 'frama-c.state.'; +// -------------------------------------------------------------------------- +// --- Pretty Printing (Browser Console) +// -------------------------------------------------------------------------- + +class PP { + static warning(t: string) { console.warn(`[Frama-C States] ${t}.`); } + static error(t: string) { console.error(`[Frama-C States] ${t}.`); } +} + // -------------------------------------------------------------------------- // --- Synchronized Current Project // -------------------------------------------------------------------------- -let currentProject = '<None>'; +let currentProject: string | null = null; let states: any = {}; const stateDefaults: any = {}; Server.onReady(async () => { - const sr: Server.Request = { - endpoint: 'kernel.project.getCurrent', - params: {}, - }; - const current: { id: string } = await Server.GET(sr); - currentProject = current.id; - Dome.emit(PROJECT); - return; + try { + const sr: Server.Request = { + endpoint: 'kernel.project.getCurrent', + params: {}, + }; + const current: { id: string } = await Server.GET(sr); + currentProject = current.id; + Dome.emit(PROJECT); + } catch (error) { + PP.error(`Fail to retrieve the current project. ${error.toString()}`); + } }); Server.onShutdown(() => { @@ -80,14 +92,14 @@ export function useProject() { */ export async function setProject(project: string) { if (Server.isRunning()) { - const sr: Server.Request = { - endpoint: 'kernel.project.setCurrent', - params: project, - }; - await Server.SET(sr); - currentProject = project; - Dome.emit(PROJECT); - return; + try { + const sr = { endpoint: 'kernel.project.setCurrent', params: project }; + await Server.SET(sr); + currentProject = project; + Dome.emit(PROJECT); + } catch (error) { + PP.error(`Fail to set the current project. ${error.toString()}`); + } } } @@ -95,12 +107,12 @@ export async function setProject(project: string) { // --- Projectified State // -------------------------------------------------------------------------- -function getValue(id: string, project: string) { +function getValue(id: string, project: string | null) { if (!project) return undefined; return _.get(states, [project, id], stateDefaults[id]); } -function setValue(id: string, project: string, value: any) { +function setValue(id: string, project: string | null, value: any) { if (!project) return; _.set(states, [project, id], value); Dome.emit(STATE + id, value); @@ -171,9 +183,8 @@ export function useRequest(rq: string, params: any, options: any = {}) { try { const r = await Server.GET({ endpoint: rq, params }); setResponse(r); - } catch (errmsg) { - if (Dome.DEVEL) - console.warn(`[Server] use request '${rq}':`, errmsg); + } catch (error) { + PP.error(`Fail in useRequest '${rq}'. ${error.toString()}`); const err = options.error; if (err !== undefined) setResponse(err); } @@ -283,19 +294,29 @@ class SyncState { } async setValue(v: any) { - this.insync = true; - this.value = v; - const sr: Server.Request = { endpoint: this.setRq, params: v }; - await Server.SET(sr); - Dome.emit(this.UPDATE); + try { + this.insync = true; + this.value = v; + const sr: Server.Request = { endpoint: this.setRq, params: v }; + await Server.SET(sr); + Dome.emit(this.UPDATE); + } catch (error) { + PP.error( + `Fail to set value of syncState '${this.id}'. ${error.toString()}`, + ); + } } async update() { - this.insync = true; - const sr: Server.Request = { endpoint: this.getRq, params: {} }; - const v = await Server.GET(sr); - this.value = v; - Dome.emit(this.UPDATE); + try { + this.insync = true; + const sr: Server.Request = { endpoint: this.getRq, params: {} }; + const v = await Server.GET(sr); + this.value = v; + Dome.emit(this.UPDATE); + } catch (error) { + PP.error(`Fail to update syncState '${this.id}'. ${error.toString()}`); + } } } @@ -359,6 +380,7 @@ export function useSyncValue(id: string) { // one per project class SyncArray { + id: string; UPDATE: string; signal: string; fetchRq: string; @@ -367,6 +389,7 @@ class SyncArray { insync: boolean; constructor(id: string) { + this.id = id; this.UPDATE = STATE + id; this.signal = `${id}.sig`; this.fetchRq = `${id}.fetch`; @@ -387,37 +410,49 @@ class SyncArray { } async fetch() { - this.insync = true; - const sr: Server.Request = { 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(); + try { + this.insync = true; + const sr: Server.Request = { 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(); + } + } catch (error) { + PP.error( + `Fail to retrieve the value of syncArray '${this.id}. ` + + `${error.toString()}`, + ); } - return; } async reload() { - const sr: Server.Request = { endpoint: this.reloadRq, params: {} }; - await Server.SET(sr); - this.index = {}; - this.insync = false; - Dome.emit(this.UPDATE); + try { + const sr: Server.Request = { endpoint: this.reloadRq, params: {} }; + await Server.SET(sr); + this.index = {}; + this.insync = false; + Dome.emit(this.UPDATE); + } catch (error) { + PP.error( + `Fail to set reload of syncArray '${this.id}. ${error.toString()}`, + ); + } } } diff --git a/ivette/src/renderer/ASTview.tsx b/ivette/src/renderer/ASTview.tsx index cc6bfd19604fddda5a2e51e81547ebca89db3be0..2642ffcf8a741e99b7711d62a3d6d83d5899193d 100644 --- a/ivette/src/renderer/ASTview.tsx +++ b/ivette/src/renderer/ASTview.tsx @@ -23,6 +23,15 @@ const THEMES = [ { id: 'solarized dark', label: 'Solarized Dark' }, ]; +// -------------------------------------------------------------------------- +// --- Pretty Printing (Browser Console) +// -------------------------------------------------------------------------- + +class PP { + static warning(t: string) { console.warn(`[AST View] ${t}.`); } + static error(t: string) { console.error(`[AST View] ${t}.`); } +} + // -------------------------------------------------------------------------- // --- Rich Text Printer // -------------------------------------------------------------------------- @@ -47,19 +56,25 @@ async function loadAST(buffer: any, theFunction?: string, theMarker?: string) { if (theFunction) { buffer.log('// Loading', theFunction, '…'); (async () => { - const data = await Server.GET({ - endpoint: 'kernel.ast.printFunction', - params: theFunction, - }); - buffer.operation(() => { - buffer.clear(); - if (!data) - buffer.log('// No code for function ', theFunction); - printAST(buffer, data); - if (theMarker) - buffer.scroll(theMarker, undefined); - }); - return; + try { + const data = await Server.GET({ + endpoint: 'kernel.ast.printFunction', + params: theFunction, + }); + buffer.operation(() => { + buffer.clear(); + if (!data) + buffer.log('// No code for function ', theFunction); + printAST(buffer, data); + if (theMarker) + buffer.scroll(theMarker, undefined); + }); + } catch (error) { + PP.error( + `Fail to retrieve the AST of function ${theFunction}, ` + + `on marker ${theMarker}`, + ); + } })(); } }