advice: Java code generation for custom language plugin

Hi, I'm working on a plugin for a custom language that produces Java source files for execution. Our translator/compiler is a jar-based one, and thus far I've managed to get application run configs working for our custom (.resolve) filetypes. That is, by right clicking on our files, I can simply run our compiler's jar on the source and output to the terminal any errors etc. To get this working, I've extended 'JavaCommandLineState' and implemented the 'createJavaParameters()' method and all seems well there. However, now I'm at the step where I would like to be able to write print statements within my language's files and see the output in the same terminal view -- that is, execute my compiler's generated files.

Here is what I would like to know:
1. my run configs work on .resolve files that have a 'main' function defined. I've added an output directory field to my run configuration's UI which serves as the -o <directory> command passed to my compiler. What I'm wondering is, since I'm automatically generating these filled-in run configurations, is there a 'best' place output my generated java sources? Preferably in an 'out-of-sight-out-of-the-way-location'.. ?

2. Once these generated sources are written to whereever, how do I go about executing them, and where should that execution logic be performed? I've read snippets of posts around here saying your can do things post process execution (i.e. somehow 'after' JavaCommandLineState is done). Do I need to override something else in my class extending JavaCommandLineState? How would I get the results of execution similarly displaying in the terminal (for instance, if someone wrote a print statement in their code).

Thanks for reading, let me know if you need additional information/details

9 comments
Comment actions Permalink

Looks like you actually need to implement a run configuration. Please refer to http://www.jetbrains.org/intellij/sdk/docs/basics/run_configurations.html and
http://www.jetbrains.org/intellij/sdk/docs/tutorials/run_configurations.html for more information on that.


0
Comment actions Permalink

Hi Dmitry,

I already have a custom run configurations for my language. Right now though the JavaCommandLineState class I'm extending simply 'compiles' whatever I had a run config for -- generating a whole new set of java classes (which I want to run automatically). You're saying should just manually create an entirely new run configuration for those generated files? I was kind of hoping that somehow after the process which compiles and runs my jar completes, I could somehow automatically (and internally) create this 'config' and run it in the same terminal view..

0
Comment actions Permalink

No, it looks like you should be doing the opposite thing - running your compiler outside of the run configuration itself (for exampe, as a before launch step), and using the run configuration to run the generated files themselves.

0
Comment actions Permalink

That makes sense, but I'm worried that I'll lose some of the cool stuff that I've already managed to accomplish by being able to run the compiler directly (for instance in attached screenshots: errors in the terminal). I would still be able to right click on my language's files and click run and get compiler feedback if I moved some logic to the before phase?

Sorry for my confusion, this all pretty new to me.



Attachment(s):
2.png
1.png
0
Comment actions Permalink

You'll be able to show errors in the Messages view, similar to how other languages show compilation errors in IntelliJ IDEA.

0
Comment actions Permalink

Sounds good Dmitry! By way of implementation, I've been looking at 'BeforeRunTaskProvider' and the 'BeforeRunTask' classes  -- are these the correct place to start looking at the sort of before task you're referring to?

If so, do you happen to know of any particular examples that do something similar in practice (i.e. codegen) to what I'm trying to achieve here? Thanks again.

0
Comment actions Permalink

It Or rather, instead of looking at 'BeforeRunTask' and 'BeforeRunTaskProvider', should I instead be looking at this CompilerManager class? It seems like that is somewhat more on track, as it has methods such as 'addTranslatingCompiler'...

http://grepcode.com/file_/repository.grepcode.com/java/ext/com.jetbrains/intellij-idea/12.0/com/intellij/openapi/compiler/CompilerManager.java/?v=source

0
Comment actions Permalink

Please don't use grepcode for accessing IntelliJ IDEA source code. Instead, use either a local checkout or https://upsource.jetbrains.com, which always contains an up to date version of the code, and provides many really nice navigation features.

The CompilerManager API does not exist in recent versions of IntelliJ IDEA. Instead, there's a separate external build system, called JPS. You can integrate with it if you really want to, but it's quite a bit more work than writing a before run task.

0
Comment actions Permalink

So what would you say is the best way to implement executeTask(..) of BeforeRunTaskProvider on a .jar? I've noticed there is indeed a subclass ExternalSystemBeforeRunTaskProvider with a 'basic' implementation of executeTask, should I instead be subclassing that?

Further, I'm pretty confused as to how I'm going to end up reconciling inputs and outputs here

1. someone creates a run config for a resolve file, specifying the resolve file they want on a FILENAME field -- say FILENAME=dan/IdeaProjects/untitled3/Foo.resolve

2. when they click play, the before run task executes my .jar, and takes as input the FILENAME specified

3. my .jar finishes its processing and writes, say 4 .java classes to a folder somewhere like 'generated-sources/', where one of the files generated is named Foo.java

4. Now what? What would actually run the java? Would my implementation of the run configuration somewhere implicitly be hardcoded to search the generated-sources directory for a file named Foo.java (and how would I get that? Just strip the original .resolve extension from FILENAME?) and execute that?

Just trying to understand

0

Please sign in to leave a comment.