react-native link support for native Android modules developed in Kotlin

Summary:
Currently React Native cli does not support linking native Android modules written in Kotlin. This PR aims to add support to it and closes #14561

- New unit tests added to verify the added functionality, they can be found inside:
`local-cli/core/__tests__/android/findPackageClassName.spec.js`

- Existing unit tests passed.
Closes https://github.com/facebook/react-native/pull/14660

Differential Revision: D5316981

Pulled By: shergin

fbshipit-source-id: 98354ba1e1ce1080a9a4b9958ef39893472038a1
This commit is contained in:
Raul Gomez Acuna 2017-06-29 01:08:47 -07:00 committed by Facebook Github Bot
parent 0797dae500
commit d666f30665
5 changed files with 54 additions and 18 deletions

View File

@ -4,21 +4,27 @@ const path = require('path');
const manifest = fs.readFileSync(path.join(__dirname, './files/AndroidManifest.xml'));
const mainJavaClass = fs.readFileSync(path.join(__dirname, './files/Main.java'));
exports.valid = {
src: {
'AndroidManifest.xml': manifest,
main: {
com: {
some: {
example: {
'Main.java': mainJavaClass,
'ReactPackage.java': fs.readFileSync(path.join(__dirname, './files/ReactPackage.java')),
function generateValidFileStructure(classFileName) {
return {
src: {
'AndroidManifest.xml': manifest,
main: {
com: {
some: {
example: {
'Main.java': mainJavaClass,
[classFileName]: fs.readFileSync(path.join(__dirname, `./files/${classFileName}`)),
},
},
},
},
},
},
};
};
}
exports.valid = generateValidFileStructure('ReactPackage.java');
exports.validKotlin = generateValidFileStructure('ReactPackage.kt');
exports.userConfigManifest = {
src: {

View File

@ -10,7 +10,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SomeExamplePackage implements ReactPackage {
public class SomeExampleJavaPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(

View File

@ -0,0 +1,19 @@
package com.some.example;
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
import java.util.*
class SomeExampleKotlinPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule>
= mutableListOf(MaterialPaletteModule(reactContext))
override fun createViewManagers(reactContext: ReactApplicationContext?):
MutableList<ViewManager<View, ReactShadowNode>> = Collections.emptyList()
}

View File

@ -19,14 +19,25 @@ describe('android::findPackageClassName', () => {
beforeAll(() => {
mockFS({
empty: {},
flat: {
flatJava: {
android: mocks.valid,
},
flatKotlin: {
android: mocks.validKotlin,
},
});
});
it('returns manifest content if file exists in the folder', () => {
expect(typeof findPackageClassName('flat')).toBe('string');
expect(typeof findPackageClassName('flatJava')).toBe('string');
});
it('returns the name of the java class implementing ReactPackage', () => {
expect(findPackageClassName('flatJava')).toBe('SomeExampleJavaPackage');
});
it('returns the name of the kotlin class implementing ReactPackage', () => {
expect(findPackageClassName('flatKotlin')).toBe('SomeExampleKotlinPackage');
});
it('returns `null` if there are no matches', () => {

View File

@ -14,16 +14,16 @@ const path = require('path');
/**
* Gets package's class name (class that implements ReactPackage)
* by searching for its declaration in all Java files present in the folder
* by searching for its declaration in all Java/Kotlin files present in the folder
*
* @param {String} folder Folder to find java files
* @param {String} folder Folder to find java/kt files
*/
module.exports = function getPackageClassName(folder) {
const files = glob.sync('**/*.java', { cwd: folder });
const files = glob.sync('**/+(*.java|*.kt)', { cwd: folder });
const packages = files
.map(filePath => fs.readFileSync(path.join(folder, filePath), 'utf8'))
.map(file => file.match(/class (.*) implements ReactPackage/))
.map(file => file.match(/class (.*) +(implements|:) ReactPackage/))
.filter(match => match);
return packages.length ? packages[0][1] : null;