mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Codegen Android: optional NativeModule method should not be marked abstract
Summary: This fixed a bug in the JS Java spec generator. Optional methods were still marked `abstract` before this fix. Instead it should be a normal method with potentially falsy return value. The JavaPoet version does this correctly already, but there was a minor typo with void return type vs optional. Changelog: [Internal] Reviewed By: RSNara Differential Revision: D24524432 fbshipit-source-id: 57a248580a78bc255f34d0492ebe3a4691e66667
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f760f90f1e
commit
a1d374e504
+110
-16
@@ -26,17 +26,15 @@ const {unwrapNullable} = require('../../parsers/flow/modules/utils');
|
||||
|
||||
type FilesOutput = Map<string, string>;
|
||||
|
||||
const FileTemplate = ({
|
||||
packageName,
|
||||
className,
|
||||
methods,
|
||||
imports,
|
||||
}: $ReadOnly<{|
|
||||
packageName: string,
|
||||
className: string,
|
||||
methods: string,
|
||||
imports: string,
|
||||
|}>) => {
|
||||
function FileTemplate(
|
||||
config: $ReadOnly<{|
|
||||
packageName: string,
|
||||
className: string,
|
||||
methods: string,
|
||||
imports: string,
|
||||
|}>,
|
||||
): string {
|
||||
const {packageName, className, methods, imports} = config;
|
||||
return `
|
||||
/**
|
||||
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
|
||||
@@ -61,7 +59,37 @@ public abstract class ${className} extends ReactContextBaseJavaModule implements
|
||||
${methods}
|
||||
}
|
||||
`;
|
||||
};
|
||||
}
|
||||
|
||||
function MethodTemplate(
|
||||
config: $ReadOnly<{|
|
||||
abstract: boolean,
|
||||
methodBody: ?string,
|
||||
methodJavaAnnotation: string,
|
||||
methodName: string,
|
||||
translatedReturnType: string,
|
||||
traversedArgs: Array<string>,
|
||||
|}>,
|
||||
): string {
|
||||
const {
|
||||
abstract,
|
||||
methodBody,
|
||||
methodJavaAnnotation,
|
||||
methodName,
|
||||
translatedReturnType,
|
||||
traversedArgs,
|
||||
} = config;
|
||||
const methodQualifier = abstract ? 'abstract ' : '';
|
||||
const methodClosing = abstract
|
||||
? ';'
|
||||
: methodBody != null && methodBody.length > 0
|
||||
? ` { ${methodBody} }`
|
||||
: ' {}';
|
||||
return ` ${methodJavaAnnotation}
|
||||
public ${methodQualifier}${translatedReturnType} ${methodName}(${traversedArgs.join(
|
||||
', ',
|
||||
)})${methodClosing}`;
|
||||
}
|
||||
|
||||
function translateFunctionParamToJavaType(
|
||||
param: NativeModuleMethodParamSchema,
|
||||
@@ -199,6 +227,60 @@ function translateFunctionReturnTypeToJavaType(
|
||||
}
|
||||
}
|
||||
|
||||
function getFalsyReturnStatementFromReturnType(
|
||||
nullableReturnTypeAnnotation: Nullable<NativeModuleReturnTypeAnnotation>,
|
||||
createErrorMessage: (typeName: string) => string,
|
||||
resolveAlias: AliasResolver,
|
||||
): string {
|
||||
const [
|
||||
returnTypeAnnotation,
|
||||
nullable,
|
||||
] = unwrapNullable<NativeModuleReturnTypeAnnotation>(
|
||||
nullableReturnTypeAnnotation,
|
||||
);
|
||||
|
||||
let realTypeAnnotation = returnTypeAnnotation;
|
||||
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
|
||||
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
|
||||
}
|
||||
|
||||
switch (realTypeAnnotation.type) {
|
||||
case 'ReservedFunctionValueTypeAnnotation':
|
||||
switch (realTypeAnnotation.name) {
|
||||
case 'RootTag':
|
||||
return 'return 0.0;';
|
||||
default:
|
||||
(realTypeAnnotation.name: empty);
|
||||
throw new Error(createErrorMessage(realTypeAnnotation.name));
|
||||
}
|
||||
case 'VoidTypeAnnotation':
|
||||
return '';
|
||||
case 'PromiseTypeAnnotation':
|
||||
return '';
|
||||
case 'NumberTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return 0;';
|
||||
case 'FloatTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return 0.0;';
|
||||
case 'DoubleTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return 0.0;';
|
||||
case 'Int32TypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return 0;';
|
||||
case 'BooleanTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return false;';
|
||||
case 'StringTypeAnnotation':
|
||||
return nullable ? 'return null;' : 'return "";';
|
||||
case 'ObjectTypeAnnotation':
|
||||
return 'return null;';
|
||||
case 'GenericObjectTypeAnnotation':
|
||||
return 'return null;';
|
||||
case 'ArrayTypeAnnotation':
|
||||
return 'return null;';
|
||||
default:
|
||||
(realTypeAnnotation.type: empty);
|
||||
throw new Error(createErrorMessage(realTypeAnnotation.type));
|
||||
}
|
||||
}
|
||||
|
||||
// Build special-cased runtime check for getConstants().
|
||||
function buildGetConstantsMethod(
|
||||
method: NativeModulePropertySchema,
|
||||
@@ -360,10 +442,22 @@ module.exports = {
|
||||
const methodJavaAnnotation = `@ReactMethod${
|
||||
isSyncMethod ? '(isBlockingSynchronousMethod = true)' : ''
|
||||
}`;
|
||||
return ` ${methodJavaAnnotation}
|
||||
public abstract ${translatedReturnType} ${method.name}(${traversedArgs.join(
|
||||
', ',
|
||||
)});`;
|
||||
const methodBody = method.optional
|
||||
? getFalsyReturnStatementFromReturnType(
|
||||
methodTypeAnnotation.returnTypeAnnotation,
|
||||
typeName =>
|
||||
`Cannot build falsy return statement for return type for method ${method.name}. Found: ${typeName}`,
|
||||
resolveAlias,
|
||||
)
|
||||
: null;
|
||||
return MethodTemplate({
|
||||
abstract: !method.optional,
|
||||
methodBody,
|
||||
methodJavaAnnotation,
|
||||
methodName: method.name,
|
||||
translatedReturnType,
|
||||
traversedArgs,
|
||||
});
|
||||
});
|
||||
|
||||
files.set(
|
||||
|
||||
Reference in New Issue
Block a user