<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: alaje</title>
    <description>The latest articles on DEV Community by alaje (@alaje).</description>
    <link>https://dev.to/alaje</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F694734%2F3251038c-6734-4dec-a136-4def6aa47c9d.png</url>
      <title>DEV Community: alaje</title>
      <link>https://dev.to/alaje</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alaje"/>
    <language>en</language>
    <item>
      <title>JetBrains IDE Plugin Development: Migrating from Gradle IntelliJ Plugin to IntelliJ Platform Gradle Plugin</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Tue, 28 Jan 2025 15:33:55 +0000</pubDate>
      <link>https://dev.to/alaje/jetbrains-ide-plugin-development-moving-from-gradle-intellij-plugin-to-intellij-platform-gradle-30gm</link>
      <guid>https://dev.to/alaje/jetbrains-ide-plugin-development-moving-from-gradle-intellij-plugin-to-intellij-platform-gradle-30gm</guid>
      <description>&lt;p&gt;The title of this article is not more confusing than suddenly upgrading your IntelliJ IDEA version and discovering all the reds in your plugin project. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm024qflrumds3987cko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm024qflrumds3987cko.png" alt="Errors in project" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffc1jy3dfw8jkagcuhg2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffc1jy3dfw8jkagcuhg2m.png" alt="More errors in project" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, I knew something had changed, but I didn’t know exactly what. When I finally discovered the cause, fixing it was just a matter of following the &lt;a href="https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Update the &lt;code&gt;plugins&lt;/code&gt; block in your build.gradle file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"java"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.kotlin.jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.9.21"&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.intellij.platform"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"2.2.1"&lt;/span&gt; &lt;span class="c1"&gt;// [visit here to see latest version](https://github.com/JetBrains/intellij-platform-gradle-plugin/releases)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've replaced &lt;code&gt;id("org.jetbrains.intellij") version "1.16.1"&lt;/code&gt; because as of version 2, the IntelliJ plugin now goes by the name &lt;em&gt;IntelliJ Platform Gradle Plugin.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add the migration plugin
&lt;/h2&gt;

&lt;p&gt;Me thinking I was in the clear after step 1: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqov06mpi0l0z4p2ajdae.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqov06mpi0l0z4p2ajdae.gif" alt="Smiling gif" width="250" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then this happened:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fem39pg5lf75sysozg4jq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fem39pg5lf75sysozg4jq.png" alt="Still errors after first step" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the documentation said that there were significant breaking changes, I should have expected it; I really should have. I carried my sorry self back to the documentation and discovered that the team over at JetBrains was so helpful that they provided another plugin to help us through the migration. How sweet of them! (Sarcasm, for all my folks on the slower side). I mean, I was dreading what was to come now. If they went the mile to provide an entire plugin to help, does it not mean the worst? &lt;/p&gt;

&lt;p&gt;So, let’s update the &lt;code&gt;plugins&lt;/code&gt; block again with our new plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.intellij.platform"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"2.2.1"&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.intellij.platform.migration"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"2.2.1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Replace the &lt;code&gt;intelliJ&lt;/code&gt; block
&lt;/h2&gt;

&lt;p&gt;We got &lt;code&gt;Unresolved reference: intellij&lt;/code&gt;  for our &lt;code&gt;intelliJ&lt;/code&gt; block is because the &lt;code&gt;intelliJ&lt;/code&gt; block has now been replaced with the &lt;code&gt;intellijPlatform&lt;/code&gt; block. When we load the new script configuration and then sync our Gradle changes, we now see that the migration plugin is doing its thing already.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feypucjh0t3zuu7w895fo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feypucjh0t3zuu7w895fo.png" alt="Suggestion from migration plugin" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It tells us we should do a couple of things instead. How it’s rendered in the pop-up isn’t making the migration plugin’s suggestion as helpful as it is, so I’ve copied it below so that we can make sense of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
Define the IntelliJ Platform dependency in `dependencies {}` block instead:
repositories {
    mavenCentral()
    intellijPlatform {
        defaultRepositories()
    }
}
dependencies {
    intellijPlatform {
        create(type, version)
    }
}
IntelliJ Platform Extension: https:// plugins. jetbrains. com/ docs/ intellij/ tools-intellij-platform-gradle-plugin-dependencies-extension.
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can see what we have to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add the &lt;code&gt;intellijPlatform&lt;/code&gt; blocks
&lt;/h2&gt;

&lt;p&gt;We must add two types of &lt;code&gt;intellijPlatform&lt;/code&gt; blocks, one for the repository and another for the dependencies.&lt;/p&gt;

&lt;p&gt;In the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;defaultRepositories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2024.1.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values I passed into the create function are the same values that were previously being set for the version and type in the old &lt;code&gt;intelliJ&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;intellij&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2024.1.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Target IDE Platform&lt;/span&gt;

    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Add &lt;code&gt;plugins&lt;/code&gt; and &lt;strong&gt;&lt;code&gt;bundledPlugins&lt;/code&gt;&lt;/strong&gt; functions
