Skip to content

Commit

Permalink
Enable module annotation processor in OSS
Browse files Browse the repository at this point in the history
  • Loading branch information
janicduplessis committed May 29, 2020
1 parent a4757d2 commit 85baa27
Show file tree
Hide file tree
Showing 18 changed files with 82 additions and 120 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ project.xcworkspace
/ReactAndroid/gradle/
/ReactAndroid/gradlew
/ReactAndroid/gradlew.bat
/android/annotations/build/
/android/annotations-compiler/build/

# Buck
.buckd
Expand All @@ -51,7 +53,6 @@ buck-out
.gradle
local.properties
*.iml
/android/

# Node
node_modules
Expand Down
3 changes: 3 additions & 0 deletions ReactAndroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ android {
}

dependencies {
api(project(':react-native-annotations'))
annotationProcessor(project(':react-native-annotations-compiler'))

api("com.facebook.infer.annotation:infer-annotation:0.11.2")
api("com.facebook.yoga:proguard-annotations:1.14.1")
api("javax.inject:javax.inject:1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@

package com.facebook.react;

import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_START;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.devsupport.LogBoxModule;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.module.annotations.ReactModuleList;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.DeviceEventManagerModule;
Expand All @@ -30,21 +24,22 @@
import com.facebook.react.modules.debug.SourceCodeModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.systrace.Systrace;
import java.util.HashMap;

import java.util.List;
import java.util.Map;

import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_START;

/**
* This is the basic module to support React Native. The debug modules are now in DebugCorePackage.
*/
@ReactModuleList(
// WARNING: If you modify this list, ensure that the list below in method
// getReactModuleInfoByInitialization is also updated
nativeModules = {
AndroidInfoModule.class,
DeviceEventManagerModule.class,
Expand Down Expand Up @@ -76,63 +71,9 @@ public CoreModulesPackage(
mMinTimeLeftInFrameForNonBatchedOperationMs = minTimeLeftInFrameForNonBatchedOperationMs;
}

/**
* This method is overridden, since OSS does not run the annotation processor to generate {@link
* CoreModulesPackage$$ReactModuleInfoProvider} class. Here we check if it exists. If it does not
* exist, we generate one manually in {@link
* CoreModulesPackage#getReactModuleInfoByInitialization()} and return that instead.
*/
@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
try {
Class<?> reactModuleInfoProviderClass =
Class.forName("com.facebook.react.CoreModulesPackage$$ReactModuleInfoProvider");
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
} catch (ClassNotFoundException e) {
// In OSS case, the annotation processor does not run. We fall back on creating this byhand
Class<? extends NativeModule>[] moduleList =
new Class[] {
AndroidInfoModule.class,
DeviceEventManagerModule.class,
DeviceInfoModule.class,
DevSettingsModule.class,
ExceptionsManagerModule.class,
LogBoxModule.class,
HeadlessJsTaskSupportModule.class,
SourceCodeModule.class,
TimingModule.class,
UIManagerModule.class
};

final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
for (Class<? extends NativeModule> moduleClass : moduleList) {
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);

reactModuleInfoMap.put(
reactModule.name(),
new ReactModuleInfo(
reactModule.name(),
moduleClass.getName(),
reactModule.canOverrideExistingModule(),
reactModule.needsEagerInit(),
reactModule.hasConstants(),
reactModule.isCxxModule(),
TurboModule.class.isAssignableFrom(moduleClass)));
}

return new ReactModuleInfoProvider() {
@Override
public Map<String, ReactModuleInfo> getReactModuleInfos() {
return reactModuleInfoMap;
}
};
} catch (InstantiationException e) {
throw new RuntimeException(
"No ReactModuleInfoProvider for CoreModulesPackage$$ReactModuleInfoProvider", e);
} catch (IllegalAccessException e) {
throw new RuntimeException(
"No ReactModuleInfoProvider for CoreModulesPackage$$ReactModuleInfoProvider", e);
}
return new CoreModulesPackage$$ReactModuleInfoProvider();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,11 @@
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.devsupport.JSCHeapCapture;
import com.facebook.react.devsupport.JSDevSupport;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.module.annotations.ReactModuleList;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import java.util.HashMap;
import java.util.Map;

/**
* Package defining core framework modules (e.g. UIManager). It should be used for modules that
* require special integration with other framework parts (e.g. with the list of packages to load
* view managers from).
* Package defining core debug only modules.
*/
@ReactModuleList(
nativeModules = {
Expand All @@ -44,45 +36,6 @@ public NativeModule getModule(String name, ReactApplicationContext reactContext)

@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
try {
Class<?> reactModuleInfoProviderClass =
Class.forName("com.facebook.react.DebugCorePackage$$ReactModuleInfoProvider");
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
} catch (ClassNotFoundException e) {
// In OSS case, the annotation processor does not run. We fall back on creating this by hand
Class<? extends NativeModule>[] moduleList =
new Class[] {
JSCHeapCapture.class, JSDevSupport.class,
};

final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
for (Class<? extends NativeModule> moduleClass : moduleList) {
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);

reactModuleInfoMap.put(
reactModule.name(),
new ReactModuleInfo(
reactModule.name(),
moduleClass.getName(),
reactModule.canOverrideExistingModule(),
reactModule.needsEagerInit(),
reactModule.hasConstants(),
reactModule.isCxxModule(),
TurboModule.class.isAssignableFrom(moduleClass)));
}

return new ReactModuleInfoProvider() {
@Override
public Map<String, ReactModuleInfo> getReactModuleInfos() {
return reactModuleInfoMap;
}
};
} catch (InstantiationException e) {
throw new RuntimeException(
"No ReactModuleInfoProvider for DebugCorePackage$$ReactModuleInfoProvider", e);
} catch (IllegalAccessException e) {
throw new RuntimeException(
"No ReactModuleInfoProvider for DebugCorePackage$$ReactModuleInfoProvider", e);
}
return new com.facebook.react.DebugCorePackage$$ReactModuleInfoProvider();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import androidx.annotation.NonNull;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.module.annotations.BaseNativeModule;

/**
* A native module whose API can be provided to JS catalyst instances. {@link NativeModule}s whose
Expand All @@ -18,7 +19,7 @@
* themselves using {@link CxxModuleWrapper}.
*/
@DoNotStrip
public interface NativeModule {
public interface NativeModule extends BaseNativeModule {
interface NativeMethod {
void invoke(JSInstance jsInstance, ReadableArray parameters);

Expand Down
25 changes: 25 additions & 0 deletions android/annotations-compiler/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

apply plugin: 'java'

sourceSets.configureEach { sourceSet ->
tasks.named(sourceSet.compileJavaTaskName).configure {
options.annotationProcessorGeneratedSourcesDirectory = file("$buildDir/generated/sources/annotationProcessor/java/${sourceSet.name}")
}
}

java {
sourceCompatibility(JavaVersion.VERSION_1_8)
targetCompatibility(JavaVersion.VERSION_1_8)
}

dependencies {
implementation('com.squareup:javapoet:1.8.0')
implementation('com.facebook.infer.annotation:infer-annotation:0.11.2')
implementation(project(':react-native-annotations'))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.facebook.react.module.processing.ReactModuleSpecProcessor
17 changes: 17 additions & 0 deletions android/annotations/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

apply plugin: 'java'

dependencies {

}

java {
sourceCompatibility(JavaVersion.VERSION_1_8)
targetCompatibility(JavaVersion.VERSION_1_8)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.module.annotations;

/**
* Used to make sure classes passed to the ReactModule annotation are actually an instance of
* NativeModule without needing a dependency on NativeModule that is in the ReactAndroid target.
*/
public interface BaseNativeModule {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;

import com.facebook.react.bridge.NativeModule;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

Expand All @@ -27,5 +26,5 @@
*
* @return List of Native modules in the package.
*/
Class<? extends NativeModule>[] nativeModules();
Class<? extends BaseNativeModule>[] nativeModules();
}
6 changes: 6 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ include(
":ReactAndroid",
":RNTester:android:app"
)

include(":react-native-annotations")
project(":react-native-annotations").projectDir = File(rootProject.projectDir, "android/annotations")

include(":react-native-annotations-compiler")
project(":react-native-annotations-compiler").projectDir = File(rootProject.projectDir, "android/annotations-compiler")

0 comments on commit 85baa27

Please sign in to comment.