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 f72426c5a3222d23e3d51df6f2ef0807fd723987..f5b3bee763af939ac7897df4dcfbe9ee6e75e19e 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 2f2d9bbae19f40609fe3f95f0526a67ca9ada098..d127bba677eb8472f55e5ea035994f2b5e0f89fc 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 0fa355294406c4d3ae5a615dc883c9f37653dcfd..66fc3b9a8b54b21d42554817124ab7a1ef121990 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 876761db7b47e3b4381140df8f8739838bd794b0..39786ef5aadea06bc25b51532aa4b0c9e0fa72c9 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 10c62c2128a474836bcf83a0c95d42cdf6754fb5..6a83fdf6c71401cc0a5d945c300c12071d07125a 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 ())