Spezifische Unterdrückung von Flussfehlern

Mar 19 2020
Wir verbessern die Unterdrückung von Flussfehlern, damit sie nicht versehentlich Fehler verbergen. Im kommenden Jahr plant Flow viele Änderungen und Verbesserungen an seinem Typsystem.
Foto von icon0.com aus Pexels

Wir verbessern die Unterdrückung von Flussfehlern, damit sie nicht versehentlich Fehler verbergen.

Im kommenden Jahr plant Flow viele Änderungen und Verbesserungen an seinem Typsystem . Eine der Konsequenzen davon ist jedoch, dass Sie möglicherweise mehr Unterdrückungen zu Ihrem Code hinzufügen müssen, da Flow vorhandene Probleme besser finden kann.

Dies kann ein Problem sein, da die Unterdrückungen von Flow mehr als nur den ursprünglichen Fehler betreffen, den Sie unterdrücken wollten. Dies verringert die Fähigkeit von Flow, Fehler zu erkennen. Dies ist ein Ergebnis von zwei Eigenschaften: Erstens, dass sich Flussunterdrückungen an einem beliebigen Teil eines Typfehlers befinden können, und zweitens, dass Flussunterdrückungen jede Art von Typfehler unterdrücken können . Um diese Mängel zu beheben, müssen Unterdrückungen an der Stelle in Ihrem Code platziert werden, an der der Fehler tatsächlich auftritt, und dass sie einen Fehlercode enthalten, der die Art des Fehlers angibt, den Sie unterdrücken möchten.

Um zu verstehen, was dies alles bedeutet, wollen wir uns mit der Art der Typfehler von Flow befassen.

Was ist ein Typfehler?

Wenn Flow beim Überprüfen Ihres Codes auf ein Problem stößt, z. B. eine Inkompatibilität zwischen zwei Typen oder einen ungültigen Eigenschaftszugriff, wird ein Fehler generiert, der dem Benutzer genau meldet, was mit seinem Code nicht stimmt. Diese Fehler können abhängig von den besonderen Umständen, die sie verursacht haben, eine Vielzahl von Informationen enthalten. Die beiden, die uns am meisten interessieren, sind die Art des Fehlers und die Orte des Fehlers.

Die Art des Fehlers kodiert die Spezifität des schlechten Verhaltens, das Flow in Ihrem Code festgestellt hat, sei es einfach wie das Übergeben zu vieler Argumente an eine Funktion oder komplex wie das Verbreiten eines Unionstyps. Diese Informationen teilen Flow genau mit, welche Art von Informationen dem Benutzer angezeigt werden sollen, um genau zu erklären, wo Sie einen Fehler gemacht haben.

Die Standorte des Fehlers enthalten Informationen darüber , wo der Fehler im Code befindet. Es gibt zwei Arten von Orten, die ein Fehler enthalten kann: einen primären Ort (von denen es nur einen geben kann) und sekundäre Orte, von denen es viele oder gar keine geben kann. Der primäre Speicherort entspricht in etwa dem Speicherort in Ihrem Code, an dem der Fehler tatsächlich aufgetreten ist, während die sekundären Speicherorte Informationen zu den Definitionsstandorten der am Fehler beteiligten Typen und Werte enthalten. Zum Beispiel:

function foo(x : number) : void {}
foo("hello");
/* error */
foo("hello");
       ^ Cannot call `foo` with `"hello"` bound to `x` because string [1] is incompatible with number [2].
References:
2: foo("hello");
       ^ [1]
1: function foo(x : number) : void {}
                    ^ [2]

function foo(x : number) : void {}
let y : string = "hello";
foo(y);
/* error */
foo(y);
       ^ Cannot call `foo` with `y` bound to `x` because string [1] is incompatible with number [2].
References:
2: let y : string = "hello";
           ^ [1]
1: function foo(x : number) : void {}
                    ^ [2]

Was ist also so falsch an Unterdrückungen?

Nun, da Unterdrückungen sowohl an der primären als auch an der sekundären Stelle angewendet werden können, würde ein //$FlowFixMeKommentar über der Definition von foodie Fehler in beiden obigen Beispielen unterdrücken. Da es fooin jedem Fehler, der es verwendet, als sekundärer Speicherort erscheint, würde dies bedeuten, dass jede Verwendung foodieses Fehlers durch diese eine Unterdrückung unterdrückt wird, wo immer sie auftreten könnte. Sie können foomit einer beliebigen Anzahl von Argumenten eines beliebigen Typs aufrufen, und Flow zeigt Ihnen diesbezüglich keine Fehler oder Warnungen an. Dies beeinträchtigt das Vertrauen der Benutzer in die Typprüfung von Flow und ermöglicht es Fehlern, die sie sonst entdeckt hätten, in die Produktion zu gelangen.

Darüber hinaus wirken sich die Unterdrückungen von Flow auf alle Arten von Fehlern aus, sofern sie einen Ort enthalten, den die Unterdrückung abdeckt. Dies bedeutet, dass mehrere Fehler unterschiedlicher Art durch eine einzige Unterdrückung unterdrückt werden können. Betrachten Sie das folgende Beispiel, um die Gefahr darin zu erkennen:

// library file lib.js
function foo(x : number) : void {}
// impl file
const {foo} = require("lib.js");
let y : string = "hello";
// $FlowFixMe
foo(y);

Was werden wir dagegen tun?

Um dies zu beheben, werden wir die folgenden Änderungen vornehmen:

  • Primäre Standorte erzwingen. Wir werden das Unterdrückungsverhalten so ändern, dass Unterdrückungen nur für Fehler gelten, wenn sie an ihrem primären Standort platziert werden. Anstatt beispielsweise zuzulassen, dass Sie einen ungültigen Aufruf bei der Definition der Funktion unterdrücken, müssen Sie die Unterdrückung jetzt am Aufrufort selbst durchführen. Auf diese Weise kann Flow Sie weiterhin über andere möglicherweise ungültige Aufrufe der Funktion informieren.
  • Fügen Sie Fehlercodes hinzu. Wir werden unseren Unterdrückungen auch Fehlercodes hinzufügen, damit sie nur Fehler der angegebenen Art unterdrücken. Dadurch wird verhindert, dass Unterdrückungen unerwartet einen Fehler unterdrücken, den Sie nicht erwartet hatten.
  • Standardisieren Sie die Unterdrückungssyntax. Bisher konnte die akzeptable Syntax für eine Fehlerunterdrückung .flowconfigfür ein bestimmtes Projekt manuell konfiguriert werden , um eine inkonsistente Unterdrückungssyntax für alle Projekte zu ermöglichen. Im Rahmen der obigen Änderungen werden wir auch die Unterdrückungssyntax standardisieren. unterstützt nur die $FlowFixMe[incompatible-type]oder $FlowExpectedError[incompatible-type]Formate.

Ausrollen

Wir sind uns bewusst, dass diese Änderung dazu führen kann, dass eine erhebliche Anzahl von Fehlern in Ihren Codebasen ungültig wird, insbesondere wenn Sie die Gewohnheit hatten, Unterdrückungen in den Bibliothekscode einzufügen. Um diese Belastung zu verringern, haben wir einige Vorschläge:

  • Um Ihre neu ungültigen Unterdrückungen an ihre primären Speicherorte zu verschieben, empfehlen wir eine Kombination der im Flow-Tool bereitgestellten Dienstprogramme add-commentsund remove-comments. Durch Ausführen ./tool remove-commentswerden alle Kommentare entfernt, die einen Fehler nicht mehr unterdrücken, da sie sich nicht an einem primären Speicherort befinden, und ./tool add-commentsneue Unterdrückungen werden an nicht unterdrückten Speicherorten platziert. Auf das ./toolSkript kann zugegriffen werden, indem das Flow-Repository auf GitHub geklont wird.
  • Unterdrückungen ohne Fehlercodes unterdrücken weiterhin alle Fehler an ihrem Speicherort. Sobald wir jedoch die Fehlercode-Funktion eingeführt haben, können Sie die richtigen Codes über einen ähnlichen Vorgang wie oben zu Ihrer Codebasis hinzufügen. Wenn Sie alle Ihre alten Kommentare entfernen und erneut hinzufügen, add-commentswird der Fehlercode in den neu hinzugefügten Kommentar aufgenommen.