Tslint: Vorschlag: Bedingte Fusselkonfiguration

Erstellt am 3. Nov. 2017  ·  42Kommentare  ·  Quelle: palantir/tslint

Es gibt einige Situationen, in denen wir eine Lint-Prüfung bedingt erzwingen möchten, je nachdem, ob der Code, der mit Lint versehen wird, Testcode ist oder nicht. Zum Beispiel möchten wir 'any' aus dem Produktionscode verbannen, da es unsicher ist. Aber in Tests kann 'any' nützlich sein, um gefälschte oder simulierte Implementierungen von Diensten bereitzustellen oder um es zu übertragen, damit Sie private Methoden aufrufen können. Oder wir möchten beispielsweise andere Methoden in Tests als im Produktionscode verbieten.

Was ich vorschlage, ist eine Möglichkeit, Lint-Überprüfungen basierend auf einer Regex-Übereinstimmung des Dateinamens bedingt zu aktivieren. Dies kann auch nützlich sein, um die Lint-Prüfung für bestimmte Verzeichnisse (die beispielsweise "Legacy"-Code enthalten) oder für .tsx- oder .d.ts-Dateien usw. auszuschalten.

Hier sind einige Ideen für Syntax-Strohmänner; Ich bin auch für Vorschläge offen.

Abschnitte Objekt

{
  "rules": {
    "no-any": {"other": true},
    "no-console":
        {
          "test": [true, "warn", "error"], 
          "other": [true, "log", "warn", "error"]
        }
  },
  "sections": {
    "test": ".*\\.spec\\.ts$"
  }
}

"Andere" wären Dinge, die mit keiner der Regexes übereinstimmen. Das ist ziemlich prägnant, aber ich denke, die Lesbarkeit des Regelabschnitts leidet ein wenig.

"Überschreiben"-Regeln

{
  "rules": {
    "no-any": true,
    "no-console": [true, "log", "warn", "error"]
  },
  "override": {
    "match": ".*\\.spec\\.ts$",
    "rules": {
      "no-any": false,
      "no-console": [true, "warn", "error"]
    }
  }
}

(Dies sollte vielleicht ein Array sein, um auch mehrere Überschreibungen zu ermöglichen).

Declined Enhancement

Hilfreichster Kommentar

Die Verschachtelung löst die hier diskutierten Probleme nicht. Viele Menschen tun , um ihre Tests in der gleichen Verzeichnisstruktur wie der Code soll es testet, und es gibt einfach keine gute Möglichkeit , dass gerade jetzt mit tslint zu tun.

Alle 42 Kommentare

Wenn Sie Ihre Tests und Ihren Produktionscode in separate Verzeichnisse legen, benötigen Sie eine solche Funktion nicht. Wenn Sie keine Konfigurationsdatei als CLI-Argument bereitstellen, verwendet TSLint das nächste tslint.json . Daher können Sie für verschiedene Ordner unterschiedliche Einstellungen vornehmen. Durch die Verwendung von "extends" Sie dieselbe Basiskonfiguration verwenden und nur bestimmte Regeln überschreiben.

Ich verstehe, dass viele Angular- und React-Projekte Tests im selben Verzeichnis wie der entsprechende Produktionscode ablegen. Ich persönlich halte dies für eine schlechte Praxis. Ich habe genug Leute gesehen, die (versehentlich) Symbole aus Tests in Produktionscode importiert haben.

IMO fügt die vorgeschlagene Funktion viel Komplexität hinzu. Die Implementierung ist vielleicht nicht so schwer, aber es macht die Konfigurationsdatei schwer zu lesen und zu verstehen.
Wenn wir dies umsetzen wollen, würde ich den zweiten Vorschlag vorziehen.

Wir müssten auch besprechen, wie es funktioniert, wenn Konfigurationen erweitert werden. In welcher Reihenfolge werden die Überschreibungen angewendet?

Es stimmt, Sie könnten den Code einfach trennen, aber es schadet der Ergonomie. Entweder hast du

src/
  tslint.json
  a/
    b/
      c/
test/
  tslint.json (extends ../src)
  a/
    b/
      c/

und c/foo.spec.ts muss import {symbol} from '../../../a/b/c/foo';

Dieser Pfad wird in unserem Monorepo hässlich, wo Dateien oft sehr tief im Baum liegen.

oder du hast

  a/
    src/
      tslint.json
    test/
      tslint.json (extends ../src)
    b/
      src/
        tslint.json
      test/
        tslint.json (extends ../src)
      c/
        src/
           tslint.json
        test/
          tslint.json (extends ../src)

