Diskussion Weitere Code-Formatter implementieren

Mat

Aktives Mitglied
Betrifft die Implementierung von

Siehe auch mein Posting von vorhin: https://dev-community.de/threads/code-formatierung-für-die-c-und-c-foren.35/page-3#post-793

Vielleicht habt ihr ja Tipps oder Empfehlungen, wie man da am besten weitere Formatter einbauen könnte, ohne den Docker-Container unnötig aufzublasen.

Meine weiteren Versuche

IDE-Formatter missbrauchen

Eclipse und Jetbrains bringen eigene Bibliotheken oder Skripte mit, mit denen man per Kommandozeile Dateien formatieren kann. Zum Beispiel Java:
VS-Code hat Formatter wie Sand am Meer, und man kann auch per Terminal Extensions für weitere Formatter installieren. Allerdings scheint das Formatieren dann nur über die Befehlspalette in der GUI zu gehen. Dadurch wäre es sehr umständlich, damit etwas automatisch zu formatieren. Ich fand das aber etwas übertrieben, extra IDEs oder dicke Libraries zu installieren und auch keine Ahnung wie das lizenztechnisch aussehen würde.

PHPCS
Hatte für PHP auch noch kurz phpcbf getestet. Den kann man auch schön über composer installieren und direkt aus dem Projektordner ausführen:
Das lief so weit auch aber dann hab ich Prettier gesehen und das vorerst beiseite gelegt. Da kann man auf jeden Fall später drauf zurückkommen.

