I'm trying to build my own custom line marker for Clion following this tutorial - https://plugins.jetbrains.com/docs/intellij/line-marker-provider.html . My question is about the language attribute on the extension tag in the plugin.xml file ...
<extensions defaultExtensionNs="com.intellij">
<codeInsight.lineMarkerProvider language="JAVA"
implementationClass="org.intellij.sdk.language.SimpleLineMarkerProvider"/>
</extensions>
When i add this extension the language="JAVA" gets highlighted in red. What plugin/dependency do i need to add for this to be resolved?
My IDE is also not able to resolve PsiIdentifier and PsiMethod from the provided snippet ...
public class MyCorrectLineMarkerProvider implements LineMarkerProvider {
public LineMarkerInfo getLineMarkerInfo(#NotNull PsiElement element) {
if (element instanceof PsiIdentifier && element.getParent() instanceof PsiMethod) return new LineMarkerInfo(element, ...);
return null;
}
}
This is what my build.gradle looks like, i know there are some other dependencies i need to add but the tutorial i've been following isn't very clear about it.
plugins {
id 'org.jetbrains.intellij' version '1.2.0'
id 'java'
}
group 'com.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version = '2021.2.2'
}
runIde {
jvmArgs '--add-exports', 'java.base/jdk.internal.vm=ALL-UNNAMED'
}
patchPluginXml {
changeNotes = """
Add change notes here.<br>
<em>most HTML tags may be used</em>"""
}
test {
useJUnitPlatform()
}
You have to add a dependency on the java plugin in your build.gradle, like so
intellij {
plugins = ['java']
}
See the IntelliJ Dev Guide for more information on plugin dependencies.
The tutorial you are following is meant for adding support for a new language, instead you are adding a line marker to Java (existing language :p). Plugin dependencies are simply outside the scope of that tutorial.
Related
In a regular build script you can easily use extensions on Project like Project.sourceSets, for example build.gradle.kts:
sourceSets {
main {
...
}
}
But when I am developing a Gradle plugin in my buildSrc module, I cannot access these. For example:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
class ExamplePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.sourceSets { // error because `sourceSets` can't be resolved.
}
}
}
This is happening despite including the kotlin-gradle-plugin module in my buildSrc dependencies:
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
}
So, how can I access these extensions from within my Gradle plugin?
class ExamplePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.configure<JavaPluginExtension> {
sourceSets {
println(names)
}
}
}
}
See additional notes here: https://docs.gradle.org/current/userguide/kotlin_dsl.html#project_extensions_and_conventions
Basically for plugins, or other times when the plugins applied are not known, the accessors (sourceSets, configurations, etc) of extensions added by other plugins will need to go through a method call which sort of 'retrieves' that scope or object. Further down the link there is also an example of how to get tasks created by other plugins:
val test by target.tasks.existing(Test::class)
test.configure { useJUnitPlatform() }
// or
val test by target.tasks.existing(Test::class) {
useJUnitPlatform()
}
note that if the 'sourceSet' object does not exist on the project (because the java plugin was not applied), an exception will be thrown .
tested with gradle version 7.2, kotlin-dsl version 2.1.6
I need to apply a gradle plugin, in this case errorprone from a custom Gradle plugin.
My Plugin has a build.gradle that looks like this:
gradlePlugin {
plugins {
myErrorprone {
id = 'my-errorprone'
implementationClass = 'com.my.MyErrorpronePlugin'
}
}
}
And the plugin code is:
public class MyErrorpronePlugin implements Plugin<Project> {
List<String> compilerArgs =
Arrays.asList(
"-XepExcludedPaths:.*/proto/.*|.*/protoGeneratedSrc/.*",
"-XepDisableWarningsInGeneratedCode");
#Override
public void apply(Project project) {
project.getPluginManager().apply("net.ltgt.errorprone:");
for (JavaCompile task : project.getTasks().withType(JavaCompile.class)) {
task.getOptions().setCompilerArgs(compilerArgs);
}
}
}
Then, when in another project I apply this plugin (after getting the dependencies in the buildscript)
like this:
apply plugin: 'my-errorprone'
A problem occurred evaluating root project 'my-project.
Failed to apply plugin [id 'my-errorprone']
Plugin with id 'net.ltgt.errorprone' not found.
And it only resolved if i add to buildscript classpath
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.16"
How can I make my plugin work in such way that the project that consumes my plugin will not have to add this direct dependency in the classpath in "net.ltgt.gradle:gradle-errorprone-plugin:0.0.16" ?
In order to solve it, one should apply the plugin by class rather than by ID. This will force you to include error prone dependency in your plugin’s dependency list as it won’t compile until you add the dependency.
import net.ltgt.gradle.errorprone.ErrorPronePlugin.class;
public class MyPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPluginManager().apply(ErrorPronePlugin.class);
// custom logic here
}
}
and in the build.gradle file:
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
api "net.ltgt.gradle:gradle-errorprone-plugin:1.1.1"
}
I found the answer in Gradle's forum under this topic:
https://discuss.gradle.org/t/apply-a-gradle-plugin-errorprone-from-a-custom-gradle-java-plugin/34645/4
I really would like to appreciate Gradle 5 especially in combination with the new Kotlin DSL, but I’m having a very hard time to get (in my eyes) a very, very simple and common build running with Gradle.
Task
Release a Java library with several interdependent submodules in Maven default directory layout as high-quality Maven artifacts/repository in a to-the-point, simple Gradle build (i.e. DRY).
Therefore: Have a root project as umbrella which defines & contains all the common configuration (practically all except the real dependencies).
My current struggles
I ported my current "results" to a sample project on Github and asked this question in the Gradle forum already.
Currently I'm failing to declare the necessary task to provide standard -sources and -javadoc artifacts in my central build.
For example these three "solutions" which you'll find on looking for a Kotlin DSL based solutions all do no (longer) work in a multi-module scenario:
https://stackoverflow.com/a/48070667
https://stackoverflow.com/a/52596969/1237653
and even the offical "Maven Publish" documentation is only working in a single-module scenario.
Incomplete solution (/build.gradle.kts)
Complete example see on Github: https://github.com/bentolor/gradle-maven-multimodule-kotlindsl
subprojects {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
// Dependencies used in EVERY module
"compile"("commons-logging:commons-logging:1.2")
"testImplementation"("junit:junit:4.12")
}
tasks {
// not working
/*register("sourcesJar", Jar::class.java) {
from(sourceSets.main.get().allJava)
classifier = "sources"
}*/
// not working, eiher
/* task<Jar>("sourcesJar") {
from(sourceSets.main.get().allJava)
classifier = "sources"
} */
}
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// won't work, beause inaccessible declaration in `tasks{}`-Block
//add("archives", javadocJar)
//add("archives", sourcesJar)
}
}
repositories {
mavenLocal()
}
}
}
Example submodule /module2/build.gradle.kts
group = "de.bentolor.sampleproject.module2"
dependencies {
compile(project(":module1"))
}
Try this:
subprojects {
apply<JavaLibraryPlugin>()
apply<MavenPublishPlugin>()
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
val implementation by configurations
val testImplementation by configurations
implementation("commons-logging:commons-logging:1.2")
testImplementation("junit:junit:4.12")
}
// This will work, but as long as these tasks are need only for publishing you can declare them inplace later where you need
// tasks {
// val sourcesJar by creating(Jar::class) {
// val sourceSets: SourceSetContainer by project
// from(sourceSets["main"].allJava)
// classifier = "sources"
// }
// val javadoc by getting(Javadoc::class)
// val javadocJar by creating(Jar::class) {
// from(javadoc)
// classifier = "javadoc"
// }
// }
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// If you configured them before
// val sourcesJar by tasks.getting(Jar::class)
// val javadocJar by tasks.getting(Jar::class)
val sourcesJar by tasks.creating(Jar::class) {
val sourceSets: SourceSetContainer by project
from(sourceSets["main"].allJava)
classifier = "sources"
}
val javadocJar by tasks.creating(Jar::class) {
from(tasks.get("javadoc"))
classifier = "javadoc"
}
artifact(sourcesJar)
artifact(javadocJar)
}
}
}
}
A few notes:
Why use String-based apply, when you can do a type-safe apply<T>()?
Why use invokes on stings in dependencies, when you can use delegates, which is less hacky and better refactorable.
Consider using implementation instead of compile
Why sourceSets is not working in a multi-module project?
When you're using Kotlin DSL it generates accessors for projects based on the applied plugins. It's a two-step process: first Gradle processes plugins (that's why it's recommended to put them in plugins block) and generates accessors and then you can use them in your code (accessors are generated as Kotlin extensions for Project, NamedDomainObjectContainer and so on). But if you're configuring subprojects there are two issues:
Parent project evaluates before child, so the extensions for child are not known in parent.
The set of plugins applied to parent and child is different and you need to use children accessors in parent.
sourceSets is one of the accessors generated by Kotlin DSL for children. And it's just not available in parent. You can try it yourself: apply only java plugin in subprojects. sourceSets will be available in children build scripts, but not in parent.
This is also why you can use java in children, but have to use configure<JavaPluginExtension> when configuring it in parent.
But you can use delegates to get references for domain objects, like tasks, source sets, configuration and so on.
I have a distributes projects with different sub-projects and I want to accomplish the following:
(root)
client
module A
module B
module C
model
I want to put
protoc {
artifact = 'com.google.protobuf:protoc:3.5.0'
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.7.0"
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
} }
dependencies {
compile "com.google.api.grpc:proto-google-common-protos:1.0.0"
compile "io.grpc:grpc-netty:1.7.0"
compile "io.grpc:grpc-protobuf:1.7.0"
compile "io.grpc:grpc-stub:1.7.0"
}
for module A, B and C.
For now I have the following in my root build.gradle
subprojects{
apply plugin: 'java'
sourceCompatibility = 1.8
group 'project'
version '0.0.1-SNAPSHOT'
jar {
manifest {
attributes 'Main-Class': "com.project.${project.name}.App"
}
doFirst {
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.9.5'
}
}
So every sub-project use java plugin, and has the defines dependencies and jar task.
How can I only put the first block for some sub-projects ?
I tried using a variable like in Multi-project Builds - Gradle but I couldn't access it in subprojects block.
Thank you in advance. I'm really interested in using Gradle correctly and it's a bit hard to get into it outside of simple Android/Java projects. Feel free to include any documentations I should read :)
Edit:
Thank you. I wouldn't have posted here if I hadn't search before. Apparently I was missing the keyword "subset" who would have gave me the solution you linked.
A solution is described here: https://discuss.gradle.org/t/configure-only-subset-of-subprojects/5379/3
You can run configure() with a list of projects.
project.ext {
subprojectList = subprojects.findAll{
it.name == 'subprojectA' ||
it.name == 'subprojectB' ||
it.name == 'subprojectC'
}
}
configure(project.subprojectList) {
// insert your custom configuration code
}
or
configure([project(':a'), project(':b'), project(':c')]) {
// configuration
}
Just wanted to include the lombok plugin with my gradle build but get the error message from the title. My build.gradle looks like this:
...
plugins {
id 'net.ltgt.apt' version '0.10'
}
ext {
lombok_version="1.16.18"
}
lombok {
version = ${lombok_version}
sha256 = ""
}
...
dependencies {
...
compileOnly "org.projectlombok:lombok:${lombok_version}"
apt "org.projectlombok:lombok:${lombok_version}"
...
}
Source: https://projectlombok.org/setup/gradle
Any ideas what's wrong here? If I remove the lombok {...} part everything works fine.
According to the documentation you should use either
lombok {
version = "1.16.18"
sha256 = ""
}
or
dependencies {
compileOnly 'org.projectlombok:lombok:1.16.18'
apt "org.projectlombok:lombok:1.16.18"
}
Disclosure: I am a lombok developer.