PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@react-native/codegen/lib/generators/components

Просмотр файла: GeneratePropsJavaDelegate.js.flow

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict
 * @format
 */

'use strict';
import type {CommandParamTypeAnnotation} from '../../CodegenSchema';
import type {
  CommandTypeAnnotation,
  ComponentShape,
  NamedShape,
  PropTypeAnnotation,
  SchemaType,
} from '../../CodegenSchema';

const {
  getDelegateJavaClassName,
  getImports,
  getInterfaceJavaClassName,
  toSafeJavaString,
} = require('./JavaHelpers');

// File path -> contents
type FilesOutput = Map<string, string>;

const FileTemplate = ({
  packageName,
  imports,
  className,
  extendClasses,
  interfaceClassName,
  methods,
}: {
  packageName: string,
  imports: string,
  className: string,
  extendClasses: string,
  interfaceClassName: string,
  methods: string,
}) => `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* ${'@'}generated by codegen project: GeneratePropsJavaDelegate.js
*/

package ${packageName};

${imports}

public class ${className}<T extends ${extendClasses}, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
  public ${className}(U viewManager) {
    super(viewManager);
  }
  ${methods}
}
`;

const PropSetterTemplate = ({propCases}: {propCases: string}) =>
  `
  @Override
  public void setProperty(T view, String propName, @Nullable Object value) {
    ${propCases}
  }
`.trim();

const CommandsTemplate = ({commandCases}: {commandCases: string}) =>
  `
  @Override
  public void receiveCommand(T view, String commandName, ReadableArray args) {
    switch (commandName) {
      ${commandCases}
    }
  }
`.trim();

function getJavaValueForProp(
  prop: NamedShape<PropTypeAnnotation>,
  componentName: string,
): string {
  const typeAnnotation = prop.typeAnnotation;

  switch (typeAnnotation.type) {
    case 'BooleanTypeAnnotation':
      if (typeAnnotation.default === null) {
        return 'value == null ? null : (Boolean) value';
      } else {
        return `value == null ? ${typeAnnotation.default.toString()} : (boolean) value`;
      }
    case 'StringTypeAnnotation':
      const defaultValueString =
        typeAnnotation.default === null
          ? 'null'
          : `"${typeAnnotation.default}"`;
      return `value == null ? ${defaultValueString} : (String) value`;
    case 'Int32TypeAnnotation':
      return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
    case 'DoubleTypeAnnotation':
      if (prop.optional) {
        return `value == null ? ${typeAnnotation.default}f : ((Double) value).doubleValue()`;
      } else {
        return 'value == null ? Double.NaN : ((Double) value).doubleValue()';
      }
    case 'FloatTypeAnnotation':
      if (typeAnnotation.default === null) {
        return 'value == null ? null : ((Double) value).floatValue()';
      } else if (prop.optional) {
        return `value == null ? ${typeAnnotation.default}f : ((Double) value).floatValue()`;
      } else {
        return 'value == null ? Float.NaN : ((Double) value).floatValue()';
      }
    case 'ReservedPropTypeAnnotation':
      switch (typeAnnotation.name) {
        case 'ColorPrimitive':
          return 'ColorPropConverter.getColor(value, view.getContext())';
        case 'ImageSourcePrimitive':
          return '(ReadableMap) value';
        case 'ImageRequestPrimitive':
          return '(ReadableMap) value';
        case 'PointPrimitive':
          return '(ReadableMap) value';
        case 'EdgeInsetsPrimitive':
          return '(ReadableMap) value';
        case 'DimensionPrimitive':
          return 'DimensionPropConverter.getDimension(value)';
        default:
          (typeAnnotation.name: empty);
          throw new Error('Received unknown ReservedPropTypeAnnotation');
      }
    case 'ArrayTypeAnnotation': {
      return '(ReadableArray) value';
    }
    case 'ObjectTypeAnnotation': {
      return '(ReadableMap) value';
    }
    case 'StringEnumTypeAnnotation':
      return '(String) value';
    case 'Int32EnumTypeAnnotation':
      return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
    case 'MixedTypeAnnotation':
      return 'new DynamicFromObject(value)';
    default:
      (typeAnnotation: empty);
      throw new Error('Received invalid typeAnnotation');
  }
}

function generatePropCasesString(
  component: ComponentShape,
  componentName: string,
) {
  if (component.props.length === 0) {
    return 'super.setProperty(view, propName, value);';
  }

  const cases = component.props
    .map(prop => {
      return `case "${prop.name}":
        mViewManager.set${toSafeJavaString(
          prop.name,
        )}(view, ${getJavaValueForProp(prop, componentName)});
        break;`;
    })
    .join('\n' + '      ');

  return `switch (propName) {
      ${cases}
      default:
        super.setProperty(view, propName, value);
    }`;
}

