tutorial software renault fungicida examples constructora blanquerna scala

software - ¿Cómo agregar una nueva clase en un plugin de compilación Scala?



scala tutorial (1)

El código fuente completo está aquí: https://gist.github.com/1794246

El truco es almacenar los ClassDef s recién creados y usarlos al crear un nuevo PackageDef . Tenga en cuenta que debe tratar tanto con símbolos como con árboles: un símbolo de paquete es solo un identificador. Para generar código, debe generar un AST (al igual que para una clase, donde el símbolo contiene el nombre y tipo de clase, pero el código está en los árboles de ClassDef ).

Como ha señalado, las definiciones de los paquetes están más arriba del árbol que las clases, por lo que tendría que volver a recurrir primero (suponiendo que genere la nueva clase de una clase existente). Luego, una vez que se cruzan los subárboles, puede preparar un nuevo PackageDef (cada unidad de compilación tiene una definición de paquete, que por defecto es el paquete vacío) con las nuevas clases.

En el ejemplo, suponiendo que el código fuente es

class Foo { def foo { "spring" } }

el compilador lo envuelve en

package <empty> { class Foo { def foo { "spring" } } }

y el complemento lo transforma en

package <empty> { class Foo { def foo { "spring" } } package mypackage { class MyClass extends AnyRef } }

En un complemento de compilación de Scala, intento crear una nueva clase que implemente un rasgo preexistente. Hasta ahora mi código se ve así:

def trait2Impl(original: ClassDef, newName: String): ClassDef = { val impl = original.impl // Seems OK to have same self, but does not make sense to me ... val self = impl.self // TODO: implement methods ... val body = impl.body // We implement original val parents = original :: impl.parents val newImpl = treeCopy.Template(impl, parents, self, body) val name = newTypeName(newName) // We are a syntheic class, not a user-defined trait val mods = (original.mods | SYNTHETIC) &~ TRAIT val tp = original.tparams val result = treeCopy.ClassDef(original, mods, name, tp, newImpl) // Same Package? val owner = original.symbol.owner // New symbol. What''s a Position good for? val symbol = new TypeSymbol(owner, NoPosition, name) result.setSymbol(symbol) symbol.setFlag(SYNTHETIC) symbol.setFlag(ABSTRACT) symbol.resetFlag(INTERFACE) symbol.resetFlag(TRAIT) owner.info.decls.enter(symbol) result }

Pero parece que no se agrega al paquete. Sospecho que es porque en realidad el paquete se "atravesó" antes del rasgo que causa la generación, o porque el método "anular la transformación de def (árbol: árbol): árbol" de TypingTransformer solo puede devolver un árbol, por cada árbol que recibe, por lo que no puede producir un nuevo Árbol, sino solo modificar uno.

Entonces, ¿cómo se agrega una nueva Clase a un paquete existente? Tal vez funcionaría si transformara el paquete cuando lo obtenga "transform (Tree)", pero ese punto aún desconozco el contenido del paquete, por lo que no puedo generar la nueva Class tan temprano (¿o podría?) . ¿O tal vez está relacionado con el parámetro "Posición" del Símbolo?

Hasta ahora he encontrado varios ejemplos en los que se modifican Árboles, pero ninguno en el que se crea una Clase completamente nueva en un Complemento de compilación.