Wie erzeuge ich in einem Scala-Compiler-Plugin neuen Quellcode in Textform?

8

Ich habe gerade die erste Version eines Java-6-Compiler-Plugins fertiggestellt, das automatisch Wrapper (Proxy, Adapter, Delegate, wie Sie wollen) basierend auf einer Annotation erzeugt.

Da ich gemischte Java / Scala-Projekte mache, möchte ich in der Lage sein, die gleiche Anmerkung in meinem Scala-Code zu verwenden und denselben generierten Code zu erhalten (außer natürlich in Scala). Das bedeutet im Grunde genommen von vorne anzufangen.

Was ich gerne machen würde, und für das ich noch kein Beispiel gefunden habe, ist, wie ich den Code in einem Scala-Compiler-Plugin auf die gleiche Weise wie im Java-Compiler-Plugin erzeuge. Das heißt, ich finde, wo meine Annotation verwendet wird, erhalte die AST für die annotierte Schnittstelle und frage dann die API, mir einen Stream / Writer zu geben, in dem ich den generierten Scala-Quellcode unter Verwendung der String-Manipulation .

Dieser letzte Teil ist was ich nicht finden konnte. Wie kann ich der API mitteilen, dass sie eine neue Scala - Quelldatei erstellen soll, und mir einen Stream / Writer / Datei / Handle geben, damit ich sie einfach schreiben kann, und wenn ich fertig bin, kompiliert der Scala - Compiler sie innerhalb der der gleiche Lauf, in dem das Plugin aufgerufen wurde?

Warum sollte ich das tun? Erstens, weil beide Plugins die gleiche Struktur haben, so ist die Wartung einfach. Zweitens möchte ich es öffnen, und es gibt einfach keine Möglichkeit, jede Option zu unterstützen, die irgendjemand möchte, also erwarte ich, dass potentielle Benutzer die Generation mit ihrem eigenen Code erweitern wollen. Das wird für sie viel einfacher, wenn sie nur ein wenig printf () machen müssen, anstatt die AST API zu lernen (das gilt auch für mich).

    
Sebastien Diot 02.10.2011, 10:12
quelle

2 Antworten

5

Kurze Antwort:

Es kann nicht gemacht werden

Lange Antwort:

Sie könnten Ihre Quelldatei möglicherweise erzeugen und durch eine Parser-Instanz in Ihrem Plugin pushen. Aber in keiner Weise dürfte das für Sie von Nutzen sein, weil Sie jetzt ein größeres Problem haben, mit dem Sie sich auseinandersetzen müssen:

Um alle Typ- / Nameninformationen zum Generieren des Delagates / Proxys zu erhalten, müssen Sie den AST des annotierten Typs aufheben, nachdem er sowohl die Namen- als auch die Tippphase durchlaufen hat (die untrennbar sind). Der Haken dabei ist, dass bei Versuchen, den generierten Code aufzurufen, die Typprüfung fehlgeschlagen ist, der Compiler einen Fehler ausgelöst hat und alle weiteren Wetten deaktiviert sind.

Die Methodensynthese ist in begrenzten Fällen möglich, solange Sie den Typchecker nur lange genug täuschen können, damit Ihr Code generiert wird. Dies ist der Trick, den ich mit meinem Autoproxy 'Lite' Plugin . Selbst dann ist es viel besser, mit TreeDSL zu arbeiten, um Code zu erzeugen, anstatt die rohe Quelle auszupumpen.

    
Kevin Wright 02.10.2011, 20:26
quelle
1

Kevin ist völlig richtig, aber nur der Vollständigkeit halber ist es erwähnenswert, dass es eine andere Alternative gibt - schreiben Sie ein Compiler-Plugin, das die Quelle generiert. Dies ist der Ansatz, den ich in Borachio angenommen habe. Es ist keine sehr befriedigende Lösung, aber es kann zum Funktionieren gebracht werden.

Bearbeiten - Ich habe Ihre Frage gerade noch einmal gelesen und festgestellt, dass Sie tatsächlich danach fragen, ob Sie eine Quelle generieren möchten

Es gibt also keine direkte Unterstützung dafür, aber es geht im Grunde nur darum, eine Datei zu öffnen und die relevanten "print" -Aussagen zu schreiben. Es gibt keine Möglichkeit, den Compiler "innerhalb" eines AFAIK-Plugins aufzurufen, aber ich habe ein sbt-Plugin geschrieben, das sich versteckt die meiste Komplexität des Aufrufs des Compilers zweimal.

    
Paul Butcher 17.10.2011 08:21
quelle