Prettier
Ansonsten war Prettier sehr vielversprechend und unterstützt viele Sprachen (und funktioniert auch überwiegend), aber ich war noch am überlegen, wie man das am schönsten einbauen könnte. Man braucht zur Ausführung nämlich nodejs, und dazu noch am Besten ein aktuelles (vielleicht gibt's noch eine Python-Alternative).

Aufbau
Die Sprachkonfiguration kann man wie bei clang in eine Datei reinstecken (ist nur ein Zwischenstand vom Herumprobieren) :
Serviervorschlag .prettierrc:
# Specification: http://json.schemastore.org/prettierrc
# Documentation: https://prettier.io/docs/en/index.html

# Plugins
plugins:
    - ./node_modules/@prettier/plugin-php
    - ./node_modules/@prettier/plugin-ruby
    - ./node_modules/@prettier/plugin-xml
    - ./node_modules/prettier-plugin-java
    - ./node_modules/prettier-plugin-kotlin

# General settings
useTabs: false      # indent_style = space
tabWidth: 4         # indent_size = 4
printWidth: 120
singleQuote: false
trailingComma: none
endOfLine: lf       # end_of_line = lf
semi: false
proseWrap: preserve

# Language specific settings
overrides:

    # Stylesheet
    -   files: "*.css"
        options:
            parser: css

    # HTML (without XML validation)
    -   files:
            - "*.html"
            - "*.html5"
        options:
            parser: html
            htmlWhitespaceSensitivity: ignore

    #
    -   files:
            - "*.js"
            - "*.javascript"
        options:
            parser: babel
            trailingComma: es5
            semi: true

    -   files:
            - "*.json"
        options:
            parser: babel
            trailingComma: es5
            semi: true

    -   files:
            - "*.md"
            - "*.MD"
        options:
            parser: markdown

    -   files: "*.scss"
        options:
            parser: scss

    -   files:
            - "*.ts"
            - "*.typescript"
        options:
            parser: typescript

    # Plugin Doc: https://github.com/prettier/plugin-php
    -   files:
            - "*.php"
        options:
            parser: php
            phpVersion: "7.3"
            singleQuote: true
            trailingCommaPHP: true
            braceStyle: "psr-2"

    # Plugin Doc: https://github.com/prettier/plugin-ruby
    -   files:
            - "*.rb"
            - "*.ruby"
        options:
            parser: ruby

    -   files:
            - "*.html.vue"
            - "*.vue"
        options:
            parser: vue
            vueIndentScriptAndStyle: true

    -   files:
            - "*.yaml"
            - "*.yml"
        options:
            parser: yaml
            singleQuote: false
            tabWidth: 2
            trailingComma: none # only applies when using []-arrays

    -   files:
            - "*.xml"
        options:
            parser: xml

Da kann man auch direkt die verknüpften Dateierweiterungen hinterlegen und relativ feingranular Einstellungen vornehmen.

Per npm oder yarn install kann man das Zeug direkt aus der package.json installieren:
package.json:
{
    "name": "code-formatter",
    "description": "Manage JS dependencies to be used with the Code Formatter",
    "version": "0.1.0",
    "dependencies": {
        "prettier": "^2.0.5",
        "@prettier/plugin-php": "^0.14.2",
        "@prettier/plugin-ruby": "^0.18.2",
        "@prettier/plugin-xml": "^0.7.2",
        "prettier-plugin-java": "^0.8.0",
        "prettier-plugin-kotlin": "^2.0.0"
    }
}

Und dann nur noch einen Formatter bauen:
PrettierCodeFormatter.php:
<?php

namespace DevCommunityDE\CodeFormatter\CodeFormatter;

/**
* Class ClangCodeFormatter
*
* @package DevCommunityDE\CodeFormatter\CodeFormatter
*/
class PrettierCodeFormatter extends CodeFormatter
{

    /**
     * @var array
     */
    protected static $supported_languages = [
        'css', // läuft
        'html', // läuft
        'javascript', // läuft
        'json', // läuft
        'less', // läuft
        'markdown', // läuft, kümmert sich wohl nur um leere Zeilen
        'scss', // läuft
        'typescript', // läuft
        'php', // läuft
        'ruby',// läuft halb
        'vue', // läuft
        'yaml', // läuft, aber sehr empfindlich
        'xml', // ToDo
    ];

    /**
     * Config taken automatically from <code>.prettierrc</code>
     * @param string $file
     * {@internal <code>--loglevel silent</code> does not override exit codes}
     * @return string
     */
    protected function getShellCommand(string $file) : string
    {
        return 'prettier --loglevel silent --write \'' . $file . '\'';
    }

}

Probleme

Idee 1
NPM in der Dockerfile installieren (damit automatisch auch Node):
Dockerfile:
# Packages for formatting several languages with Prettier
RUN apt update -y && \
    apt install -y npm git && \
    npm install --global prettier

Da wird dann dann irgendein Gammel installiert (node 10 und npm 3 oder sowas.. und dann beschwert sich npm auch noch, dass node10 zu alt sei.. es müsse node 5,6,7 oder 8 her!! .. das parsed wohl nur die erste Stelle in der Version, aber das kennen wir ja von JS). Es lief dann auch, aber die anderen SprachPlugins waren nicht kompatibel damit. Man muss also eine custom repo für node hinterlegen und sich da die neue Version holen. Ich hatte es auch mit dem vorinstallierten snap-Paketmanager statt apt versucht, aber der hatte Netzwerkprobleme. apt kennt yarn nicht, und wenn doch, dann installiert es stattdessen cmdtest oder sowas. Kann man da nicht einfach eine Standalone binary von Node reinklatschen?

Wenn ein js-Interpreter sich als erforderlich und sinnvoll erweist, könnte man da sicher irgendwas platzsparendes hinkriegen. Aber bin da noch am überlegen.

Idee 2
Ich hatte daran gedacht, einen weiteren Container (zum Beispiel hat node:14-slim nur 50MB oder so, inklusive Yarn) laufen zu lassen mit Server, der vom Hauptcontainer per HTTP-Request um Codeformatierungen angebettelt werden könnte. Es gibt wohl auch einige container, die soetwas in der Art laufen haben (die sind leider schon einige Jahre alt). Aber man kann es auch mit den Microservices übertreiben :D

Nodejs als Remote-Interpreter in einem extra-Container wäre schön, aber da müsste man dann ja eine Netzwerkpipeline zwischen den beiden Containern machen mit ssh oder einer Reverse-Shell.. dann kann man eigentlich auch genausogut nodejs im Hauptcontainer installieren.


Abschließend
In Hinblick auf ein mögliches zukünftiges Feature mit eigenen Codestyles (wie zum Beispiel Lano's Code ), ist es wahrscheinlich ganz gut so wenige unterschiedliche Codeformatter wie möglich zu haben, damit da nicht dutzende unterschiedliche APIs für die Formatierungseinstellungen geschrieben werden müssen. Deswegen sind da clang-format und prettier ganz gut. Allerdings scheint prettier leichter erweiterbar zu sein als clang.

Vielleicht kennt ihr ja noch einen gut erweiterbaren Formatter.. habe leider nur Prettier gefunden.

Ganz toll fänd ichs ja, wenn die Interpreter einfach selbst einen Formatter mitliefern würden (wie der von Go), aber am besten noch mit einer anpassbaren standardisierten Formatvorlage. Und der markiert und dann direkt im transformierten Code auch etwaige Syntaxfehler oder Warnungen (falls es kein isolierter Teilcode ist) .. man darf ja noch träumen :D
 
Zuletzt bearbeitet:
Auch an dieser Stelle nochmal ein großes Dankeschön für deine Arbeit! :)

1. Einen IDE-Formatter zu missbrauchen, wäre vermutlich nicht so eine gute Idee.
Da würden wir mit individuellen Formattern für jede Sprache wohl noch besser fahren.
Aber lustigerweise bin ich da tatsächlich auch mal kurz drüber gestolpert. :D

2. PHPCS ist wirklich ein nettes Tool, was natürlich die klassische Wahl wäre, wenn man für PHP nach einem Formatter sucht.
Das könnten wir btw sowieso auch für die Code-Formatter-Codebase nutzen, bspw. precommit.

3. Prettier wäre auf alle Fälle meine Wahl gewesen, um Sprachen wie HTML, CSS und JS zu formatieren.
Prettier als allgemeinen Formatter für eine Vielzahl von Sprachen einzusetzen, um möglichst viele Sprachen mit wenigen Formattern abzudecken, ist aber sicher auch eine gute Idee, die insbesondere in der Zukunft interessant werden könnte.

Die Voraussetzung von Prettier, dass im Container eine aktuelle Node-Version läuft, hätte ich jetzt erstmal nicht als so problematisch erwartet.
Anscheinend hat man da aber als apt-Nutzer wirklich ein Problem. :D

Wenn's irgendwie geht, würde ich aber definitiv erstmal versuchen, Node in den gleichen Container zu bekommen, anstatt einen weiteren Container aufzubauen, mit dem die Anwendung dann kommunizieren müsste.

Man muss also eine custom repo für node hinterlegen und sich da die neue Version holen.

Was heißt das?

Spontan habe ich das hier gefunden:

Ist das im Grunde das, was du meinst? Sieht für mich als Laie so aus, als würde man den Node-Quellcode als Binary herunterladen und dann als Package bauen und zum Installieren auf dem eigenen Rechner verfügbar machen. Jedenfalls hätte man dann Zugriff auf eine aktuelle Node-Version.
 
2. PHPCS ist wirklich ein nettes Tool, was natürlich die klassische Wahl wäre, wenn man für PHP nach einem Formatter sucht.
Das könnten wir btw sowieso auch für die Code-Formatter-Codebase nutzen, bspw. precommit.
Ohja.. sonst muss man dauernd aufpassen, dass man Sachen nicht automatisch von der IDE formatieren lässt. Hab z. B. bei PHPStorm gemerkt, dass der trotz vorhandener .editorconfig dann doch seine eigenen Einstellungen nimmt.

Ist das im Grunde das, was du meinst? Sieht für mich als Laie so aus, als würde man den Node-Quellcode als Binary herunterladen und dann als Package bauen und zum Installieren auf dem eigenen Rechner verfügbar machen. Jedenfalls hätte man dann Zugriff auf eine aktuelle Node-Version.

Ah, ja.. genau. Ich hatte den Schritt ab hier im Hinterkopf:
https://github.com/nodesource/distributions/blob/master/README.md#manual-installation

Das mit curl lädt einfach nur ein Skript runter, das diese manuellen Schritte + Fehlerbehandlung? schon drin hat.

Die Voraussetzung von Prettier, dass im Container eine aktuelle Node-Version läuft, hätte ich jetzt erstmal nicht als so problematisch erwartet.
Anscheinend hat man da aber als apt-Nutzer wirklich ein Problem. :D

Wenn's irgendwie geht, würde ich aber definitiv erstmal versuchen, Node in den gleichen Container zu bekommen, anstatt einen weiteren Container aufzubauen, mit dem die Anwendung dann kommunizieren müsste.

Jo, ich werd's mit dem curl-Skript versuchen, das du gepostet hast und wenn alles läuft, mach ich einen PR.

Aber ich komme wahrscheinlich erst Anfang Juli dazu, das ausgiebig zu testen. Also wenn jemand anders das vorher basteln kann, dann ruhig machen. ;)
 
Ah, ja.. genau. Ich hatte den Schritt ab hier im Hinterkopf:
https://github.com/nodesource/distributions/blob/master/README.md#manual-installation

Das mit curl lädt einfach nur ein Skript runter, das diese manuellen Schritte + Fehlerbehandlung? schon drin hat.

Jo, ich werd's mit dem curl-Skript versuchen, das du gepostet hast und wenn alles läuft, mach ich einen PR.

Aber ich komme wahrscheinlich erst Anfang Juli dazu, das ausgiebig zu testen. Also wenn jemand anders das vorher basteln kann, dann ruhig machen. ;)

Alles klar, vielleicht schaffe ich es ja, mir das in den nächsten Tagen schon mal anzuschauen.
Ich sag dann im Zweifel Bescheid bzw. schiebe die Anfänge dann schon auf GitHub, sodass wir nicht lokal im Geheimen nachher beide dran basteln. :)
 

Kann jemand mal bei sich testen, ob bei docker-compose up das npm install korrekt ausgeführt wird? Also es müsste am Ende den Ordner node_modules anlegen, mit Prettier drin.

Seit der Umstellung von yarn auf npm geht das bei mir mal gut und mal gar nicht. Npm meldet dann, dass die package.json nicht existiert. Ich hoffe, dass ich einfach nur irgendwelche Caching- und Mount-Probleme hab und das bei anderen läuft.