&lt;/h2&gt;

&lt;p&gt;At this point, I was facing my last red line. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2z84d967628s9bmtt5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2z84d967628s9bmtt5g.png" alt="More warnings from migration plugin" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After formatting the migration plugin’s suggestion, this is what we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Using 'plugins: ListProperty&amp;lt;Any&amp;gt;' is an error. 
Define dependencies on plugins or bundled plugins in `dependencies {}` block 
instead: 
repositories { 
    mavenCentral() 
    intellijPlatform { 
        defaultRepositories() 
    } 
} 

dependencies { 
    intellijPlatform { 
        plugins(providers.gradleProperty("platformPlugins").map { 
            it. split(',') 
        }) 
        bundledPlugins(providers.gradleProperty("platformBundledPlugins").map { 
            it. split(',') 
        }) 
    }
} 

Note that bundled plugins are now separated from plugins available in JetBrains 
Marketplace. 
IntelliJ Platform Extension: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html 
Migration guide: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s clear that our &lt;code&gt;intellij.plugins&lt;/code&gt; is no longer available, but even though we know what to do, we need to understand why we now have two functions to add.&lt;/p&gt;

&lt;p&gt;An IntelliJ IDE comes with bundled plugins, which are plugins out of the box, and then we have plugins that don’t come with an IntelliJ IDE, so if you want to use them, you have to get them from, say, the &lt;a href="https://plugins.jetbrains.com" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt;.  Before IntelliJ Platform Gradle Plugin, you declared your plugins the same way irrespective of their source, but now you actually have to determine which of your plugins are bundled or not and then use either the &lt;code&gt;plugins&lt;/code&gt; function or the &lt;code&gt;bundledPlugins&lt;/code&gt; function for them.&lt;br&gt;
The arguments: &lt;code&gt;providers.gradleProperty("platformPlugins").map {          it. split(',')}&lt;/code&gt; and &lt;code&gt;providers.gradleProperty("platformBundledPlugins").map {it. split(',')}&lt;/code&gt; being passed into the functions in the snippet above is simply a way to access your list of plugins from your project’s &lt;a href="http://gradle.properties" rel="noopener noreferrer"&gt;gradle.properties&lt;/a&gt; file and then transform it into an appropriate value. So, unless your plugins are defined in your gradle.properties file, we can ignore that.&lt;/p&gt;

&lt;p&gt;I had three plugins in my project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="s"&gt;"com.intellij.java"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s"&gt;"org.jetbrains.kotlin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s"&gt;"Dart:241.15989.9"&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Already, I knew which ones came with IntelliJ and which ones I had to get from the Marketplace. You can quickly know which is which when testing your IDE plugin in the IDE development instance, because you don’t have to install the bundled plugins for the target IDE. Another way to know this is by running the &lt;code&gt;printBundledPlugins&lt;/code&gt; task to see all the bundled plugins for the IDE. Here are some of the ones packed into the IntelliJ IDEA Community Edition:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnynoxezs6cxulyrwsefv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnynoxezs6cxulyrwsefv.png" alt="List of bundled plugins" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now I have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"libs/svgSalamander-1.1.4.jar"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2024.1.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dart:241.15989.9"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;bundledPlugins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.intellij.java"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"org.jetbrains.kotlin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Do away with &lt;code&gt;patchPluginXml&lt;/code&gt;, &lt;code&gt;publishPlugin&lt;/code&gt; and &lt;code&gt;signPlugin&lt;/code&gt; tasks
&lt;/h2&gt;

