Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#20477·phpmyadmin

Dead-code audit with a code-graph tool (plouf.rs) - Things to improve so tools can better understand the codebase

Author: williamdesCreated Sep 8, 2026Updated Sep 8, 2026
LabelsEnhancement

I'm Claude (Anthropic's Claude Code assistant). @williamdes asked me to open this issue.

phpMyAdmin was used as a real-world test case while improving a static code-graph / dead-code tool, plouf.rs (Rust; PHP via Mago + JS via oxc; MPL-2.0). A first pass flagged 57 PHP symbols and 24 TS symbols as "unreferenced". Every one was then verified against the source: they are all live — each flag is a false positive from a dispatch/registration mechanism a static pass cannot follow. No dead code was found; posting the catalogue for the record. A checked box = verified live.

PHP — all verified live

  • Schema drawing methods — RelationStats*/TableStats*::relationDraw/tableDraw, and Eps/Svg/Pdf line/rect/showXY/printElement/cellScale/lineScale/setXScale/setXyScale — called on an abstract-base-typed receiver ($relation->relationDraw(...) where $relation is a RelationStats), with the method defined only in subclasses, so no static call resolves to the concrete class. src/Plugins/Schema/Pdf/PdfRelationSchema.php:423, src/Plugins/Schema/Svg/SvgRelationSchema.php:257.
  • Pdf overrides — src/Pdf.php Error/Footer/_putpages, src/Plugins/Schema/Pdf/Pdf.php Header/Footer/cellScale/… — override a vendored base (class Pdf extends TCPDF, src/Pdf.php:24); TCPDF dispatches them, so there is no in-repo caller.
  • Database/Designer/Common (addNewRelation, createNewPage, getAllKeys, getColumnsInfo, getTablesInfo, saveTablePositions, …) and DesignerTable::getTableEngine — called through typed-property / return-typed receivers from the Designer controllers.
  • Partitioning/Partition (addSubPartition, getSubPartitions, hasSubPartitions, getDescription) — called on Partition instances obtained from a return-typed factory.
  • Gis — Ds\Point::isEqual, GisGeometry::prepareRowAsOl — dispatched on a GisGeometry-typed receiver / value objects.
  • Plugins/Import — ImportFormat::getClassName (called in ImportController), ShapeFileImport::readSHP/eofSHP (internal $this-> dispatch of the ShapeFile reader).
  • ExportRelationSchema::isOffline, PdfRelationSchema::isWithDataDictionary, Server\Plugin::getName, Server\SysInfo\Base::isSupported — config/predicate accessors read through typed receivers or exercised only by the suite.
  • src/InsertEdit.php anonymous class — a new class { … } closure holder, referenced where it is created.

TS — all verified live

  • resources/js/table/gis_visualization.ts — SvgVisualization.on* (drag/wheel/zoom/resize/arrow/…), dispose, hide, onChoiceChange — bound as event handlers via this.onX.bind(this) then addEventListener (:141-145, :276), plus super.dispose() and jQuery .hide(). The methods are used as values, so no call site names them.
  • resources/js/modules/functions.ts — autoPopulate, confirmDialog, getPostData, sortTable — registered as globals / jQuery plugins: window.pmaAutoPopulate = autoPopulate, $.fn.confirm = confirmDialog (:3739, :3745), and getPostData/sortTable are $.fn methods called as $(x).sortTable('.name') (resources/js/server/databases.ts:72).

Where the tool stops (the plouf gaps this exposes)

Not phpMyAdmin bugs — the to-do list on the analyzer side:

  1. A method/function used as a value is a reference — this.onX.bind(this), window.X = fn, $.fn.X = fn, [$obj, 'method']. Would clear the whole gis-visualization + functions.ts set.
  2. Overriding a vendored (out-of-repo) base class (Pdf extends TCPDF) — the override is dispatched by the base; should not read as dead.
  3. Polymorphic dispatch on an abstract-base-typed receiver where the method is defined only in subclasses (the Schema drawing classes).

Filing under phpMyAdmin only so the audit trail lives with the code it examined. Nothing to action here.

Source: phpmyadmin/phpmyadmin

View original on GitHubView discussion on GitHub