Skip to content

[0.73] Improve diffing for Kotlin Migration #69

@cortinico

Description

@cortinico

Hey all,
In 0.73 we updated the Android template to be in Kotlin rather than Java.
This results in the upgrade helper having 2 files removed (MainActivity.java and MainApplication.java) and 2 files added (MainActivity.kt and MainApplication.kt).

The diff looks as follows:

diff --git a/android/app/src/main/java/com/rntestapp/MainActivity.java b/android/app/src/main/java/com/rntestapp/MainActivity.java
deleted file mode 100644
index 2e7d5bf..0000000
--- a/android/app/src/main/java/com/rntestapp/MainActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.rntestapp;
-
-import com.facebook.react.ReactActivity;
-import com.facebook.react.ReactActivityDelegate;
-import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
-import com.facebook.react.defaults.DefaultReactActivityDelegate;
-
-public class MainActivity extends ReactActivity {
-
-  /**
-   * Returns the name of the main component registered from JavaScript. This is used to schedule
-   * rendering of the component.
-   */
-  @Override
-  protected String getMainComponentName() {
-    return "RNTestApp";
-  }
-
-  /**
-   * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
-   * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
-   * (aka React 18) with two boolean flags.
-   */
-  @Override
-  protected ReactActivityDelegate createReactActivityDelegate() {
-    return new DefaultReactActivityDelegate(
-        this,
-        getMainComponentName(),
-        // If you opted-in for the New Architecture, we enable the Fabric Renderer.
-        DefaultNewArchitectureEntryPoint.getFabricEnabled());
-  }
-}
diff --git a/android/app/src/main/java/com/rntestapp/MainActivity.kt b/android/app/src/main/java/com/rntestapp/MainActivity.kt
new file mode 100644
index 0000000..5e5f577
--- /dev/null
+++ b/android/app/src/main/java/com/rntestapp/MainActivity.kt
@@ -0,0 +1,22 @@
+package com.rntestapp
+
+import com.facebook.react.ReactActivity
+import com.facebook.react.ReactActivityDelegate
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
+import com.facebook.react.defaults.DefaultReactActivityDelegate
+
+class MainActivity : ReactActivity() {
+
+  /**
+   * Returns the name of the main component registered from JavaScript. This is used to schedule
+   * rendering of the component.
+   */
+  override fun getMainComponentName(): String = "RNTestApp"
+
+  /**
+   * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
+   * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
+   */
+  override fun createReactActivityDelegate(): ReactActivityDelegate =
+      DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
+}
diff --git a/android/app/src/main/java/com/rntestapp/MainApplication.java b/android/app/src/main/java/com/rntestapp/MainApplication.java
deleted file mode 100644
index a601b36..0000000
--- a/android/app/src/main/java/com/rntestapp/MainApplication.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.rntestapp;
-
-import android.app.Application;
-import com.facebook.react.PackageList;
-import com.facebook.react.ReactApplication;
-import com.facebook.react.ReactNativeHost;
-import com.facebook.react.ReactPackage;
-import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
-import com.facebook.react.defaults.DefaultReactNativeHost;
-import com.facebook.soloader.SoLoader;
-import java.util.List;
-
-public class MainApplication extends Application implements ReactApplication {
-
-  private final ReactNativeHost mReactNativeHost =
-      new DefaultReactNativeHost(this) {
-        @Override
-        public boolean getUseDeveloperSupport() {
-          return BuildConfig.DEBUG;
-        }
-
-        @Override
-        protected List<ReactPackage> getPackages() {
-          @SuppressWarnings("UnnecessaryLocalVariable")
-          List<ReactPackage> packages = new PackageList(this).getPackages();
-          // Packages that cannot be autolinked yet can be added manually here, for example:
-          // packages.add(new MyReactNativePackage());
-          return packages;
-        }
-
-        @Override
-        protected String getJSMainModuleName() {
-          return "index";
-        }
-
-        @Override
-        protected boolean isNewArchEnabled() {
-          return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
-        }
-
-        @Override
-        protected Boolean isHermesEnabled() {
-          return BuildConfig.IS_HERMES_ENABLED;
-        }
-      };
-
-  @Override
-  public ReactNativeHost getReactNativeHost() {
-    return mReactNativeHost;
-  }
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    SoLoader.init(this, /* native exopackage */ false);
-    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
-      // If you opted-in for the New Architecture, we load the native entry point for this app.
-      DefaultNewArchitectureEntryPoint.load();
-    }
-    ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
-  }
-}
diff --git a/android/app/src/main/java/com/rntestapp/MainApplication.kt b/android/app/src/main/java/com/rntestapp/MainApplication.kt
new file mode 100644
index 0000000..6e185a3
--- /dev/null
+++ b/android/app/src/main/java/com/rntestapp/MainApplication.kt
@@ -0,0 +1,52 @@
+package com.rntestapp
+
+import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.common.annotations.UnstableReactNativeAPI
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
+import com.facebook.react.defaults.DefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.react.flipper.ReactNativeFlipper
+import com.facebook.react.interfaces.ReactHost
+import com.facebook.soloader.SoLoader
+
+@UnstableReactNativeAPI
+class MainApplication : Application(), ReactApplication {
+
+  override val reactNativeHost: ReactNativeHost =
+      object : DefaultReactNativeHost(this) {
+        override fun getPackages(): List<ReactPackage> {
+          // Packages that cannot be autolinked yet can be added manually here, for example:
+          // packages.add(new MyReactNativePackage());
+          return PackageList(this).packages
+        }
+
+        override fun getJSMainModuleName(): String = "index"
+
+        override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
+
+        override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+        override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+      }
+
+  override val reactHost: ReactHost
+    get() =
+        DefaultReactHost.getDefaultReactHost(
+            context = this,
+            packageList = PackageList(this).packages,
+            jsMainModulePath = "index",
+            isHermesEnabled = BuildConfig.IS_HERMES_ENABLED)
+
+  override fun onCreate() {
+    super.onCreate()
+    SoLoader.init(this, false)
+    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+      // If you opted-in for the New Architecture, we load the native entry point for this app.
+      load()
+    }
+    ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
+  }
+}