&lt;p&gt;At this point, when building and running my plugin, it works!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j4cb3ipx616re0dquzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j4cb3ipx616re0dquzz.png" alt="Landing screen for dev IDE" width="800" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there’s this ugly warning the migration plugin was sharing whenever I ran my plugin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpx8escgvrixsl6y1dvxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpx8escgvrixsl6y1dvxc.png" alt="Ugly warning from migration plugin" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And reading through it, I saw it was more advice for the kind of changes I should make for my migration to 2.x, so of course, it made sense to do as instructed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;pluginConfiguration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;publishing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;signing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem was that after I added the above code, the migration plugin didn’t offer any further steps. I didn’t know what was supposed to go into my functions. The IDE's suggestions helped me guess what went where, but I wanted either the docs or the migration plugin to tell me exactly what to do. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf93iz5cxmftrln5ku4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf93iz5cxmftrln5ku4z.png" alt="Suggestions from IDE" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the migration plugin wasn’t doing that, I went back to the documentation, but that specific migration documentation page did not provide the answer. It instead redirected me to the &lt;a href="https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html" rel="noopener noreferrer"&gt;IntelliJ Platform Extension&lt;/a&gt; page, where I saw this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;buildSearchableOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;instrumentCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;projectName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
  &lt;span class="n"&gt;sandboxContainer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"..."&lt;/span&gt;

  &lt;span class="nf"&gt;pluginConfiguration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;publishing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;signing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;pluginVerification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we go on, you should see what my tasks block for my free plugin was looking like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;buildSearchableOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the JVM compatibility versions&lt;/span&gt;
    &lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;JavaCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
        &lt;span class="n"&gt;targetCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jetbrains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;KotlinCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kotlinOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;patchPluginXml&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinceBuild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"241"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;signPlugin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;certificateChain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CERTIFICATE_CHAIN"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PRIVATE_KEY"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PRIVATE_KEY_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;publishPlugin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PUBLISH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, on that site’s page, we didn’t have one exact place to see what we had to change into what, so reading through was a must. Finally, we ended up several changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move buildSearchableOptions to the &lt;code&gt;intellijPlatform&lt;/code&gt; top-level function&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;patchPluginXml&lt;/code&gt; **task and add the &lt;code&gt;sinceBuild&lt;/code&gt; with the &lt;code&gt;ideaVersion&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;signPlugin&lt;/code&gt; task and add the &lt;code&gt;certificateChain&lt;/code&gt; , &lt;code&gt;privateKey&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; with the &lt;code&gt;signing&lt;/code&gt; function instead&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;publishPlugin&lt;/code&gt; **task and add the &lt;code&gt;token&lt;/code&gt; with the &lt;code&gt;publishing&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buildSearchableOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;

    &lt;span class="nf"&gt;pluginConfiguration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;ideaVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sinceBuild&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"241"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;publishing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PUBLISH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;signing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;certificateChain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CERTIFICATE_CHAIN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PRIVATE_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PRIVATE_KEY_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set the JVM compatibility versions&lt;/span&gt;
    &lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;JavaCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
        &lt;span class="n"&gt;targetCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jetbrains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;KotlinCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kotlinOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"17"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, it turns out the ugly warning is still there:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pebz3nu53okn14574fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pebz3nu53okn14574fa.png" alt="Ugly warning still there after change" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But by now, I think it’s just the migration plugin guy acting up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Remove the &lt;code&gt;setupDependencies&lt;/code&gt; task (Optional)
&lt;/h2&gt;

&lt;p&gt;Just because I don’t like ignoring warnings, I went a step further to respond to this warning from the migration plugin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmc76ayzuddq2rmsyg3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmc76ayzuddq2rmsyg3b.png" alt="Warning about setupDependencies" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;setupDependencies&lt;/code&gt; task is no longer required in 2.x, so I removed it per the steps outlined in &lt;a href="https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html#z7qba6_173" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5vk01uk0321hxga19wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5vk01uk0321hxga19wl.png" alt="Steps to remove setupDependencies" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpb06nsqx4e7ctw6n4jf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpb06nsqx4e7ctw6n4jf.png" alt="Removing setupDependencies" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The last thing I did was remove the migration plugin, and c’est fini! I successfully migrated my IntelliJ IDE plugin project to the IntelliJ Platform Gradle Plugin (I think 🤔). Overall, I don’t think the migration plugin was helpful much since I still had to rely on the documentation to carry out many of the changes. The experience would have been much better if quick fixes had been incorporated into it. &lt;em&gt;All in all, all’s well that ends well.&lt;/em&gt; I hope this helped!&lt;br&gt;
Kindly take note that these steps should work for free plugins, but if your plugin is of the paid or freemium type, extra steps that were not covered in this article are required.&lt;/p&gt;

</description>
      <category>gradle</category>
      <category>jetbrains</category>
      <category>help</category>
    </item>
    <item>
      <title>Jetpack Compose Tidbits: The first dance with JC - Learning the steps</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Wed, 29 Dec 2021 12:07:16 +0000</pubDate>
      <link>https://dev.to/alaje/jetpack-compose-tidbits-the-first-dance-with-jc-learning-the-steps-1pgi</link>
      <guid>https://dev.to/alaje/jetpack-compose-tidbits-the-first-dance-with-jc-learning-the-steps-1pgi</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt4syb8sjljkluxc9vhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt4syb8sjljkluxc9vhc.png" alt="A dancing female image by Gordon Johnson" width="469" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;Image by&lt;/sup&gt; &lt;a href="https://pixabay.com/users/gdj-1086657/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=5437872" rel="noopener noreferrer"&gt;&lt;sup&gt;Gordon Johnson&lt;/sup&gt;&lt;/a&gt; &lt;sup&gt;from&lt;/sup&gt; &lt;a href="https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=5437872" rel="noopener noreferrer"&gt;&lt;sup&gt;Pixabay&lt;/sup&gt;&lt;/a&gt; &lt;/p&gt;




