2016-02-03 10 views
12

Ziel ist es, JSDoc-Dokumentation aus TypeScript-Code zu erhalten. Die Qualität der Dokumentation von TypeDoc (TypeScript-Dokumentationslösung) ist nicht akzeptabel, da die Dokumentation auf JS-Benutzer ausgerichtet ist und nicht mit Details überflutet werden sollte, die spezifisch für die TypScript-Implementierung (Schnittstellen usw.) sind.TypeScript streift Kommentare ab und verdirbt JSDoc-Dokumentation

Das Übertragen auf ES6 und das Generieren der Dokumentation aus JS-Dateien führen den größten Teil dazu aus. Bis auf die Eigenschaften, denen keine Werte zugewiesen sind. Wie es scheint,

class A { 
    /** 
    * @private 
    * @var _a 
    */ 
    private _a; 

    /** 
    * @public 
    * @var a 
    */ 
    public a = true; 
} 

wird transpiled zu

class A { 
    constructor() { 
     /** 
     * @public 
     * @var a 
     */ 
     this.a = true; 
    } 
} 

Während ich so etwas wie

class A { 
    constructor() { 
     /** 
     * @private 
     * @var _a 
     */ 

     /** 
     * @public 
     * @var a 
     */ 
     this.a = true; 
    } 
} 

oder

class A { 
    /** 
    * @private 
    * @var _a 
    */ 

    constructor() { 
     /** 
     * @public 
     * @var a 
     */ 
     this.a = true; 
    } 
} 

Wie können Kommentare (besonders JSDoc) erwarten vorgesehen sein für nicht zugeordnete Klassenmitglieder in TypeScript? Gibt es einen Trick, der dazu führen könnte, dass die Kommentare bestehen bleiben (auch wenn private _a; im transpilierten Code nicht vorhanden ist)?

+0

Darf ich fragen, warum Sie diese Funktionalität benötigen? Sicherlich gibt es Tricks und Workarounds, um diese Kommentare zu behalten, aber derzeit sehe ich absolut keinen Grund dafür. –

+1

@JohnWhite Ich habe keine gute Möglichkeit gefunden, JSDoc-Dokumentation in TypeScript anders als von transpiliertem ES6 zu generieren. Und mit dieser Art von Verhalten bleibt ein Bündel von Eigenschaften undokumentiert. – estus

Antwort

1

Umgehung:

class A { 
    /** 
    * @private 
    * @var _a 
    */ 
    private _b = undefined; 

    /** 
    * @public 
    * @var a 
    */ 
    public a = true; 
} 

[Playground]

Frage:

Wie können Kommentare (insbesondere JSDoc) für nicht zugeordnete Klassenmitglieder in Typoskript zur Verfügung gestellt werden?

Wenn Sie einen Blick auf den Quellcode für Konstruktor Generation:

  • emitConstructor [line]
  • |--- emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false)); [line]
  • |------ getInitializedProperties [line]

Sie können sehen, es ist nicht möglich le, um das Verhalten anzupassen.

Vorhandene Instrumente zur Dokumentation Generation

Hardcore Ansatz:

Typoskript bietet Compiler API: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API. Möglicherweise können Sie den Quellcode durchqueren und die Dokumentation erstellen, die Sie mögen.

+0

Ja, danke, das ist die Lösung. Aber es wird eine beträchtliche Menge an Junk-Code produzieren (und kann möglicherweise "in" und "hasOwnProperty" Teile brechen). – estus

+0

Können Sie zu Ihrer Frage die gewünschte Ausgabe hinzufügen? –

3

Gibt es einen Trick, der dazu führen könnte, dass die Kommentare erhalten bleiben?

Sie wollen das fast gar nicht. Beispielsweise erzeugt der folgende Code keine Ausgabe:

/** an interface */ 
interface Q { } 

Wenn der Compiler die Dokumentation zu erhalten, würden sie in vielen (fast allen) Fällen überflüssig und irreführend sein. Wenn das über einem class C erschien, dann scheint das Dokument für die Klasse zu gelten (noch verwirrender, wenn diese Klasse keine eigenen Dokumente hatte). Wenn ich das Beispiel in Ihrer Frage gelesen hätte, würde ich mich fragen, ob this.a tatsächlich @private war, wie das erste Dokument behauptet, oder @public. Es gibt keinen richtigen Weg für andere Programmierer und für Ihre Werkzeuge, diese streunenden Dokumente zu interpretieren.

Der Compiler behält die Dokumente bei, wenn eine direkte Entsprechung zwischen TS und JS besteht, und zwar ausschließlich deshalb, weil es keinen Schaden verursacht (obwohl es sehr wenig Dienstprogramm gibt). Aber es sollten und sollten Dokumente nicht beibehalten, die von dem Code getrennt sind, auf den sie angewendet werden.

Der beste Ort, um sich Dokumente anzusehen, ist direkt in der TypeScript-Quelle (in Ihrem Editor oder über Quellkarten). Es ist die TypeScript-Datei, die Ihre Quelle ist, nicht die emittierte JS: Verwenden Sie a TypeScript doc generator. Kompilierter oder transpilierter Code ist kein nützlicher Ort für Dokumente, und die Übertragung der speziellen Dokumente, nach denen die Frage fragt, wäre irreführend.

+0

Das mag stimmen, aber ich will das sicher. Die Frage bezieht sich in erster Linie auf JSDoc-Kommentare. Sie sind für Dokumentationsleser gedacht, die keine Codeleser sein müssen. Wenn Sie sie in transpiliertes JS einfügen, können Sie die JSDoc-Dokumentation generieren und nicht lesen. Beachten Sie die Verwendung des @ var-Tags. Es wurde speziell dort platziert, um zu helfen, dass verschobene Kommentare richtig analysiert werden. – estus

+0

Sie schreiben eine JS-Bibliothek in TS und Sie möchten nur JS-Dokumente - vollkommen in Ordnung. Sie hoffen, dass der TS-Compiler Code auf eine Art und Weise ausgibt, die Ihre Problemumgehung beim Lesen des transpilierten JS mit JSDoc erleichtert. Das tut es nicht, und ich stimme zu, dass es enttäuschend ist, aber manchmal ist die hilfreichste Antwort nur "du kannst nicht" (aber ich konnte nur das nicht posten). Versuchen Sie nicht, den Compiler zu ändern, sondern eine Anfrage mit dem TypeDoc-Projekt für ein Flag, das Docs für das Typoskript auslässt, einzureichen. Scheint wie eine vernünftige Anfrage. Und dann brauchst du die redundanten '@ public' oder' @var' nicht. –

1

Gibt es einen Trick, der dazu führen könnte, dass die Kommentare erhalten bleiben?

Etwas. Sie können den Standardkonstruktor explizit angeben und die ansonsten gelösten Kommentare anhängen. Wechsel:

class MyClass { 
    /** 
    * @private 
    * @var _a 
    */ 
    private _a; 

    /** 
    * @private 
    * @var _b 
    */ 
    private _b; 
} 

zu:

class MyClass { 
    /** 
    * @private 
    * @var _a 
    */ 

    /** 
    * @private 
    * @var _b 
    */ 

    constructor() {} 

    private _a; 

    private _b; 
} 

Das wird die Ausgabe von ändern:

var MyClass = (function() { 
    function MyClass() { 
    } 
    return MyClass; 
})(); 

zu:

var MyClass = (function() { 
    /** 
    * @private 
    * @var _a 
    */ 
    /** 
    * @private 
    * @var _b 
    */ 
    function MyClass() { 
    } 
    return MyClass; 
})(); 

das ist genau das, was Sie wollen. Dies ist der "sauberste Trick", der gefunden werden kann.

+0

Danke für den Vorschlag, so verletzt den Stil, aber ist als temporäre Lösung zulässig, bis es in TypeScript selbst aussortiert wird. – estus

+0

Dies ist bestenfalls eine Teillösung. Nehmen Sie die Ausgabe, die im letzten Code-Snippet gezeigt wird, und fügen Sie einfach die erforderliche '/ ** @class * /' vor 'MyClass' hinzu und bearbeiten Sie dann mit jsdoc. In der Dokumentation erhalten Sie die Klasse, aber keine Eigenschaften. jsdoc kann die Doclets, die Teil des IIFE sind, nicht verwenden. Um von jsdoc verwendet zu werden, müssten sie das '@ name'-Tag haben, um einen vollständigen Namen zu erhalten, der sie zu Mitgliedern von' MyClass' macht. – Louis

0

definieren _a als nicht definiert, wie folgt aus:

class A { 
    /** 
    * @private 
    * @var _a 
    */ 
    private _a = undefined; 

    /** 
    * @public 
    * @var a 
    */ 
    public a = true; 
} 

diese kompiliert

class A { 
    constructor() { 
     /** 
     * @private 
     * @var _a 
     */ 
     this._a = undefined; 
     /** 
     * @public 
     * @var a 
     */ 
     this.a = true; 
    } 
} 

Edit:

Wenn Sie, dass hasOwnProperty genau gleich verhalten wollen löschen _a im Konstruktor :

class A { 
    /** 
    * @private 
    * @var _a 
    */ 
    private _a = undefined; 

    /** 
    * @public 
    * @var a 
    */ 
    public a = true; 

    constructor() { 
     delete this._a; 
    } 
} 

diese kompiliert

var A = (function() { 
    function A() { 
     /** 
     * @private 
     * @var _a 
     */ 
     this._a = undefined; 
     /** 
     * @public 
     * @var a 
     */ 
     this.a = true; 
     delete this._a; 
    } 
    return A; 
}());