das sind zu viele tslint.json-Dateien

Zum Thema Überschreibungen: Ich würde sagen, die Überschreibungen gelten in der gleichen Reihenfolge, in der Regeln angewendet werden. Ich weiß nicht, was das ist, und ich konnte keine Dokumentation finden, aber intuitiv würde ich denken, dass es so wäre:

// a.json
{"rules": {"foo": [true, 1]}}

// b.json
{"rules": {"foo": [true, 2]}}

// c.json
{
  "extends": ["a.json", "b.json"],
  "rules": {"foo": [true, 3]}
}

würde dazu führen, dass die Regel "foo" das Argument 3 hat. Wenn diese Regel nicht in c.json , dann sollte "foo" den Wert 2 haben, wegen der Reihenfolge des "extends"-Arrays.

Bei Überschreibungen würde ich erwarten, dass dieselbe Reihenfolge angewendet wird. Es ist für mich sinnvoll, die letzte Überschreibung zu verwenden, die der angegebenen Regex entspricht, unter Berücksichtigung der Reihenfolge, in der 'extends'-Regeln berücksichtigt werden. Ein Beispiel für eine einzelne Datei:

{
  "rules": {"a": [true, 1]},
  "override": [
    {"match": "test|spec", "rules": {"a": [true, 2]}},
    {"match": "test", "rules": {"a": [true, 3]}}
  ]
}

würde den Wert 2 für die Regel "foo" haben, wenn der Dateipfad "spec" enthält, 3, wenn er "test" enthält, und 1 andernfalls. (offensichtlich kein sehr nützlicher Satz von Überschreibungen, da "test" genauso gut aus dem ersten weggelassen werden könnte, aber Sie bekommen die Idee)

Macht das Sinn und beantwortet Ihre Frage?

@calebegg Es sind noch einige andere

// a.json
{
  "rules": {"foo": [true, 1]},
  "override": {"match": "test|spec", "rules": {"foo": [true, 2]}}
}

// b.json
{
  "extends": "./a.json"
  "rules": {"foo": false}
}

Was ist das erwartete Ergebnis?

  • 2 weil die Bestellung a.json/rules -> b.json/rules -> a.json/override
  • false weil die Bestellung a.json/rules -> a.json/override -> b.json/rules

Das gleiche hier, was ist das erwartete Ergebnis:

// c.json
{
  "rules": {"foo": [true, 1]},
  "override": {"match": "test|spec", "rules": {"foo": false}}
}

// d.json
{
  "extends": "./a.json"
  "rules": {"foo": {"options": 2}},
  "override": {"match": "test|spec", "rules": {"foo": {"options": 3}}}
}

Nur ein zufälliger Gedanke: Warum nicht einfach die Muster der Reihe nach abgleichen und die vorherige Übereinstimmung (teilweise) überschreiben:

{
  "rules": { // same as "*"
    "rule-one": true,
    "rule-two": true
  },
  "*.js?(x)": { // we could get rid of "jsRules" with this
    "rule-two": false
  },
  "*.{t,j}sx": {
    "jsx-rule": true
  },
  "*.spec.*" {
    "rule-one": false
  }
}

Einige Beispiele:

  • foo.ts : Regel eins, Regel zwei
  • foo.tsx : Regel-eins, Regel-zwei, jsx-Regel
  • foo.js : Regel-eins
  • foo.jsx : Regel-eins, jsx-Regel
  • foo.spec.tsx : Regel-zwei, jsx-Regel
  • foo.spec.js : keine

Ich weiß nur nicht, wo ich das in die Konfiguration einfügen soll. Die gleiche Ebene wie "rules" erleichtert das Schreiben, kann jedoch die Benutzer verwirren, da sie auf der gleichen Ebene wie "extends" , "rulesDirectory" , ...

Ein weiteres Problem ist das Erweitern von Konfigurationen. Wenn wir alle Überschreibungen aus der Basiskonfiguration und dann die Überschreibungen aus der aktuellen Konfiguration anwenden, ist es ziemlich schwer zu verstehen.

Es macht den Code auch komplexer. Derzeit werden die Konfigurationen beim Parsen zusammengeführt. Bei diesem Vorschlag ist die endgültige Konfiguration nur bekannt, wenn wir einen Dateinamen haben.

Hallo,

Diese Funktion wird großartig sein. Ich denke, Eslint unterstützt diese Funktion: https://eslint.org/docs/user-guide/configuring#configuration -based-on-glob-patterns. Syntax und Semantik könnten also gleich sein, um Verwirrung zu vermeiden.

