2012-01-17 11 views
10

Il compilatore JDT di Eclipse fornisce un'interfaccia INameEnvironment che definisce il metodo findType(...) che consente di eseguire la compilazione in cascata. Curiosamente vorrei sapere se ci sono mezzi per farlo usando il toolkit standard del compilatore JDK?Compilazione in memoria in cascata con javax.tool

Nota, lo scenario è un motore di template, che fare la compilazione memoria per classi generate file di modello che hanno interdipendenze, e non può prevedere l'ordine che avete incontrato un file di modello, quindi Foo forza deve essere compilato prima prima che sia genitore Bar compilato già, pertanto è necessario un meccanismo per fare la compilazione a cascata, cioè durante la compilazione di Foo è necessario generare un'altra fonte Bar e compilarlo prima al fine di continuare la compilazione s' Foo: un po' di codice simile al seguente:

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); 
    } 
} 

risposta

2

Sulla base della nostra conversazione di commento, penso che la risposta sia chiara: no, non è possibile farlo con il compilatore JDK. Ti dà un gancio quando richiede il pacchetto, ma non la dipendenza specifica della classe.

quanto di più vicino si può ottenere per quanto ne so è:

Here's a nice article con il codice se deve essere adattato per gestire in classi di memoria. In particolare il problema che stai descrivendo è gestito dal metodo JavaFileManager.list(...). Devi restituire JavaFileObjects qui che hai memorizzato nella cache. È molto probabile che sia necessario creare una sottoclasse di ForwardingJavaFileManager come descritto nell'articolo, anche se modificata per gestire le classi memorizzate nella cache con cui si sta lavorando.

È possibile utilizzarlo per compilare qualcosa. Se restituisce errori, usa regex per scoprire cosa manca. Dopo aver generato/compilato il codice per la cosa mancante, riprovare a compilare il codice originale.

NOTA: Richiede l'FQN della classe dipendente come argomento packageName in ForwardingFileManager.list (...) a un certo punto. Non ho provato a restituire la classe a quel punto. Potrebbe non funzionare perché il pacchetto potrebbe non corrispondere, ma forse lo sarebbe.

+0

Il punto di 'INameEnvironment.findType()' di JDT è che mi consente di eseguire la compilazione in cascata, ad esempio, ho una classe 'Foo' che dipende dalla classe' Bar'. E la mia app tenta di compilare 'Foo' prima che venga compilato' Bar', quindi durante la compilazione di 'Foo' posso implementare una logica per generare il codice sorgente di' Bar' e compilarlo e quindi continuare la compilazione di 'Foo'. Questo tipo di cose è fattibile con 'ForwardJavaFileManager'? –

+0

Potrebbe essere in grado di implementare quel tipo di cosa in cima a ciò che descrivo. Faccio qualcosa di simile. Se ottengo determinati errori, io uso regex per scoprire cosa manca e generare/compilare uno stub per questo. Ma se stai dicendo che JDT ti dà degli aggetti nel bel mezzo della compilation per trovare i simboli mancanti, non penso che Javac abbia quello disponibile. Dovete o capirlo in anticipo, o con l'errore, o la lista '(...) 'call è per un pacchetto, quindi se sai che una richiesta per un determinato pacchetto significa che devi generare qualcosa, allora potresti inserire la cascata qui. – mentics

+0

hmm ... probabilmente non è il modo per me di andare. Il punto è quando compilo B, ho trovato A mancante, non manca solo la classe A, ma anche il codice sorgente non è pronto, ho bisogno di generare il codice sorgente A da un file modello [a]. La chiamata 'findType' di JDT si adatta perfettamente alle esigenze. –

1

Prova a leggere questo esempio HelloWorld per vedere se risolve il tuo problema. Senza pubblicare il codice, è difficile dire qual è il tuo problema specifico.

+0

Ecco il caso. Supponiamo di avere 2 string di codice sorgente da compilare. Uno è "pacchetto foo; public class One {...}" e l'altro è "pacchetto bar; import foo.One; public class Two {...}". Tutto va bene fino a quando non inizia la compilazione della seconda classe "Due". Il compilatore segnalerà che foo.One non può essere localizzato. –

+0

Capisco. Lascerò perdere e cercherò una soluzione migliore. Sembra che tu abbia bisogno di una sorta di classloader di URL. –

+0

Quindi rinuncio al compilatore JDT standard e termina con ECJ. Hai delle nuove scoperte? –