How to use a Compiler interface

Hello,

I am developing a plugin where I need to instrument some classes after they are compiled.
What I have done so far:

1. registered my +ClassInstrumentingCompiler +with CompilerManager

2. in ClassInstrumentingCompiler.+getProcessingItems +I return items (files) which need to be instrumented with corresponding ValidityState

2. in ClassInstrumentingCompiler.process I instrument my classes, but before I need to recompile some of them (basically to get rid of previous intrumentation if some meta data has been changed). The problem is in that step. Inside the process I just call:


But it complains that it needs to be called from inside EDT. I wonder why? I am already in the compiler thread, am I not?
Anyway if I put it inside EDT by calling ApplicationManager.invokeAndWait (I can't really use invokeLater, because this whole chain of compilers will be broken?) then it seems that


is running asynchronously in another thread (not in EDT). Here is the execution sequence how it seems to be working:


How I expect it to work:


I am a little bit confused. How to implement this properly?
Thanks!

6 comments

Hello,

The Native2Ascii plugin - is a Compiler. But it not an instrumenting compiler. Anyways, you can use it as example. Source available with plugin and on: http://idea-trinkets.googlecode.com/svn/trunk/native2ascii/

Thanks!

0

Hello Priscilla,

Basically, what you are trying to do is to call the compiler reentrantly
(invoke another chain of compiler calls while one is in progress). That is
not supported. You can do one of the following things instead:
- implement the logic to remove existing instrumentation in your instrumenter
- invoke javac from your compiler to recompile the classes
- register a compiler that will run before IDEA's javac (for example, a SourceGeneratingCompiler)
and do a no-op generation that will update the validity state of the source
file and cause IDEA's javac to recompile it.

PH> I am developing a plugin where I need to instrument some classes
PH> after they are compiled. What I have done so far:
PH>
PH> 1. registered my +ClassInstrumentingCompiler +with
PH> CompilerManager
PH>
PH> 2. in ClassInstrumentingCompiler.+getProcessingItems +I
PH> return items (files) which need to be instrumented with
PH> corresponding ValidityState
PH>
PH> 2. in ClassInstrumentingCompiler.process I instrument my
PH> classes, but before I need to recompile some of them (basically to
PH> get rid of previous intrumentation if some meta data has been
PH> changed). The problem is in that step. Inside the process I
PH> just call:
PH>
PH>

 CompilerManager.getInstance(project).compile(VirtualFile[], null,
PH> false);
PH> ]]>

PH> But it complains that it needs to be called from inside EDT. I
PH> wonder why? I am already in the compiler thread, am I not? Anyway if
PH> I put it inside EDT by calling
PH> ApplicationManager.invokeAndWait (I can't really use
PH> invokeLater, because this whole chain of compilers will be broken?)
PH> then it seems that
PH>
PH>

 CompilerManager.getInstance(project).compile(VirtualFile[], null,
PH> false);
PH> ]]>

PH> is running asynchronously in another thread (not in EDT). Here is
PH> the execution sequence how it seems to be working:
PH>
PH>

 process
PH> invokeAndWait
PH> runWriteAction
PH> compile  // gets executed in another thread thus exiting
PH> immediatedly
PH> my bytecode instrumentation  // it breaks here because
PH> compile step is not finished yet
PH> ]]>

PH> How I expect it to work:
PH>
PH>

 process
PH> invokeAndWait
PH> runWriteAction
PH> compile  // gets executed in this thread and finishes
PH> when compilation is done
PH> my bytecode instrumentation
PH> ]]>

PH> I am a little bit confused. How to implement this properly? Thanks!
PH>
--
Dmitry Jemerov
Software Developer
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Dmitry,

Thanks for your advice, but it is still unclear how to do that.

- implement the logic to remove existing instrumentation in your instrumenter


Unfortunately I have no control over it, it's a third party instrumenter, I am just trying to integrate it with IDEA

- invoke javac from your compiler to recompile the classes


It may solve the problem, but users who use jikes or eclipse compiler will not be happy

- register a compiler that will run before IDEA's javac (for example, a SourceGeneratingCompiler) and do a no-op generation that will update the validity state of the source file and cause IDEA's javac to recompile it.


How does it work? I mean how do I tell IDEA to recompile it? I looked at the code and some examples, but it seems that every compiler somewhat independent from each other. If I set validity state of a file then how IDEA's Java compiler picks it up? I have no way to pass validity from one compiler to another, have I?

I also tried to delete classes (.class) in SourceGeneratingCompiler, but Java compiler did not pick them up. It seems to me that at this point it already made up its electronic mind on which classes should be recompiled and which not.

Thanks!

Priscilla

0

Thanks Alexey, but unfortunately it did not help.

Priscilla

0

Hello Priscilla,

I consulted with my colleagues, and they suggested one more solution: you
can keep copies of .class files in the state before you instrumented them.
Then, you either run your instrumentation on the .class passed to you (if
it's newer than your saved copy) or on your saved copy.

>> - register a compiler that will run before IDEA's javac (for example,
>> a SourceGeneratingCompiler) and do a no-op generation that will
>> update the validity state of the source file and cause IDEA's javac
>> to recompile it.
>>
PH> How does it work? I mean how do I tell IDEA to recompile it? I
PH> looked at the code and some examples, but it seems that every
PH> compiler somewhat independent from each other. If I set validity
PH> state of a file then how IDEA's Java compiler picks it up? I have no
PH> way to pass validity from one compiler to another, have I?
PH>
PH> I also tried to delete classes (.class) in SourceGeneratingCompiler,
PH> but Java compiler did not pick them up. It seems to me that at this
PH> point it already made up its electronic mind on which classes should
PH> be recompiled and which not.
PH>
PH> Thanks!
PH>
PH> Priscilla
PH>
--
Dmitry Jemerov
Software Developer
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Dmitry,

Do you have any suggestions where do I keep copies of .class files if I am to implement this?

Basically I need a way to trigger recompilation of a java class even when it (.java) has not been changed. And I mean recompilation by standard IDEA compiler. One obvious way is to delete .class file in one of the pretranslator compiler (SourceGenerating or SourceInstrumenting) does not seem to be working. Is there any other way?

Thanks!

0

Please sign in to leave a comment.