From e665a74f97ddf496befb509442dd919d36d0998a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr>
Date: Fri, 17 Sep 2021 19:45:02 +0200
Subject: [PATCH] [server] In getMainFunction request, catches exception
 No_such_entry_point.

In ivette, ensures that the reset of the selected locations (and the call to the
'getMainFunction' request) is only done after the AST has been computed.
---
 ivette/src/frama-c/api/generated/kernel/ast/index.ts | 12 ++++++++++--
 ivette/src/frama-c/menu.ts                           |  5 +++--
 ivette/src/frama-c/states.ts                         |  9 +++------
 src/plugins/server/kernel_ast.ml                     |  7 +++++--
 4 files changed, 21 insertions(+), 12 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 fa299dac4c2..fd188273e4c 100644
--- a/ivette/src/frama-c/api/generated/kernel/ast/index.ts
+++ b/ivette/src/frama-c/api/generated/kernel/ast/index.ts
@@ -289,14 +289,22 @@ export const byLocation: Compare.Order<location> =
     marker: byMarker,
   });
 
-const getMainFunction_internal: Server.GetRequest<null,Json.key<'#fct'>> = {
+const getMainFunction_internal: Server.GetRequest<
+  null,
+  Json.key<'#fct'> |
+  undefined
+  > = {
   kind: Server.RqKind.GET,
   name:   'kernel.ast.getMainFunction',
   input:  Json.jNull,
   output: Json.jKey<'#fct'>('#fct'),
 };
 /** Get the current 'main' function. */
-export const getMainFunction: Server.GetRequest<null,Json.key<'#fct'>>= getMainFunction_internal;
+export const getMainFunction: Server.GetRequest<
+  null,
+  Json.key<'#fct'> |
+  undefined
+  >= getMainFunction_internal;
 
 const getFunctions_internal: Server.GetRequest<null,Json.key<'#fct'>[]> = {
   kind: Server.RqKind.GET,
diff --git a/ivette/src/frama-c/menu.ts b/ivette/src/frama-c/menu.ts
index 3890a571f8b..66c5e17a070 100644
--- a/ivette/src/frama-c/menu.ts
+++ b/ivette/src/frama-c/menu.ts
@@ -41,11 +41,12 @@ const allFilter = {
   extensions: ['*'],
 };
 
-async function parseFiles(files: string[]) {
+async function parseFiles(files: string[]): Promise<void> {
   Status.setMessage({ text: 'Parsing source files…', kind: 'progress' });
   await Server.send(Ast.setFiles, files);
   await Server.send(Ast.compute, { });
   Status.setMessage({ text: 'Source files parsed.', kind: 'success' });
+  return;
 }
 
 async function setFiles(): Promise<void> {
@@ -54,7 +55,7 @@ async function setFiles(): Promise<void> {
     filters: [cFilter, allFilter],
   });
   if (files) {
-    parseFiles(files);
+    await parseFiles(files);
     States.resetSelection();
   }
   return;
diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts
index 7900638fce9..e688565299e 100644
--- a/ivette/src/frama-c/states.ts
+++ b/ivette/src/frama-c/states.ts
@@ -776,13 +776,10 @@ export function useSelection(): [Selection, (a: SelectionActions) => void] {
 export async function resetSelection() {
   GlobalSelection.setValue(emptySelection);
   const main = await Server.send(Ast.getMainFunction, { });
-  const selection = {
-    ...emptySelection,
-    current: { fct: main },
-  };
   // If the selection has already been modified, do not change it.
-  if (GlobalSelection.getValue() === emptySelection)
-    GlobalSelection.setValue(selection);
+  if (main && GlobalSelection.getValue() === emptySelection) {
+    GlobalSelection.setValue({ ...emptySelection, current: { fct: main } });
+  }
 }
 /* Select the main function when the current project changes and the selection
    is still empty (which happens at the start of the GUI). */
diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml
index 57794fc7dfb..c59c6950196 100644
--- a/src/plugins/server/kernel_ast.ml
+++ b/src/plugins/server/kernel_ast.ml
@@ -361,8 +361,11 @@ end
 let () = Request.register ~package
     ~kind:`GET ~name:"getMainFunction"
     ~descr:(Md.plain "Get the current 'main' function.")
-    ~input:(module Junit) ~output:(module Kf)
-    (fun () -> fst (Globals.entry_point ()))
+    ~input:(module Junit) ~output:(module Joption (Kf))
+    begin fun () ->
+      try Some (fst (Globals.entry_point ()))
+      with Globals.No_such_entry_point _ -> None
+    end
 
 let () = Request.register ~package
     ~kind:`GET ~name:"getFunctions"
-- 
GitLab