@minomikula Vielen Dank. Ich habe zuvor die ESLint-Dokumente durchsucht, aber diesen Abschnitt nicht gefunden.

Ihr Ansatz ist sinnvoll. Zusammenfassen:

  • "overrides" Abschnitt
  • eine Überschreibung kann mehrere Globmuster angeben ( "files" ). wenn einer davon übereinstimmt, gilt die Konfiguration
  • Sie können Dateien nach dem Glob-Muster ausschließen: "excludedFiles"
  • glob-Muster sind relativ zur Konfigurationsdatei, in der sie angegeben sind
  • glob-Muster müssen immer mit dem gesamten Pfad übereinstimmen, nicht nur mit dem Basisnamen
  • Überschreibungen werden der Reihe nach verarbeitet und überschreiben die vorherige
  • Beim Erweitern einer Konfigurationsdatei wird die Basiskonfiguration vollständig ausgewertet, bevor mit der Erweiterungskonfiguration fortgefahren wird

    • base.json/rules

    • base.json/overrides

    • extension.json/rules

    • extension.json/overrides

Bei der Portierung dieses Verhaltens auf TSLint sind einige Dinge zu beachten:

  • wir sollten auf jeden Fall extends und linterOptions in Überschreibungen deaktivieren
  • wir wollen wahrscheinlich auch rulesDirectory verbieten
  • Wollen wir rules und jsRules in Überschreibungen zulassen oder lehnen wir jsRules zugunsten einer **/*.js?(x) Überschreibung ab?

Gedanken oder Kommentare @adidahiya @calebegg @alexeagle @minomikula?

Oh, wow, ja, dieser Ansatz scheint mir vernünftig. Ich hätte auch nach Stand der Technik suchen sollen.

Das wäre eine tolle Ergänzung! Der Ansatz von eslint funktioniert hervorragend, wenn einige Regeln in Testdateien bedingt deaktiviert werden.

@calebegg hast du noch vor, das voranzutreiben, wenn du Zeit findest?

Ja, daran möchte ich auf jeden Fall arbeiten. @ajafff Sind Sie im Allgemeinen zufrieden damit, mit dem ESLint-Ansatz zu beginnen und in PRs zu iterieren? Oder sind Ihrer Meinung nach Designfragen, über die wir zuerst sprechen sollten?

Wollen wir Regeln und jsRules in Überschreibungen zulassen oder verwerfen wir jsRules zugunsten einer */ .js?(x)-Überschreibung?

Es macht für mich Sinn, abzulehnen, aber ich fühle mich auch nicht sehr stark.

@calebegg Mir geht es gut mit dem ESLint-Ansatz. Ich habe ein sehr ähnliches Konzept in meiner POC-Linter-Laufzeit implementiert https://github.com/fimbullinter/wotan/tree/master/packages/wotan#overrides

Die Integration in die aktuelle TSLint-API könnte schwierig sein, da sie derzeit alle Konfigurationen beim Parsen zusammenführt. Dies muss verschoben werden, bis der Name der Datei bekannt ist, und muss für jede Datei durchgeführt werden.

Dies ist sicherlich eine bahnbrechende API-Änderung.

@calebegg @mitchlloyd @ajafff @alexeagle Ich sehe in dieser Funktion wenig Vorteile gegenüber dem einfachen Verschachteln von tslint.json Dateien, um äußere Konfigurationen zu überschreiben. diese Funktion funktioniert bereits heute und erfordert keine komplexen API-Unterbrechungen. Wären Sie beleidigt, wenn wir diese Anfrage ablehnen?

Die Verschachtelung löst die hier diskutierten Probleme nicht. Viele Menschen tun , um ihre Tests in der gleichen Verzeichnisstruktur wie der Code soll es testet, und es gibt einfach keine gute Möglichkeit , dass gerade jetzt mit tslint zu tun.

Es gibt viele Projekte, die Spezifikationsdateien im selben Verzeichnis wie die Quellen ablegen. Dies ist in vielen Umgebungen zu einer bewährten Methode geworden, Angular CLI generiert eine Projektstruktur wie diese usw. Ich glaube nicht, dass das Verschachteln von tslint-Konfigurationsdateien für all diese Leute funktionieren wird.

Ich bin damit einverstanden, dass meine Projektstruktur nicht von einem Linting-Tool diktiert werden sollte. Stattdessen sollte das Linting-Tool gängige vorhandene Muster unterstützen. Die gemeinsame Anordnung von Tests und Quelldateien ist ein gängiges Muster.

@giladgray Die angeforderte Änderung unterstützt ein Szenario, in dem Benutzer ihre Tests und Produktionsdateien wie

