diff --git a/ivette/src/frama-c/kernel/ASTview.tsx b/ivette/src/frama-c/kernel/ASTview.tsx
index 1219c382ae20ac28352c9a2c108069584eb0985e..e1092fa2e44f75f97c4a0665bd2e5a9277209806 100644
--- a/ivette/src/frama-c/kernel/ASTview.tsx
+++ b/ivette/src/frama-c/kernel/ASTview.tsx
@@ -29,8 +29,6 @@ import * as Utils from 'dome/data/arrays';
 import * as States from 'frama-c/states';
 import * as Settings from 'dome/data/settings';
 import { IconButton } from 'dome/controls/buttons';
-import * as Studia from 'frama-c/plugins/studia';
-import * as Wp from 'frama-c/plugins/wp';
 import * as Ast from 'frama-c/kernel/api/ast';
 import { text } from 'frama-c/kernel/api/data';
 import * as Eva from 'frama-c/plugins/eva/api/general';
@@ -493,6 +491,15 @@ function createPropertiesGutter(): Editor.Extension {
 //  Context menu
 // -----------------------------------------------------------------------------
 
+type MarkerMenuExtender =
+  (items: Dome.PopupMenuItem[], attr: Ast.markerAttributesData) => void;
+
+const MarkerMenuExtenders : MarkerMenuExtender[] = [];
+
+export function registerMarkerMenuExtender(e : MarkerMenuExtender) : void {
+  MarkerMenuExtenders.push(e);
+}
+
 // This field contains all the current function's callers, as inferred by Eva.
 const Callers = Editor.createField<Eva.CallSite[]>([]);
 
@@ -546,8 +553,7 @@ function createContextMenuHandler(): Editor.Extension {
           items.push({ label, onClick });
         });
       }
-      Studia.buildMenu(items, attributes);
-      Wp.buildMenu(items, attributes);
+      MarkerMenuExtenders.forEach((ext) => ext(items, attributes));
       items.push({
         label: 'Copy to clipboard',
         onClick: () => {
diff --git a/ivette/src/frama-c/plugins/studia/index.ts b/ivette/src/frama-c/plugins/studia/index.ts
index 7349dc397678113d5d509b60cb70af2e4aefb7ca..817a17796110d68722a2a0bc87e2d7a4208bfc41 100644
--- a/ivette/src/frama-c/plugins/studia/index.ts
+++ b/ivette/src/frama-c/plugins/studia/index.ts
@@ -26,6 +26,7 @@ import * as States from 'frama-c/states';
 import * as Server from 'frama-c/server';
 import * as Status from 'frama-c/kernel/Status';
 import * as Ast from 'frama-c/kernel/api/ast';
+import * as ASTview from 'frama-c/kernel/ASTview';
 import * as Locations from 'frama-c/kernel/Locations';
 import { getWritesLval, getReadsLval } from 'frama-c/plugins/studia/api/studia';
 import './style.css';
@@ -105,6 +106,8 @@ export function buildMenu(
   }
 }
 
+ASTview.registerMarkerMenuExtender(buildMenu);
+
 const studiaReadsMode : Ivette.SearchProps = {
   id: 'frama-c.plugins.studia.reads',
   rank: -1,
diff --git a/ivette/src/frama-c/plugins/wp/index.tsx b/ivette/src/frama-c/plugins/wp/index.tsx
index f774d664d49e10ea8693b89a844b52e37247e3ac..0c527ec205d1cad28b1e7867a87aaceaf7986b12 100644
--- a/ivette/src/frama-c/plugins/wp/index.tsx
+++ b/ivette/src/frama-c/plugins/wp/index.tsx
@@ -34,6 +34,7 @@ import * as Ivette from 'ivette';
 import * as Server from 'frama-c/server';
 import * as States from 'frama-c/states';
 import * as Ast from 'frama-c/kernel/api/ast';
+import * as ASTview from 'frama-c/kernel/ASTview';
 import { GoalTable } from './goals';
 import { TIPView } from './tip';
 import * as WP from 'frama-c/plugins/wp/api';
@@ -43,7 +44,7 @@ import './style.css';
 /* --- Generate Goals                                                     --- */
 /* -------------------------------------------------------------------------- */
 
-export function buildMenu(
+function buildMenu(
   menu: Dome.PopupMenuItem[],
   attr: Ast.markerAttributesData,
 ): void {
@@ -61,6 +62,8 @@ export function buildMenu(
   }
 }
 
+ASTview.registerMarkerMenuExtender(buildMenu);
+
 /* -------------------------------------------------------------------------- */
 /* --- Goal Component                                                     --- */
 /* -------------------------------------------------------------------------- */