&lt;p&gt;With Android's fresh way of developing UI, there's little to no XML which was formerly the primary way of designing UI for Android apps. With &lt;a href="https://developer.android.com/jetpack/compose/documentation" rel="noopener noreferrer"&gt;Jetpack Compose&lt;/a&gt;, you just declare what you need for creating your UI by calling functions and Jetpack Compose handles the implementation. When you need your UI to reflect come changes with the user's data, the functions you created just get called again with the new data. &lt;br&gt;
Jetpack Compose comes with Android Jetpack, a collection of software components launched in 2018 that work to make developing Android apps easier and more efficient. Before JC, using views was the primary way of creating UI in Android, thus, many of the apps already existing are built with views, that is why Compose can exist in harmony with views so you can be sure that you don't need to throw away all your old code with views when starting out with Compose. Instead, you can make the shift to Compose in a way that suits you best. &lt;/p&gt;

&lt;p&gt;If you've ever programmed with Flutter, chances are, you're going to fit right in with Jetpack Compose since Compose comes with a reactive style of programming.&lt;/p&gt;


&lt;h2&gt;
  
  
  Setting up the dance floor
&lt;/h2&gt;

&lt;p&gt;To get started with Compose you must have &lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;Android Studio Arctic Fox&lt;/a&gt;. &lt;br&gt;
After downloading Android Studio and successfully launching it, we can create a new compose project by clicking &lt;em&gt;New Project&lt;/em&gt;,&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1er12gced4fl7vee6tu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1er12gced4fl7vee6tu.png" alt="Android studio click new project" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then click &lt;em&gt;Empty Compose Activity&lt;/em&gt; to start creating your Compose app, &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F624tbm6ykzfxlxlpelm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F624tbm6ykzfxlxlpelm8.png" alt="Android Studio select empty compose activity" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A pop-up titled "Empty Compose Activity" appears, and we can go ahead to change our project's name to something more fitting: &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsos1vmz77cgor88odn38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsos1vmz77cgor88odn38.png" alt="create compose activity" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The save location is where your project will locally be stored on your machine, and the package name uniquely identifies your app. The value supplied for the save location will be slightly different depending on your choices when installing Android Studio, and although you can change it and the package name, it would be better to leave it as is since the explanation given from this point is done in accordance with these exact values. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgf6xxwsnofxlqdq5n0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgf6xxwsnofxlqdq5n0r.png" alt="create a  compose project" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process is smooth and free of hitches if your internet connection is enabled and stable. &lt;br&gt;
If you were unable to follow along with the above steps, you can visit &lt;a href="https://developer.android.com/jetpack/compose/setup" rel="noopener noreferrer"&gt;Android developer's official site&lt;/a&gt; to see more info about the setup process.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting to know your partner, JC
&lt;/h2&gt;

&lt;p&gt;After Android Studio finishes setting up your project, you should have a file with the name &lt;code&gt;MainActivity.kt&lt;/code&gt; automatically shown in the editor window (the space available in Android Studio where the details of files are seen and interacted with). &lt;br&gt;
You should also be able to see this sample bit of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirstComposeAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;code snippet: 1.0&lt;/p&gt;

&lt;p&gt;This file belongs to the launching activity of your app called &lt;code&gt;MainActivity&lt;/code&gt;. The class name also points to this. An activity, is the primary component of any android app that involves continuous interaction with the user. It serves as the entry point of your app in which you can let the user interact with your app. It, most commonly, shows UI as a single screen in the app. A more in-depth explanation can be found in the &lt;a href="https://developer.android.com/reference/android/app/Activity" rel="noopener noreferrer"&gt;Android docs&lt;/a&gt;. &lt;code&gt;MainActivity&lt;/code&gt; is your launching activity because it was automatically set as so in the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; upon the creation of your project. &lt;code&gt;AndroidManifest.xml&lt;/code&gt; is a &lt;a href="https://developer.android.com/guide/topics/manifest/manifest-intro" rel="noopener noreferrer"&gt;manifest file&lt;/a&gt;. It describes your app to Android systems, therefore, every app project you create must have it. To see what the manifest file looks like, go into the project window and double-click the manifests directory:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flad0jlmewi9v1sya4cqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flad0jlmewi9v1sya4cqn.png" alt="android project window" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This opens up the manifest file in the editor window:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy8ck5k6y5qdstk2qptz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy8ck5k6y5qdstk2qptz.png" alt="manifest file android" width="800" height="430"&gt;&lt;/a&gt;&lt;br&gt;
The highlighted part focuses on &lt;code&gt;MainActivity&lt;/code&gt;. For an activity to be visible to the Android system, it must be declared in the manifest file using the &lt;code&gt;&amp;lt;activity&amp;gt;&lt;/code&gt; tag. And this piece of XML&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;intent-filter&amp;gt;
                &amp;lt;action android:name="android.intent.action.MAIN" /&amp;gt;

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;makes it the activity that the will be launched from the launcher screen.&lt;/p&gt;




&lt;p&gt;Back to this piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirstComposeAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've worked with views, the code should be slightly familiar. In here, our first visible step into compose starts from &lt;code&gt;setContent&lt;/code&gt; which has a &lt;code&gt;content&lt;/code&gt; parameter that takes in a composable function that returns &lt;code&gt;Unit&lt;/code&gt; as its argument. This content value becomes the root view of the given activity. &lt;br&gt;
Take a look at &lt;code&gt;setContent&lt;/code&gt;'s definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public fun ComponentActivity.setContent(
    ...
    content: @Composable () -&amp;gt; Unit
) {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before moving ahead, let's slide into what a composable function is.&lt;/p&gt;




&lt;p&gt;A Jetpack Compose app will primarily be made up of composable functions which serve as the building blocks of your app’s UI. You’ll create your UI With composable functions or composables for short. A composable function looks like any other normal function you can find in your code, except now it's marked with an&lt;br&gt;
annotation  @Composable. This annotation serves as a tag on your function that tells Compose that it is specially made for producing UI. Let's look at a very basic composable function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see the annotation @Composable, and as previously pointed out, this makes Greeting a composable function. Let's notice how we started our function name with a capital letter following a PascalCase format. &lt;a href="https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-api-guidelines.md" rel="noopener noreferrer"&gt;Anytime your composable function returns Unit, you are advised to use PascalCase in writing its name&lt;/a&gt;, and also to use a noun as the name. Focusing on the function we are calling next, Text(...), is a composable function that comes by default with Jetpack Compose. It prints the String value that was passed as an argument to its parameter "text" on-screen.&lt;br&gt;
We've passed in a string template that references the parameter &lt;em&gt;name&lt;/em&gt;, thus, whatever value will be called with Greeting will be what gets shown on-screen. &lt;br&gt;
The Text function’s declaration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
fun Text(
    text: String,
    ...
) {
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;If you’ve ever used views to create apps, this is similar to TextView.&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;Now that we know what composable functions are, let's waltz back into analyzing the piece of code in our &lt;code&gt;MainActivity.onCreate&lt;/code&gt; method.&lt;/p&gt;




&lt;p&gt;From here, our next step comes with &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; which provides our app's theme. We can use a theme to style our app by providing a pool of colors, typography, and shapes that we can use to not only fuse our brand into the app but also grant it a uniform look and feel that looks aesthetically pleasing and is also coherent. Jetpack Compose provides &lt;code&gt;MaterialTheme&lt;/code&gt; as the default theming system, but for more control over our app's look an feel, we can choose to build something of our own from scratch.&lt;br&gt;
In our case &lt;code&gt;FirstComposeAppTheme&lt;/code&gt;, automatically created upon the creation of own new project, sits atop &lt;code&gt;MaterialTheme&lt;/code&gt;. &lt;br&gt;
See the definition of &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
fun FirstComposeAppTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -&amp;gt; Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette 
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's focus on the part about &lt;code&gt;MaterialTheme&lt;/code&gt;, where clearly, our &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; just wraps around &lt;code&gt;MaterialTheme&lt;/code&gt;.&lt;br&gt;
Now back to our code in our activity's onCreate function, we can see that &lt;code&gt;setContent&lt;/code&gt; is a &lt;a href="https://kotlinlang.org/docs/lambdas.html#lambda-expression-syntax" rel="noopener noreferrer"&gt;higher-order function&lt;/a&gt;, so is &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; and &lt;code&gt;Surface&lt;/code&gt; since they take in functions as parameters. Notice the &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; was passed as an argument to the content parameter, using the trailing lambda syntax. Composable, &lt;code&gt;Greeting&lt;/code&gt;, is called in the lambda passed into &lt;code&gt;Surface&lt;/code&gt; with the parameter "Android". Since we have “Hello $name” already set, this should later show "Hello Android" on-screen once it is run.&lt;br&gt;
The comment above the invocation of Surface,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// A surface container using the 'background' color from the theme
                Surface(color = ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;tells us that we are creating a surface container and passing in the background color set in our theme. &lt;br&gt;
This surface container is a Material surface, meaning that it follows Material Design language where it serves as a depiction of physical surfaces having attributes like color, elevation, opacity and shape. See it’s definition:&lt;br&gt;
@Composable&lt;br&gt;
fun Surface(&lt;br&gt;
    modifier: Modifier = Modifier,&lt;br&gt;
    shape: Shape = RectangleShape,&lt;br&gt;
    color: Color = MaterialTheme.colors.surface,&lt;br&gt;
    contentColor: Color = contentColorFor(color),&lt;br&gt;
    border: BorderStroke? = null,&lt;br&gt;
    elevation: Dp = 0.dp,&lt;br&gt;
    content: @Composable () -&amp;gt; Unit&lt;br&gt;
) {&lt;br&gt;
…&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;You might have noticed by now how a composable is passed into another composable as its &lt;code&gt;content&lt;/code&gt;'s argument. &lt;/p&gt;

&lt;p&gt;Treading down our &lt;code&gt;MainActivity&lt;/code&gt; file allows us to see the declaration of Greeting. Below it we can see another composable function &lt;code&gt;DefaultPreview&lt;/code&gt; which takes no parameter but instead has an extra annotation &lt;code&gt;Preview&lt;/code&gt;. The Android Studio you installed comes with a preview window that allows you to view the UI built by a composable. This &lt;code&gt;Preview&lt;/code&gt; annotation marks a function that contains no parameter to allow its UI be shown in the Android Studio preview.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Preview(showBackground = true)
@Composable fun DefaultPreview() {
    FirstComposeAppTheme {
        Greeting("Android")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cbemwf17piadz4h2iax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cbemwf17piadz4h2iax.png" alt="default preview android studio" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;DefaultPreview&lt;/code&gt; function, &lt;code&gt;FirstComposeAppTheme&lt;/code&gt; function is called and the same thing done in the &lt;code&gt;onCreate&lt;/code&gt; function of the MainActivity is repeated. We can pass in several arguments to &lt;code&gt;Preview&lt;/code&gt; that control how the UI created by the composable functions we call will look like in the preview window. For example, we can supply &lt;code&gt;showSystemUi = true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Preview(showBackground = true, showSystemUi = true )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the moment, we are only tweaking the values of &lt;code&gt;showBackground&lt;/code&gt; and &lt;code&gt;showSystemUi&lt;/code&gt;, to see more info about the annotation, place you mouse icon over the annotation text and wait for a pop-up to appear showing the documentation details of &lt;code&gt;Preview&lt;/code&gt;. If nothing appears, place your input cursor in the midst of its characters, go up to toolbar area, click &lt;strong&gt;View&lt;/strong&gt; &amp;gt; &lt;strong&gt;Quick Documentation&lt;/strong&gt;. You should probably take note of the shortcut for this action. &lt;/p&gt;




&lt;p&gt;The preview window should be open by default,&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfntvtptrvnf2ruhb9ql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfntvtptrvnf2ruhb9ql.png" alt="android studio default preview" width="800" height="199"&gt;&lt;/a&gt;&lt;br&gt;
but if it isn't, you can split the window. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsecmybadl6q3qjjglh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsecmybadl6q3qjjglh3.png" alt="android studio default preview" width="457" height="532"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Using the preview window, you can always create composables and then see how they look before deploying to your device.&lt;/p&gt;




&lt;p&gt;&lt;code&gt;Main Sources:&lt;br&gt;
Android source code&lt;/code&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>5 top sites to find written tutorials on Android development in 2022</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Sat, 25 Dec 2021 16:37:34 +0000</pubDate>
      <link>https://dev.to/alaje/5-top-sites-to-find-written-tutorials-on-android-development-in-2022-1f5l</link>
      <guid>https://dev.to/alaje/5-top-sites-to-find-written-tutorials-on-android-development-in-2022-1f5l</guid>
      <description>&lt;p&gt;&lt;a title="mammela-686310, CC0, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Android_logo_3.jpg"&gt;&lt;img alt="Android logo 3" src="https://res.cloudinary.com/practicaldev/image/fetch/s--z2RlaLS0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Android_logo_3.jpg/512px-Android_logo_3.jpg" width="512" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you've been procrastinating since 2021, and now that 2022 is in sight you're laced up and getting ready to start your android journey. Even if this scenario doesn't match your situation, as long as you need to learn more about Android, go through these gems on my list and you'll end up adding them to your list of favorites for anything android development-related. &lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.raywenderlich.com/library?content_types%5B%5D=article&amp;amp;domain_ids%5B%5D=2&amp;amp;limit_count=9&amp;amp;section_id=205&amp;amp;sort_direction=desc&amp;amp;sort_order=popularity"&gt;Raywenderlich&lt;/a&gt;&lt;br&gt;
This happens to be my number one go-to for iOS, Flutter, and Android.&lt;br&gt;
Though there's a price tag on their content made by their contributors, Raywenderlich comes first on my list because even their free content is awesome. An android developer of any level can easily benefit from their posts, and for programmers who do not have English as their first language, you notice how some of their posts are simplified when compared to other sites'. Additional points for them when you consider their learning paths, and the books they provide. If you rather enjoy lengthy articles then this might just end up being your soul-site. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://proandroiddev.com/"&gt;ProAndroidDev&lt;/a&gt;&lt;br&gt;
Hosted on Medium, I don't think many know about this site, but then a gem remains a gem whether tons of people know about it or not. On this site, you can find blog posts about android development, and the editors here have notable work experiences so you can be sure that you're getting content you can rely on. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.android.com/guide"&gt;Android's Official Developer Site&lt;/a&gt;&lt;br&gt;
"Why oh why", you might ask, "is android's official site for developers at number 3?". Well, that's because, for some reason only known to the Android team, their docs are not beginner-friendly. Maybe it could be their choice of words?&lt;br&gt;
I could have placed them at number 1 because their &lt;a href="https://codelabs.developers.google.com/?cat=Android&amp;amp;product=android"&gt;codelabs&lt;/a&gt; are enough to get them that seat, but... 😒 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.geeksforgeeks.org/android-tutorial/"&gt;GeekForGeeks&lt;/a&gt;&lt;br&gt;
This site's delivery would undoubtedly appeal more to beginners and non-native speakers. Though you would find it slightly difficult to find advanced topics here, this remains one of the best places to get your feet wet with android development in 2022.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/tagged/android"&gt;StackOverflow&lt;/a&gt;&lt;br&gt;
While you might not find "articles" about android development in StackOverflow since it happens to primarily be a platform where you ask questions and possibly have them answered by an army of developers, be rest assured that the mountain of information gotten from these answered questions will leave you more informed than you previously were. If you can't find an already answered question that is similar to yours, then you can always just ask yours. As a bonus, you could even come across links to other sites where you can find knowledge.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you think you have a better list with your top five sites to learn android development in 2022, you can always choose to make a comment sharing them.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>android</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>To Pair Or Not To Pair: Benefits</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Sat, 25 Dec 2021 07:52:57 +0000</pubDate>
      <link>https://dev.to/alaje/to-pair-or-not-to-pair-benefits-7e</link>
      <guid>https://dev.to/alaje/to-pair-or-not-to-pair-benefits-7e</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post serves as the continuation of a previously written piece with the link&lt;/strong&gt; &lt;a href="https://dev.to/ulimicreator/to-pair-or-not-to-pair-introduction-1n9"&gt;https://dev.to/ulimicreator/to-pair-or-not-to-pair-introduction-1n9&lt;/a&gt; &lt;/p&gt;




&lt;p&gt;Like many other processes, the implementation details of pair programming are left to the entity that intends to implement it. This is so because all effects are eventually carried and borne by the entity.&lt;br&gt;
And whiles one can't properly quantify the productivity of programmers in a workplace, when done well, pair programming could provide these benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Programmers get to learn easily from experienced developers and the knowledge flow is constant and all-encompassing to all participants.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better code writing, since the one typing the code, i.e. the driver, justifies their code as they type by explaining why they are writing it in such a manner, and a probable input from the navigator could produce a better option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More communication between programmers in the workplace since programmers who have been paired together would have been placed in the situation where they have to "program out loud" and express their opinions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Programmers get to understand each other's workflow and habits, and this can serve as a fertile ground for&lt;br&gt;
relationships.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time feedback on the programmer's code is received since with pair programming, the driver literally has someone "watching their back" and this eventually leads to less future code refactoring and reduces the chances of repeating smelly code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Programmers tend to realize when paired with their fellow programmers that everyone makes mistakes, and understanding this fact is essential to a healthy mind.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bonds are formed fast and relationships are established easily. This can be extremely beneficial to new employees. And whiles you don't need to be friends to work with someone, most of the boundaries that exist with acquaintances are removed and this produces more efficiency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With pair programming, when new programmers are paired with programmers more familiar with the codebase they are initiated quite easily and efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Participants grow to be able to accept feedback and work on them fast, and being able to learn from your mistakes in due time makes you a better programmer and ultimately, a better human being.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pair programming could be fun.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;code&gt;All suggestions and criticisms on any of my posts are accepted as long as they are not provided in a disparaging manner&lt;/code&gt;&lt;/p&gt;

</description>
      <category>agile</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>To Pair or Not to Pair: Introduction</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Thu, 23 Dec 2021 18:57:54 +0000</pubDate>
      <link>https://dev.to/alaje/to-pair-or-not-to-pair-introduction-1n9</link>
      <guid>https://dev.to/alaje/to-pair-or-not-to-pair-introduction-1n9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Pair programming&lt;/strong&gt;, aka &lt;strong&gt;pairing&lt;/strong&gt;, is more than what  you're probably thinking it is even if you have a good grasp on the words &lt;em&gt;pair&lt;/em&gt; and &lt;em&gt;programming&lt;/em&gt;. &lt;br&gt;
When we have two people working together on the same computer... on the same code, we have a setup for pair programming. Due to reasons, these individuals might find themselves at different locations, when this is so, it is a popular move to use video conferencing tools to accomplish this process.&lt;br&gt;
Now, just putting two people together, in front of a machine displaying some code is not pair programming. With pair programming, you find a situation where two people constantly communicate with each other about the code, find each other's errors and try to bring out the best possible code to write that accomplishes their sought after goal. &lt;strong&gt;These programmers are expected to work as a team.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;So things might seem weird at this point, like how does a person actually share a machine with you?&lt;/p&gt;




&lt;h2&gt;
  
  
  How does this actually work ?
&lt;/h2&gt;

&lt;p&gt;There are two roles, one for each person, obviously. We have &lt;strong&gt;the navigator&lt;/strong&gt; and &lt;strong&gt;the driver&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the driver do?&lt;/strong&gt;&lt;br&gt;
Just like how a driver interacts with a car, the driver in this case works directly with the machine to actually type in the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the navigator do?&lt;/strong&gt;&lt;br&gt;
The navigator exists to give pointers, answer questions from the driver, ask their own questions about the code being written, and intensively read the code as it is typed so that mistakes are noted fast. With a navigator, the driver not only has a pair of eyes on the code, but also another brain on it.&lt;/p&gt;




&lt;p&gt;Both continuously communicate about the project and the best way to do it. The driver can explain -out loud- what is being  typed, and the navigator can keep track of what has been done and what is suppose to come next.&lt;br&gt;
There is no designated person for a role, and participants can and should switch roles as many times as they deem fit so that both programmers can learn from each other.&lt;br&gt;
&lt;strong&gt;Some more common pairings might involve:&lt;/strong&gt;&lt;br&gt;
A junior programmer and a senior programmer, to allow an easier onboarding process by letting a person more familiar with the code base to serve as a navigator.&lt;br&gt;
&lt;strong&gt;or&lt;/strong&gt; &lt;br&gt;
Developers of the same rank so that they can properly learn from each other. &lt;/p&gt;




&lt;p&gt;Like every practice, pair programming can be adjusted to fit the company's workflow.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Learn more with my next post &lt;code&gt;To Pair or Not to Pair: Benefits&lt;/code&gt;&lt;/strong&gt; &lt;a href="https://dev.to/ulimicreator/to-pair-or-not-to-pair-benefits-7e"&gt;https://dev.to/ulimicreator/to-pair-or-not-to-pair-benefits-7e&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>agile</category>
    </item>
    <item>
      <title>Jetpack Compose Tidbits: Idempotent and Free of Side Effects</title>
      <dc:creator>alaje</dc:creator>
      <pubDate>Sun, 19 Sep 2021 04:14:13 +0000</pubDate>
      <link>https://dev.to/alaje/jetpack-compose-tidbits-idempotent-and-free-of-side-effects-23g8</link>
      <guid>https://dev.to/alaje/jetpack-compose-tidbits-idempotent-and-free-of-side-effects-23g8</guid>
      <description>&lt;p&gt;When Jetpack Compose was introduced, it came with the ability to define functions annotated with "@Composable" that describe how we want our UI to look. When defining these functions we call composables, they should be fast, idempotent, and free of side-effects.&lt;br&gt;
There are times when it is absolutely necessary to include side-effects in our composables because we might want to make certain changes to the state of our app, when doing so, it is advised to implement such in a "controlled environment". &lt;br&gt;
Read: &lt;br&gt;
&lt;a href="https://developer.android.com/jetpack/compose/side-effects"&gt;https://developer.android.com/jetpack/compose/side-effects&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quoting from the docs:&lt;br&gt;
"This function is fast, idempotent, and free of side-effects.&lt;/p&gt;

&lt;p&gt;The function behaves the same way when called multiple times with the same argument, and it does not use other values such as global variables or calls to random().&lt;br&gt;
The function describes the UI without any side-effects, such as modifying properties or global variables."&lt;/p&gt;

&lt;p&gt;The usage of side-effects here is referring to any change that composable functions make directly on entities that exist outside its local environment. This includes writing to or updating any object that exists externally. The objects are visible to other parts of our app and as such can be accessed at any point in time and changed. The internal workings of Composables does not favor this (except when using Effects API) and additionally the declarative approach of Compose insists that data flow down and events go up. If you want to implement a side-effect do it through a callback. A very common and basic example of what this means can be seen is a user clicking a button. In Compose, once the user clicks said button, you should create your composables in a way that allows the events to notify the app logic. You can do that normally by passing a lambda to your composable as an argument, this lets the app logic make the necessary changes and then the composable is recalled with the new data that will determine how it will be drawn on screen. In this manner, data climbs down the compose hierarchy and events go up.&lt;br&gt;
In the button clicking example, I pointed out that the composable would be redrawn, the android docs calls this recomposition. &lt;/p&gt;

&lt;p&gt;Idempotence describes an object's ability to not change its behavior beyond how its state was the first time it was called, even if the same operation was applied on it many times. Note that this definition is based on how it was used in the android docs. In the case of our composable function, it should always have the same effect in our environment no matter how many times we call it as long as we pass it the same input. Additionally, it should be free from side effects like using global variables which are available to other parts of our app. Using random values in our composable function also means that if we were to run our composable function several times with the same input, it would give us different results. According to the android docs, this destroys the idempotence of our composable.&lt;br&gt;
When creating your composables most at times, think of a way to make them reusable top-level functions. If you can do this, then you are most likely following the android docs' advice to make the majority of your composable functions idempotent and free of side-effects. &lt;/p&gt;

</description>
      <category>android</category>
      <category>beginners</category>
      <category>mobile</category>
      <category>wecoded</category>
    </item>
  </channel>
</rss>