function getCommandArgJavaType(
  param: NamedShape<CommandParamTypeAnnotation>,
  index: number,
) {
  const {typeAnnotation} = param;

  switch (typeAnnotation.type) {
    case 'ReservedTypeAnnotation':
      switch (typeAnnotation.name) {
        case 'RootTag':
          return `args.getDouble(${index})`;
        default:
          (typeAnnotation.name: empty);
          throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
      }
    case 'BooleanTypeAnnotation':
      return `args.getBoolean(${index})`;
    case 'DoubleTypeAnnotation':
      return `args.getDouble(${index})`;
    case 'FloatTypeAnnotation':
      return `(float) args.getDouble(${index})`;
    case 'Int32TypeAnnotation':
      return `args.getInt(${index})`;
    case 'StringTypeAnnotation':
      return `args.getString(${index})`;
    case 'ArrayTypeAnnotation':
      return `args.getArray(${index})`;
    default:
      (typeAnnotation.type: empty);
      throw new Error(`Receieved invalid type: ${typeAnnotation.type}`);
  }
}

function getCommandArguments(
  command: NamedShape<CommandTypeAnnotation>,
): string {
  return [
    'view',
    ...command.typeAnnotation.params.map(getCommandArgJavaType),
  ].join(', ');
}

function generateCommandCasesString(
  component: ComponentShape,
  componentName: string,
) {
  if (component.commands.length === 0) {
    return null;
  }

  const commandMethods = component.commands
    .map(command => {
      return `case "${command.name}":
        mViewManager.${toSafeJavaString(
          command.name,
          false,
        )}(${getCommandArguments(command)});
        break;`;
    })
    .join('\n' + '      ');

  return commandMethods;
}

function getClassExtendString(component: ComponentShape): string {
  const extendString = component.extendsProps
    .map(extendProps => {
      switch (extendProps.type) {
        case 'ReactNativeBuiltInType':
          switch (extendProps.knownTypeName) {
            case 'ReactNativeCoreViewProps':
              return 'View';
            default:
              (extendProps.knownTypeName: empty);
              throw new Error('Invalid knownTypeName');
          }
        default:
          (extendProps.type: empty);
          throw new Error('Invalid extended type');
      }
    })
    .join('');

  return extendString;
}

function getDelegateImports(component: ComponentShape) {
  const imports = getImports(component, 'delegate');
  // The delegate needs ReadableArray for commands always.
  // The interface doesn't always need it
  if (component.commands.length > 0) {
    imports.add('import com.facebook.react.bridge.ReadableArray;');
  }
  imports.add('import androidx.annotation.Nullable;');
  imports.add('import com.facebook.react.uimanager.BaseViewManagerDelegate;');
  imports.add('import com.facebook.react.uimanager.BaseViewManager;');
  imports.add('import com.facebook.react.uimanager.LayoutShadowNode;');

  return imports;
}

function generateMethods(
  propsString: string,
  commandsString: null | string,
): string {
  return [
    PropSetterTemplate({propCases: propsString}),
    commandsString != null
      ? CommandsTemplate({commandCases: commandsString})
      : '',
  ]
    .join('\n\n  ')
    .trimRight();
}

module.exports = {
  generate(
    libraryName: string,
    schema: SchemaType,
    packageName?: string,
    assumeNonnull: boolean = false,
    headerPrefix?: string,
  ): FilesOutput {
    // TODO: This doesn't support custom package name yet.
    const normalizedPackageName = 'com.facebook.react.viewmanagers';
    const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;

    const files = new Map<string, string>();
    Object.keys(schema.modules).forEach(moduleName => {
      const module = schema.modules[moduleName];
      if (module.type !== 'Component') {
        return;
      }

      const {components} = module;
      // No components in this module
      if (components == null) {
        return;
      }

      return Object.keys(components)
        .filter(componentName => {
          const component = components[componentName];
          return !(
            component.excludedPlatforms &&
            component.excludedPlatforms.includes('android')
          );
        })
        .forEach(componentName => {
          const component = components[componentName];
          const className = getDelegateJavaClassName(componentName);
          const interfaceClassName = getInterfaceJavaClassName(componentName);

          const imports = getDelegateImports(component);
          const propsString = generatePropCasesString(component, componentName);
          const commandsString = generateCommandCasesString(
            component,
            componentName,
          );
          const extendString = getClassExtendString(component);

          const replacedTemplate = FileTemplate({
            imports: Array.from(imports).sort().join('\n'),
            packageName: normalizedPackageName,
            className,
            extendClasses: extendString,
            methods: generateMethods(propsString, commandsString),
            interfaceClassName: interfaceClassName,
          });

          files.set(`${outputDir}/${className}.java`, replacedTemplate);
        });
    });

    return files;
  },
};

Выполнить команду


Для локальной разработки. Не используйте в интернете!