some-dir/
  my-component.ts
  my-component.test.ts

Wie würde "Verschachtelung von tslint.json Dateien" diesen Anwendungsfall angehen, wenn wir unterschiedliche Regeln für my-component.ts und my-component.test.ts ?

Die Winkelrichtlinien von @giladgray empfehlen, dass Sie Ihre Tests neben Ihren Dateien platzieren. 99% der Angular-Projekte tun dies. Da Tslint rückwärts war, hatte jedes Winkelprojekt, an dem ich arbeitete, Probleme. Ihr letzter Kommentar ist verwirrend und kurzsichtig. Wenn Sie diesen unglaublich nützlichen Vorschlag nicht annehmen können/wollen, dann sind Sie meiner Meinung nach viel zu konservativ, um bei einem so wichtigen Projekt für uns Entscheidungen zu treffen. Dieses Thema erschwert unsere kantige Projektarbeit seit Jahren.

@ohjames Bleiben wir beim Thema und vermeiden Sie persönliche Angriffe, okay? Zu behaupten, dass jemand nicht in der Lage ist, sein eigenes Projekt zu verwalten, ist nicht der Weg, um OSS zu beeinflussen, und wird sicherlich nicht dem helfen, wofür wir hier alle argumentieren.

Es ist sinnvoll, Überschreibungen für Dateien zu verwenden, die nicht wie oben erwähnt in eine verschachtelte Struktur passen. Es scheint mir, als ob der Kommentar von

Wenn Sie dies verfolgen möchten, aktualisieren Sie bitte diesen Zweig, damit wir ihn überprüfen können, oder schließen Sie ihn, wenn er nicht mehr relevant ist. Wir werden dies schließen, wenn wir in zwei Wochen nichts von Ihnen hören.

@ohjames Ich würde vorschlagen, dass Sie Ihren Kommentar noch einmal überdenken - wie @DanielSchaffer erwähnt hat, werden Ihnen persönliche Angriffe weder hier noch irgendwo in Open-Source-Software helfen. Jeder versucht sein Bestes, um gute, zuverlässige und funktionsreiche Software zu entwickeln, und Angriffe auf Menschen tragen in keiner Weise dazu bei.

Gibt es zu diesem Thema ein Update?
Die von @ajafff in seinem zusammenfassenden Kommentar vorgeschlagene Idee scheint vernünftig und befriedigt alle unterschiedlichen Bedürfnisse. Die Verwendung derselben Semantik wie bei eslint ist ein guter Weg nach vorne.

Wie ich den verwandten #1063 kommentiert habe, wäre mein Anwendungsfall, dass die Verwendung von tslint-microsoft-contrib derzeit Vue-Einzeldateikomponenten für einige Regeln bombardiert. Dies kann entweder ein Vue-Problem oder ein TSLint-Problem sein, und diese Teams können das spezifische Problem möglicherweise beheben oder auch nicht. Im Vergleich dazu müssen Sie jeder einzelnen .vue-Datei dieselbe Deaktivierungsdirektive hinzufügen und sie an allen diesen Stellen aktualisieren, wenn sich die Regelunterstützung ändert. Es macht auch keinen Sinn, ein Projekt in .vue- und .ts-Dateien aufzuteilen, da dies eine sehr umständliche Struktur wäre.

Ich bin dafür, dass dieses Feature eingeführt wird. Vielleicht können wir damit auch die tslintignore-Anfrage in #73 sauber lösen, indem wir einigen Überschreibungen erlauben, alle Regeln vollständig zu deaktivieren?

{
    "files": "./src/test-data/*.ts",
    "reset": true // Resets tslint.json to {}
}

tslint-microsoft-contrib bombardiert derzeit Vue-Einzeldateikomponenten für einige Regeln

Oh 😕 @millimoose könnten Sie bitte ein Problem bei tslint-microsoft-contrib melden?

@JoshuaKGoldberg - Ich hatte bereits einen ausführlichen Bericht über diesen Fehler in @vuejs/vue-cli erstellt, der am besten geeignet schien. (Es ist als "Warten auf Reproduktion" gekennzeichnet, daher vermute ich, dass es nicht ganz fehl am Platz ist.) Ich habe es nur als Motivation erwähnt, um sich hier einzumischen. Es ist die Art von Dingen, die in einem sich entwickelnden Ökosystem vorkommen können und werden, was ein Argument dafür sein sollte, dass Tools flexibel genug sind, um Hindernisse zu umgehen, ohne tatsächlich Hacks um die Fehler anderer zu schreiben.

Irgendein Update zu diesem Thema?

