Custom TargetBuilder.build implementation never gets called
Hello,
I am trying to create a plugin for an assembler language. The editor integration went well, but now I am trying to integrate the assembling into IntelliJ. I've created a new module, implemented the BuildService, Builder, BuildTarget, BuildTargetLoader, BuildTargetType and BuildRootDescriptor. However the Builder's build method never gets called. The targets seem to be created just fine.
The plugin: https://github.com/patrick246/intellij-digital-plugin/tree/feature/jps-build
Regards,
Patrick
Please sign in to leave a comment.
Hi Patrick,
My experiments with the code show that the builder is registered correctly and at least its "buildStarted()" method is called.
I would pay attention to the implementation of "DABuildTargetType.computeAllTargets()".
Looks like its intended behavior is to scan module's content roots, find '*.dasm' files and for each such file create a DABuildTarget() object.
Even if I create a file named "test.dasm" under some module's content root, this code returns 0 targets.
This explains why the "build()" method is not called.
Another (unrelated) problem: I also noticed that all DABuildTarget objects share the same targetId. If more than 1 target can be created for a project, this will cause problems.
Best regards,
Eugene.
btw, feel free to use https://github.com/JetBrains/gradle-grammar-kit-plugin for generating lexer/parser with JFlex/GrammarKit
@Eugene Zhuravlev: Thanks for the hint. The problem was the endsWith, which operates differently on a Path object than one would expect (matches path parts, not string parts). After converting the Path to a string, it works as intended.
However, build still doesn't get called, because it fails the check if it is affected. This is because in CompileScopeImpl myFiles is empty and myTypes only contains Java build target types (java-test and java-production). How do I get my target types to be affected?
I also fixed the ID not being unique, thanks for pointing that out, I would probably have missed that.
@Alexandr Evstigneev: Thanks, but I am already using it, at least I thought. Or have I overlooked something?
Why do you need jflex.jar in your repo then?
> still doesn't get called, because it fails the check if it is affected. This is because in CompileScopeImpl myFiles is empty and myTypes only contains Java build target types
A code that launches jps build, should specify what targets should be built. This is done by specifying a list of TargetTypeBuildScope objects. In the IDE this is performed in the actions that initiate a build session: Build, Rebuild project, Build module etc. All these actions "know" about predefined build targets and project structure and plugin can extend this list by defining a com.intellij.compiler.impl.BuildTargetScopeProvider. Such providers are called at the moment when compilation scope is formed, allowing the plugin to augment the scope with its targets.
There is one alternative that will be suitable for most plugins and which makes things a bit easier. If jps plugin declares targets that are closely tied to a project structure, then basing your target implementation on a ModuleBasedTarget might be a good idea. Such targets are automatically included in the compilation scope, when their corresponding module is affected. So whenever standard build actions (which work on project and modules) are called in the IDE, there is no need to register a separate target scope provider for that. I would consider implementing your build target as a ModuleBasedTarget for that reason. There are also some additional considerations why this could be a good idea:
1. According to the code, your build targets are "naturally" strongly connected with modules, because target set is calculated based on project structure.
2. Currently there is a "target-per-file" logic, which looks like a "too granular" approach to me. BuildTarget is a build stage, which exists in a build process, no matter has a project files to be built or not. During project life files are created, changed, moved, deleted, but build targets should stay the same. Otherwise it is not possible to provide incremental build experience. I think that MavenResourcesTarget can serve as a good code example and a starting point for your build target: it reflects most of functionality that is important to your plugin. (at least it seems to me so after looking at the code)
3. Basing on a ModuleBasedTarget will give you some functionality "for free", like "affected scopes" behavior mentioned above