2012-01-17 17 views
10

El compilador JDT de Eclipse proporciona una interfaz INameEnvironment que define el método findType(...) que le permite hacer una compilación en cascada. Curiosamente, me gustaría saber si hay algún medio para hacerlo utilizando el kit de herramientas estándar para el compilador JDK.Compilación en memoria en cascada con javax.tool

Nota, el escenario es un motor de plantillas, que se puede hacer en la compilación de memoria para las clases generadas archivo de plantilla que tienen interdependencias, y no se puede predecir el orden en que se encontró con un archivo de plantilla, por lo tanto Foo poder necesita ser compilado primero antes de que sea el padre Bar ya compilado, por lo tanto, se necesita un mecanismo para hacer la compilación en cascada, es decir, durante la compilación de Foo que necesita para generar otra fuente Bar y compilar en primer lugar con el fin de continuar la compilación Foo 's: un código como el siguiente manera:

private NameEnvironmentAnswer findType(final String name) { 
    try { 
     if (!name.contains(TemplateClass.CN_SUFFIX)) { 
      return findStandType(name); 
     } 

     char[] fileName = name.toCharArray(); 
     TemplateClass templateClass = classCache.getByClassName(name); 

     // TemplateClass exists 
     if (templateClass != null) { 

      if (templateClass.javaByteCode != null) { 
       ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true); 
       return new NameEnvironmentAnswer(classFileReader, null); 
      } 
      // Cascade compilation 
      ICompilationUnit compilationUnit = new CompilationUnit(name); 
      return new NameEnvironmentAnswer(compilationUnit, null); 
     } 

     // So it's a standard class 
     return findStandType(name); 
    } catch (ClassFormatException e) { 
     // Something very very bad 
     throw new RuntimeException(e); 
    } 
} 

Respuesta

2

Según nuestra conversación de comentarios, creo que la respuesta es clara: no, no se puede hacer eso con el compilador JDK. Le da un gancho cuando solicita el paquete, pero no la dependencia de clase específica.

lo más cerca que se puede llegar tan lejos como lo que se es:

Here's a nice article con código pesar de que tiene que ser adaptado para manejar en las clases de memoria. Específicamente, el problema que está describiendo se maneja mediante el método JavaFileManager.list(...). Tienes que devolver JavaFileObjects aquí que has guardado en la memoria. Lo más probable es que necesite crear una subclase de ForwardingJavaFileManager como se describe en el artículo, aunque modificada para manejar las clases en caché con las que está trabajando.

Puede usar eso para compilar algo. Si devuelve errores, use expresiones regulares para averiguar qué falta. Después de generar/compilar el código de la falla, vuelva a intentar compilar el código original.

NOTA: Solicita el FQN de la clase dependiente como el argumento packageName en ForwardingFileManager.list (...) en algún momento. No he intentado devolver la clase en ese punto. Puede que no funcione porque el paquete no coincidiría, pero quizás lo haría.

+0

El punto de 'INameEnvironment.findType()' de JDT es que me permite hacer una compilación en cascada, por ejemplo, tengo la clase 'Foo' que depende de la clase' Bar'. Y mi aplicación intenta compilar 'Foo' antes de compilar' Bar', así durante la compilación de 'Foo' puedo implementar una lógica para generar el código fuente de' Bar' y compilarlo y luego continuar la compilación de 'Foo'. ¿Es este tipo de cosas factible con 'ForwardJavaFileManager'? –

+0

Es posible que pueda implementar ese tipo de cosas además de lo que describo. Hago algo similar. Si obtengo ciertos errores, uso la expresión regular para averiguar qué falta y generar/compilar un talón para ella. Pero si estás diciendo que JDT te da ganchos justo en el medio de la compilación para encontrar los símbolos que faltan, no creo que Javac lo tenga disponible. O bien tiene que resolverlo de antemano, o con el error, o la 'lista (...) 'llamada es para un paquete, por lo que si sabe que una solicitud para un determinado paquete significa que tiene que generar algo, entonces puede poner allí la compilación en cascada. – mentics

+0

hmm ... probablemente no sea el camino para que vaya. El punto es cuando compilo B, encontré que A falta, no solo falta la clase A, pero el código fuente tampoco está listo, necesito generar el código fuente A desde un archivo de plantilla [a]. La llamada 'findType' de JDT encaja perfectamente para las necesidades. –

1

Intente leer este ejemplo HelloWorld para ver si resuelve su problema. Sin publicar el código, es difícil decir cuál es su problema específico.

+0

Aquí está el caso. Supongamos que tiene 2 cadenas de código fuente para compilar. Uno es "paquete foo; public class One {...}" y el otro es "package bar; import foo.One; public class Two {...}". Todo está bien hasta que comience a compilar la segunda clase "Dos". El compilador informará que foo.One no pudo ser localizado. –

+0

Ya veo. Dejaré esto y buscaré una mejor solución. Parece que necesitas algún tipo de cargador de clases de URL. –

+0

Así que renuncio al compilador estándar JDT dom y termino con ECJ. ¿Tiene algún hallazgo nuevo? –

Cuestiones relacionadas