Dieses Problem ist derzeit als "Vorschlag erforderlich" gekennzeichnet, aber ich denke, wir haben bereits einen Vorschlag in https://github.com/palantir/tslint/issues/3447#issuecomment -344020834?

Der Vorschlag von @ajafff erwähnte einige lose Enden, die angegangen werden sollten:

Bei der Portierung dieses Verhaltens auf TSLint sind einige Dinge zu beachten:

  • wir sollten auf jeden Fall extends und linterOptions in Überschreibungen deaktivieren
  • wir wollen wahrscheinlich auch rulesDirectory verbieten
  • Wollen wir rules und jsRules in Überschreibungen zulassen oder lehnen wir jsRules zugunsten einer **/*.js?(x) Überschreibung ab?

Darüber sollten sich auch die Leute in der Palantirtech-Organisation einig sein, bevor Sie fortfahren, da es sich um ein ziemlich wesentliches Feature handelt.

Ich bin gerade selbst darüber gestolpert und möchte nur mein Interesse an dieser Art von Feature bekunden.

Am Ende haben wir einige Linting-Regeln gelockert, die sich auf Produktionscode auswirken, und mal sehen, wie es läuft. ):

Ich würde diese Funktion gerne sehen

abonnieren - Brauchen Sie dies auch.

Ich brauche das so dringend :(

Hier gilt das gleiche! Wir verwenden Typescript mit Vuejs und unsere Unit-Test-Dateien befinden sich nicht zusammen in einem Tests-Verzeichnis, sondern überall entlang des Komponenten-Quellcodes.

Ich würde gerne diese Funktion sehen, wir verwenden derzeit ein etwas wackeliges Setup, das dazu führt, dass vscode andere Linting-Fehler hervorhebt als die, die unser Befehlszeilen-Lint hervorhebt, um dieses Problem zu umgehen.

Ich bezweifle stark, dass diese Funktion jemals implementiert wird, Tslint scheint im Allgemeinen nicht aktiv gewartet zu werden. Ich schlage vor, zu @typescript-eslint wechseln, es wird sowohl von eslint- als auch von ts-Projekten vollständig unterstützt und die Migration ist mit @typescript-eslint/eslint-plugin-tslint einfacher denn je. Und es gibt eine Compat-Tabelle mit Tslint und entsprechenden Eslint-Regeln / anderen Alternativen. Das Eslint-Setup ist hochgradig anpassbar, daher sehe ich keinen Sinn, bei Tslint zu bleiben.

Ich schlage vor, das Konzept, das das Git-Repository für Dateien in der Datei .gitIgnore... verwendet, auf die tsLint-Regeln anzuwenden. Verwendung Ihrer aktuellen hierarchischen Position als Kontext für den Linter, zusammen mit einer Überschreibungsdatei, wenn ein bestimmtes Unterverzeichnis liniert wird. Dann können Sie jede beliebige Konfiguration auf jeder gewünschten Verzeichnisebene ein- oder ausschließen und einrichten.

z.B
Eine tslint-Konfiguration wird im Stammverzeichnis platziert, und auf einer bestimmten Ebene in Ihrer Quellcodestruktur möchten Sie ein anderes Verhalten. Überschreiben Sie es einfach mit einer Erweiterungs-tslint-Datei im Stammverzeichnis dieses Unterverzeichnisses.

@redevill Es hilft Leuten, Tests in einem test Ordner zu schreiben. Aber nicht ein Schreibtest als something.test.ts im selben Ordner der Komponente/des Dienstes.

Einverstanden - aber mit kleiner Änderung: (Was mit Template-Generator (CLI Style) automatisiert werden könnte
MyComponentDir
---MyComponentTestsDir
------tslint.test.json
------etwas.test.ts
---mycomponent.component.css
---mycomponent.component.html
---mycomponent.component.ts

Die Idee könnte noch funktionieren.

Großer Fan dieses Vorschlags. JA BITTE! Ich bevorzuge das Overrides-Konzept.

Übrigens, angesichts der Ankündigung der Einstellung von tslint kann ich mir _wirklich_ nicht vorstellen, dass zu diesem Zeitpunkt eine so große Änderung vorgenommen wird und mein Team zu eslint übergeht, das bereits über Funktionen zum Überschreiben pro Regel und pro Datei verfügt.

@RoystonS hat grundsätzlich Recht, ein so großes Feature wird an dieser Stelle nicht zu Tslint hinzugefügt. siehe #4534

Wir verwenden ein Angular-Projekt. Wir brauchen das Overrides-Konzept. Ansonsten ist es schwer zu handhaben

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen