]> Repositorios git - classgraph.git/commitdiff
Render a side panel for external type families
authorJavier Sagredo <[email protected]>
Wed, 6 May 2026 23:21:02 +0000 (01:21 +0200)
committerJavier Sagredo <[email protected]>
Wed, 6 May 2026 23:51:06 +0000 (01:51 +0200)
Clicking a family node not present in pdTypeFamilies (e.g. SigDSIGN
from a foreign crypto package) used to render nothing — showSelection
silently fell off the renderFamilyPanel branch. Add
renderExternalFamilyPanel that uses the QualName's package + module
to give a useful description, mirroring the external-class panel
treatment.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
data/viewer.js

index 677aaf5c5d850b63afe5844102c215d9d1a4b904..e97247975f3fae72a40b91a83f98bfc26dc1609a 100644 (file)
       }
     } else if (data.kind === 'family') {
       const fam = familyById.get(target.id());
-      if (fam) el.innerHTML = renderFamilyPanel(fam);
+      if (fam) {
+        el.innerHTML = renderFamilyPanel(fam);
+      } else {
+        // External family — not in pdTypeFamilies but referenced
+        // via a FamilyApp somewhere. We still know its package and
+        // module from the QualName, so render a minimal panel.
+        el.innerHTML = renderExternalFamilyPanel(data);
+      }
     } else if (data.kind === 'instance') {
       el.innerHTML = renderInstancePanel(data.instance);
     } else if (data.kind === 'fam-instance') {
       </dl>`;
   }
 
+  // External family panel — the family is referenced (so we have a
+  // QualName with package + module), but it isn't in pdTypeFamilies.
+  // We don't know its kind, flavour, or arity, so we just describe
+  // what we *do* know.
+  function renderExternalFamilyPanel(d) {
+    const pkg = d.package || '';
+    const mod = d.module  || '';
+    let status;
+    if (pkg && mod) {
+      status = `Defined in module <code>${escape(mod)}</code> ` +
+               `(package <code>${escape(pkg)}</code>) — not extracted ` +
+               `by the plugin in this program. Re-run the plugin against ` +
+               `the package that owns this family if you'd like its ` +
+               `equations to surface here.`;
+    } else if (mod) {
+      status = `Defined in module <code>${escape(mod)}</code> — not ` +
+               `extracted by the plugin in this program.`;
+    } else if (pkg) {
+      status = `Defined in package <code>${escape(pkg)}</code> — not ` +
+               `extracted by the plugin in this program.`;
+    } else {
+      status = `Referenced but not extracted by the plugin in this program.`;
+    }
+    return `
+      <h2>${escape(d.label)}</h2>
+      <p class="pkgmod">${escape(pkg)} · ${escape(mod)}</p>
+      <dl>
+        <dt>Status</dt><dd>${status}</dd>
+      </dl>`;
+  }
+
   function renderInstancePanel(inst) {
     const head = escape(inst.iiClass.qnName) + ' ' +
       escape(renderArgsCompact(inst.iiArgs, inst.iiTyVars));