Dockerfile:
FROM php:7.4-apache

COPY .docker/web/vhost.conf /etc/apache2/sites-available/000-default.conf

WORKDIR /srv/app

RUN mkdir -p /srv/app/storage/code
RUN chmod -R ug+rwx /srv/app/storage/code && chown -R www-data:www-data /srv/app && a2enmod rewrite

# Packages for formatting C and C++ code
RUN apt-get update -y && \
    apt-get install -y clang-format

# Packages for formatting Go code
RUN apt-get update -y && \
    apt-get install -y golang

# Packages for formatting Python code
RUN apt-get update -y && \
    apt-get install -y python3.7-minimal python3-pip && \
    pip3 install black

# Packages for formatting code using Prettier (JS, CSS, etc)
RUN apt-get update -y && \
    curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get install -y nodejs && npm install

docker-compose:
version: '3'

services:
  web:
    build:
      context: .
      dockerfile: .docker/web/Dockerfile
    image: dev-community-code-formatter_web
    ports:
      - 8000:80
    volumes:
      - .:/srv/app
    environment:
      - API_KEY=abc
    depends_on:
      - composer

  composer:
    image: composer:1.10
    command: ["composer", "install"]
    volumes:
      - .:/app
 
Wäre cool.

Vielleicht können wir das dann auch direkt für den Repo-Code mitbenutzen (oder zumindest die Regeln zum lokalen Autoformatieren). Siehe:
2. PHPCS ist wirklich ein nettes Tool, was natürlich die klassische Wahl wäre, wenn man für PHP nach einem Formatter sucht.
Das könnten wir btw sowieso auch für die Code-Formatter-Codebase nutzen, bspw. precommit.
 
precommit eher nicht, da hatte ich immer Probleme mit.
Aber generell spricht nichts dagegen. Wir können auch direkt phan/phpstan/psalm integrieren (ich nutze idr. phan).
 
