From 6f8c8671e3023eae3d7d54145341fc738ca6de0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Thu, 16 Sep 2021 16:19:33 +0200 Subject: [PATCH] [ivette] Automatically selects the 'main' function. - when the AST is recomputed; - when the current project changes and the selection is empty. --- .../frama-c/api/generated/kernel/ast/index.ts | 5 +++++ ivette/src/frama-c/kernel/ASTview.tsx | 14 ++++++++++---- ivette/src/frama-c/menu.ts | 3 --- ivette/src/frama-c/states.ts | 17 +++++++++++++++++ src/plugins/server/kernel_ast.ml | 5 +++++ 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/ivette/src/frama-c/api/generated/kernel/ast/index.ts b/ivette/src/frama-c/api/generated/kernel/ast/index.ts index f72426c5a32..f5b3bee763a 100644 --- a/ivette/src/frama-c/api/generated/kernel/ast/index.ts +++ b/ivette/src/frama-c/api/generated/kernel/ast/index.ts @@ -71,6 +71,11 @@ const compute_internal: Server.ExecRequest<null,null> = { /** Ensures that AST is computed */ export const compute: Server.ExecRequest<null,null>= compute_internal; +/** Emitted when the AST has been computed */ +export const computed: Server.Signal = { + name: 'kernel.ast.computed', +}; + /** Marker kind */ export enum markerKind { /** Expression */ diff --git a/ivette/src/frama-c/kernel/ASTview.tsx b/ivette/src/frama-c/kernel/ASTview.tsx index 2f2d9bbae19..d127bba677e 100644 --- a/ivette/src/frama-c/kernel/ASTview.tsx +++ b/ivette/src/frama-c/kernel/ASTview.tsx @@ -201,14 +201,20 @@ export default function ASTview() { return () => { buffer.off('change', setBullets); }; }, [buffer, setBullets]); + async function reload() { + printed.current = theFunction; + loadAST(buffer, theFunction, theMarker); + } + // Hook: async loading React.useEffect(() => { - if (printed.current !== theFunction) { - printed.current = theFunction; - loadAST(buffer, theFunction, theMarker); - } + if (printed.current !== theFunction) + reload(); }); + // Also reload the buffer when the AST is recomputed. + Server.onSignal(Ast.computed, reload); + React.useEffect(() => { const decorator = (marker: string) => { if (multipleSelections?.some((location) => location?.marker === marker)) diff --git a/ivette/src/frama-c/menu.ts b/ivette/src/frama-c/menu.ts index 0fa35529440..66fc3b9a8b5 100644 --- a/ivette/src/frama-c/menu.ts +++ b/ivette/src/frama-c/menu.ts @@ -28,7 +28,6 @@ import * as Dome from 'dome'; import * as Dialogs from 'dome/dialogs'; import * as Server from 'frama-c/server'; import * as Ast from 'frama-c/api/kernel/ast'; -import * as States from 'frama-c/states'; const cFilter = { name: 'C source files', @@ -46,8 +45,6 @@ async function setFiles(): Promise<void> { }); await Server.send(Ast.setFiles, files); await Server.send(Ast.compute, { }); - const main = await Server.send(Ast.getMainFunction, { }); - States.setSelection({ fct: main }); return; } diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts index 876761db7b4..39786ef5aad 100644 --- a/ivette/src/frama-c/states.ts +++ b/ivette/src/frama-c/states.ts @@ -772,4 +772,21 @@ export function useSelection(): [Selection, (a: SelectionActions) => void] { return [current, (action) => setCurrent(reducer(current, action))]; } +/* Select the main function when the AST is recomputed, or when the current + project changes and the selection is still empty. */ +async function selectMainFunction() { + const main = await Server.send(Ast.getMainFunction, { }); + const selection = { + ...emptySelection, + current: { fct: main }, + }; + GlobalSelection.setValue(selection); +} +Server.onSignal(Ast.computed, selectMainFunction); +PROJECT.on(async () => { + const selection = GlobalSelection.getValue(); + if (selection === emptySelection) + selectMainFunction(); +}); + // -------------------------------------------------------------------------- diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml index 10c62c2128a..6a83fdf6c71 100644 --- a/src/plugins/server/kernel_ast.ml +++ b/src/plugins/server/kernel_ast.ml @@ -37,6 +37,11 @@ let () = Request.register ~package ~descr:(Md.plain "Ensures that AST is computed") ~input:(module Junit) ~output:(module Junit) Ast.compute +let computed_signal = Request.signal ~package ~name:"computed" + ~descr:(Md.plain "Emitted when the AST has been computed") + +let () = Ast.apply_after_computed (fun _ -> Request.emit computed_signal) + let ast_update_hook f = Ast.add_hook_on_update f; Ast.apply_after_computed (fun _ -> f ()) -- GitLab