2010-02-25 14 views
11

lo tanto, aquí es una pieza de código usando CodeModel que genera el código de Java:Edición/modificación de un archivo .java mediante programación? (No el archivo .class)

JCodeModel cm = new JCodeModel(); 
    JDefinedClass dc = cm._class("foo.Bar"); 
    JMethod m = dc.method(0, int.class, "foo"); 
    m.body()._return(JExpr.lit(5)); 
    File f = new File("C:/target/classes"); 
    f.mkdirs(); 
    cm.build(f); 

Este código genera un archivo .java:

package foo; 
public class Bar { 

     int foo() { 
     return 5; 
    } 
} 

Sin embargo, NO DOY Quiero CodeModel para crear un nuevo archivo java para mí. Ya tengo un archivo .java y me gustaría agregar algunas líneas de código a un método dentro de él. Por lo tanto, me gustaría que la API modifique directamente el archivo java/cree una copia modificada de este. ¿Hay alguna manera de hacer esto?

+0

Tener clases parciales [de C#] en java ayudará en cierta medida ... – Fakrudeen

+0

@Fakrudeen Elabore. – Jay

+0

C# permite que las definiciones de clase abarquen múltiples archivos. Si los cambios son solo aditivos, puede definirlos [generar] en un archivo diferente, en lugar de modificar el archivo existente. Todo esto es discutible para ti, ya que Java no tiene clases parciales. Es por eso que lo agregué como comentario. – Fakrudeen

Respuesta

10

Sé que ha pasado un tiempo desde la publicación original, pero una de las bibliotecas de transformación de Java que parecen más accesibles parece ser Spoon.

Desde el Spoon Homepage:

cuchara permite transformar (véase más adelante) y analizar (ver ejemplo) código fuente. Spoon proporciona un metamodelo Java completo y fino donde se puede acceder a cualquier elemento del programa (clases, métodos, campos, declaraciones, expresiones ...) tanto para lectura como para modificación. Spoon toma como código fuente de entrada y produce el código fuente transformado listo para ser compilado.

Actualización: Square también han creado la biblioteca de generación JavaPoet código fuente, la API fluida parece bastante simple de entender.

+1

ni siquiera recuerdo por qué hice esta pregunta :). Gracias por responder de todos modos. ¡Estoy recompensando su respuesta! – Jay

+1

¿Puede leer JavaPoet en el código fuente existente? No puedo encontrar ninguna mención de esto en skimming JavaPoet README.md. – JohnC

+1

@JohnC, lo siento, no he usado JavaPoet con ira, pero por lo que puedo deducir, Spoon parece ajustarse mejor a tus necesidades. No hay razón para no combinar las 2 bibliotecas para modificación y generación pura (es decir, la herramienta adecuada para el trabajo correcto). –

2

Realmente va a necesitar un análisis completo del código que desea modificar para asegurarse de insertar el código en la ubicación correcta. Pensé que tu mejor opción sería utilizar una herramienta de análisis sintáctico existente que permita reescribir el código, en lugar de intentar hacer algo a mano.

El Eclipse IDE hace algo como esto para admitir la refactorización de código. Este article puede ser útil.

-1

Lo que quiere es un program transformation system. Esta es una herramienta que analiza su archivo fuente y puede aplicar transformaciones para modificarlo, y regenera el código fuente con las modificaciones.

un sistema de transformación de fuente a fuente acepta reglas de la forma de:

lhs -> rhs if cond 

donde los LHS y rhs son patrones souce para fragmentos válidos de la lengua y la cond cheques que la regla es segura de aplicar (Considere "? X /? X -> 1 si? X ~ = 0"; necesita la condición para verificar que la división sea válida).

Una de estas herramientas es nuestra DMS Software Reengineering Toolkit. DMS tiene analizadores frontales C, C++, C#, Java, COBOL, Python, PHP y ECMAScript completos (como muchos otros idiomas menos conocidos) y puede aplicar dichas reglas directamente. DMS también proporciona construcción de tablas de símbolos y análisis de flujo de datos y control, ya que a menudo son útiles para definir un cond para reglas complejas. Si lo desea, también puede recurrir a una interfaz de procedimientos "estándar" para visitar los nodos de los árboles y modificar los AST.

+0

@Ira gracias. Sin embargo, estoy buscando usar material de código abierto, no comercial. – Jay

+0

Bueno, puede probar TXL http://www.txl.ca o Stratego http://www.strategoxt.org, que también son sistemas de transformación de programas que tienen reglas de reescritura de fuente a fuente. Lo que no tienen, lo que creo es fundamentalmente necesario para la transformación de los lenguajes de procedimiento, es la tabla de símbolos y las herramientas de análisis de flujo. Hemos encontrado que estos son indispensables para hacer una transformación de programas confiable a gran escala. Puede intentar implementarlo usted mismo en las herramientas OSS, pero es mucho trabajo. YMMV. –

+0

Wow. Respuesta de 7 años, que aborda la pregunta de OP que incluye directamente alternativas de código abierto cuando OP lo dejó en claro en su comentario ... ¿y * ahora * dibuja votos a la baja? No creo que los downvoters estén dispuestos a explicar por qué downvoted. –

2

... Me gustaría que la API modifique directamente el archivo java/cree una copia modificada de este. ¿Hay alguna manera de hacer esto?

JavaParser es una API que le permite leer en archivos Java, modificarlos y obtener los resultados como una Cadena.

Más específicamente, JavaParser analiza el archivo y construye un AST (árbol de sintaxis abstracta). A continuación, puede modificar el JavaParser AST que representa su código fuente utilizando la API y recuperar la representación de cadenas del AST.

Ya tengo un archivo .java y me gustaría agregar algunas líneas de código a un método dentro de él.

He aquí un ejemplo del uso de javaparser añadir una línea en el extremo de un cuerpo de método e imprimir el resultado:

class MyClass { 
    public static void someMethod() { 
     /* ... */ 
     // Lines will be added here: 
    } 

    public static void main(String[] args) { 
     String newStatement = "System.out.println(\"Hello world!\");" 
     File myClassSourceFile = new File("MyClass.java"); 
     CompilationUnit cu = JavaParser.parse(myClassSourceFile); 
     ClassOrInterfaceDeclaration classDeclaration = cu.getClassByName("MyClass").get(); 
     MethodDeclaration method = classDeclaration.getMethodsByName().get(0); 
     method.getBody().get().addStatement(newStatement); 

     // Print out the resulting Java source code. 
     System.out.println(cu.toString()); 
    } 
} 

CompilationUnit - De javadoc de javaparser, "Esta clase representa la compilación completa unidad. Cada archivo java denota una unidad de compilación ".

NOTA: En su código, querrá reemplazar las llamadas Option.get() con el manejo opcional adecuado.

+1

Su respuesta no me dejó claro si el código fuente generado será el original pero con modificaciones localizadas. La pregunta requiere modificaciones mínimas, probablemente para evitar muchos conflictos de control de versiones. – neves

Cuestiones relacionadas