PHP kann man mittels PHP-CS-FIXER realisieren.
Dieses Tools kommt bei vielen (auch sehr großen) Projekten zum Einsatz (z.b. Symfony).


Wenn ihr wollt kann ich das integrieren :)

Gerne, go for it. :)

precommit eher nicht, da hatte ich immer Probleme mit.
Aber generell spricht nichts dagegen. Wir können auch direkt phan/phpstan/psalm integrieren (ich nutze idr. phan).

Ja, gut. Vielleicht wäre das als GitHub Action besser aufgehoben.
Phan kannst du dann gerne auch direkt integrieren, wenn du dich damit auskennst.
 
@JR Cologne sorry wenn der pull-request ein bisschen umfang reich wurde.
Hau einfach dein Feedback rein und ich passe meine Änderungen entsprechend an :)
 
@JR Cologne sorry wenn der pull-request ein bisschen umfang reich wurde.
Hau einfach dein Feedback rein und ich passe meine Änderungen entsprechend an :)

Ich hatte noch dein Request for Review gesehen und mir auch schon den Code durchgesehen. Gefällt mir sehr gut (obwohl ich wegen npx bei Prettier noch schauen muss.. indirekte Aufrufe als Skript hatten bei meinen Tests immer die Laufzeit extrem erhöht, aber kann an meinem System liegen).

Du hast wohl noch schnell Request for Review auch an mich rausgeschickt, als du gesehen hast, dass ich online bin, um direkt noch Mergekonflikte lösen zu können.

Hätte ich so aber direkt absegnen können. Habs nur nicht gemacht, weil ich Entscheidungen über grundlegende Architektur-Änderungen lieber dem Owner überlasse. :D
 
@JR Cologne sorry wenn der pull-request ein bisschen umfang reich wurde.
Hau einfach dein Feedback rein und ich passe meine Änderungen entsprechend an :)

Kein Problem. Schon mal vielen, vielen Dank für deinen PR!
Ihr übertrumpft euch ja gegenseitig mit den größten und umfangreichsten PRs. :D
Ich schau mir das heute Abend in aller Ruhe an. :)
 
Hey, ich hab den pull-request geschlossen. Das war zu viel auf einmal :D
Ich werde stattdessen kleinere Anpassungen machen wie z.b. phan/php-cs-fixer einbauen und dann sehen wir weiter.
 
Why? Jetzt war ich gerade mitten im Review. :D

Soweit ich bisher alles durchgeschaut habe, ist die grundlegende Idee sowie der neue Aufbau des Codes wirklich eine lohnenswerte Änderung, die den Code deutlich übersichtlicher macht und professionalisiert. :)
Ich will auf keinen Fall, dass deine Arbeit jetzt verloren geht.
Es mag sein, dass der PR ein bisschen aus den Nähten platzt. Das ist aber doch kein Grund, die Arbeit jetzt einfach fallen zu lassen. :unsure:
 
Alles gut, gibt schon wieder nen neuen pull-request :D
Ich denke, dass es besser ist kleinere Schritte zu machen.
 
asc hatte zu viel Kaffee. Der läuft mit einer weit höheren Taktrate als wir.

Ich glaube auch. :LOL:

Alles gut, gibt schon wieder nen neuen pull-request :D
Ich denke, dass es besser ist kleinere Schritte zu machen.

Oh, je. Das PR-Rad dreht sich weiter. :D

Ja, gut. Kleinere Schritte schaden erstmal nicht.
Der Code ist ja noch da und geht nicht verloren. Dann können wir das in aller Ruhe Stück für Stück einbauen. :)
 
Kann es sein, dass da jemand mächtig Langeweile hat?! :LOL:

Den Code Parser PR hast du ja auch nochmal ordentlich überarbeitet. Nicht schlecht.
Wirkt so, als würde dir der Code praktisch in einem Strom aus den Fingern fließen. 😛

Vielen Dank für den PR! Das ist definitiv PHP fortgeschrittener Natur. (y)
Schau mir das gerade an und stolpere erstmal über Dinge wie yield und iterable.
Na ja, man lernt ja nie aus. :)
 
Zurück
Oben Unten