We should be able to instead use the -M flag of git diff to tweak the similarity factor between two files.

I've done some testing and 15% looks like a good value.
Specifically if I run:

git diff HEAD~1 HEAD -M15%

the diff is as follows:

diff --git a/android/app/src/main/java/com/rntestapp/MainActivity.java b/android/app/src/main/java/com/rntestapp/MainActivity.kt
similarity index 20%
rename from android/app/src/main/java/com/rntestapp/MainActivity.java
rename to android/app/src/main/java/com/rntestapp/MainActivity.kt
index 2e7d5bf..5e5f577 100644
--- a/android/app/src/main/java/com/rntestapp/MainActivity.java
+++ b/android/app/src/main/java/com/rntestapp/MainActivity.kt
@@ -1,32 +1,22 @@
-package com.rntestapp;
+package com.rntestapp
 
-import com.facebook.react.ReactActivity;
-import com.facebook.react.ReactActivityDelegate;
-import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
-import com.facebook.react.defaults.DefaultReactActivityDelegate;
+import com.facebook.react.ReactActivity
+import com.facebook.react.ReactActivityDelegate
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
+import com.facebook.react.defaults.DefaultReactActivityDelegate
 
-public class MainActivity extends ReactActivity {
+class MainActivity : ReactActivity() {
 
   /**
    * Returns the name of the main component registered from JavaScript. This is used to schedule
    * rendering of the component.
    */
-  @Override
-  protected String getMainComponentName() {
-    return "RNTestApp";
-  }
+  override fun getMainComponentName(): String = "RNTestApp"
 
   /**
-   * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
-   * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
-   * (aka React 18) with two boolean flags.
+   * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
+   * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
    */
-  @Override
-  protected ReactActivityDelegate createReactActivityDelegate() {
-    return new DefaultReactActivityDelegate(
-        this,
-        getMainComponentName(),
-        // If you opted-in for the New Architecture, we enable the Fabric Renderer.
-        DefaultNewArchitectureEntryPoint.getFabricEnabled());
-  }
+  override fun createReactActivityDelegate(): ReactActivityDelegate =
+      DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
 }
diff --git a/android/app/src/main/java/com/rntestapp/MainApplication.java b/android/app/src/main/java/com/rntestapp/MainApplication.kt
similarity index 19%
rename from android/app/src/main/java/com/rntestapp/MainApplication.java
rename to android/app/src/main/java/com/rntestapp/MainApplication.kt
index a601b36..6e185a3 100644
--- a/android/app/src/main/java/com/rntestapp/MainApplication.java
+++ b/android/app/src/main/java/com/rntestapp/MainApplication.kt
@@ -1,62 +1,52 @@
-package com.rntestapp;
-
-import android.app.Application;
-import com.facebook.react.PackageList;
-import com.facebook.react.ReactApplication;
-import com.facebook.react.ReactNativeHost;
-import com.facebook.react.ReactPackage;
-import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
-import com.facebook.react.defaults.DefaultReactNativeHost;
-import com.facebook.soloader.SoLoader;
-import java.util.List;
-
-public class MainApplication extends Application implements ReactApplication {
-
-  private final ReactNativeHost mReactNativeHost =
-      new DefaultReactNativeHost(this) {
-        @Override
-        public boolean getUseDeveloperSupport() {
-          return BuildConfig.DEBUG;
-        }
-
-        @Override
-        protected List<ReactPackage> getPackages() {
-          @SuppressWarnings("UnnecessaryLocalVariable")
-          List<ReactPackage> packages = new PackageList(this).getPackages();
+package com.rntestapp
+
+import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.common.annotations.UnstableReactNativeAPI
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
+import com.facebook.react.defaults.DefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.react.flipper.ReactNativeFlipper
+import com.facebook.react.interfaces.ReactHost
+import com.facebook.soloader.SoLoader
+
+@UnstableReactNativeAPI
+class MainApplication : Application(), ReactApplication {
+
+  override val reactNativeHost: ReactNativeHost =
+      object : DefaultReactNativeHost(this) {
+        override fun getPackages(): List<ReactPackage> {
           // Packages that cannot be autolinked yet can be added manually here, for example:
           // packages.add(new MyReactNativePackage());
-          return packages;
+          return PackageList(this).packages
         }
 
-        @Override
-        protected String getJSMainModuleName() {
-          return "index";
-        }
+        override fun getJSMainModuleName(): String = "index"
 
-        @Override
-        protected boolean isNewArchEnabled() {
-          return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
-        }
+        override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
 
-        @Override
-        protected Boolean isHermesEnabled() {
-          return BuildConfig.IS_HERMES_ENABLED;
-        }
-      };
+        override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+        override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+      }
 
-  @Override
-  public ReactNativeHost getReactNativeHost() {
-    return mReactNativeHost;
-  }
+  override val reactHost: ReactHost
+    get() =
+        DefaultReactHost.getDefaultReactHost(
+            context = this,
+            packageList = PackageList(this).packages,
+            jsMainModulePath = "index",
+            isHermesEnabled = BuildConfig.IS_HERMES_ENABLED)
 
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    SoLoader.init(this, /* native exopackage */ false);
+  override fun onCreate() {
+    super.onCreate()
+    SoLoader.init(this, false)
     if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
       // If you opted-in for the New Architecture, we load the native entry point for this app.
-      DefaultNewArchitectureEntryPoint.load();
+      load()
     }
-    ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+    ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
   }
 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions