Dead Code Finder: Die harte Realität der statischen Analyse

Ich habe für einen Hackathon ein Tool entwickelt, um toten Code zu finden. Das Ziel war einfach: Code finden, der von nichts aufgerufen wird.

Ich wollte nicht wissen, was kaputtgeht, wenn man Code löscht. Ich wollte wissen, ob überhaupt irgendetwas einen bestimmten Codeabschnitt aufruft.

Ich habe es Dead Code Finder genannt. Es nutzt einen Knowledge Graph, um nach Aufrufen und Imports zu suchen. Dabei werden alle Funde in drei Kategorien unterteilt:

• Confident: Keine eingehenden Kanten und kein Einstiegspunkt. • Uncertain: Fälle wie Vererbung, bei denen statische Analyse nicht ausreicht. • Skipped: Dinge wie Decorator oder Test-Frameworks, die das Tool nicht auflösen kann.

Ich habe einer strengen Regel gefolgt: Sage niemals, dass Code sicher gelöscht werden kann. Der Bericht besagt lediglich, dass im Graphen keine Referenz gefunden wurde.

Das Projekt war schwieriger als erwartet. Ich stieß auf zwei Hauptprobleme mit der Plattform:

  1. Fehlende Tools: Die Graph-Tools fehlten zur Laufzeit, obwohl sie in der Konfiguration enthalten waren.
  2. Unzuverlässige Injection: Das System konnte manchmal nicht die vollständige Logik für den Agenten bereitstellen.

Ich habe dies durch den Bau eines Fallback-Modus gelöst. Wenn die Graph-Tools fehlen, liest das Tool die tatsächlichen Dateien im Repository ein. Es nutzt Dateisuche, um Referenzen zu finden. Wenn es diese Methode verwendet, werden die Funde als inferred markiert.

Zudem musste ich Logikfehler für spezifische Fälle beheben:

  • Dunder-Methoden: Methoden wie __init__ zeigen oft null eingehende Kanten, da der Graph den Aufruf mit der Klasse statt mit der Methode verknüpft. Ich habe dies behoben, indem ich die umschließende Klasse prüfe.
  • Decorator: Funktionen, die über String-Lookups in einem Dictionary aufgerufen werden, wirken auf einen statischen Graphen wie toter Code. Ich habe diese in den Skipped-Bucket verschoben.
  • Tests: Test-Frameworks finden Methoden durch Reflection. Auch diese landen im Skipped-Bucket.

Die Ergebnisse waren zuverlässig. Mein Fallback-Modus identifizierte toten Code korrekt und stimmte mit den echten Graph-Daten überein. Er kennzeichnete auch unsichere Fälle wie Vererbung korrekt.

Gelernte Lektionen:

  • Bestätige die Verfügbarkeit von Tools, bevor du Logik schreibst, die von ihnen abhängt.
  • Ein Bericht, der sagt „Ich weiß es nicht“, ist besser als ein Bericht, der mit voller Überzeugung falsch liegt.
  • Das Kennzeichnen von Unsicherheit sorgt dafür, dass man bei den sicheren Funden tatsächlich handeln kann.

Quelle: https://dev.to/hereforlolz/dead-code-finder-gitlab-orbit-based-static-analysis-that-turned-out-to-be-harder-than-expected-4jgk

Optionale Lern-Community: https://t.me/GyaanSetuAi