mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Make buildModuleSchema and buildComponentSchema operate on Program AST nodes
Summary: ## Why We want to reuse these functions inside the ESLint rule. Therefore, it's better to make them accept the AST node object, as opposed to a custom type defined in codegen. Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D24379512 fbshipit-source-id: 9f7378fc6c5f48cce34da109f5a7c017332b302a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
33789ba0ea
commit
2f438b03d7
@@ -16,6 +16,7 @@ const {getEvents} = require('./events');
|
||||
const {getProps, getPropProperties} = require('./props');
|
||||
const {getCommandOptions, getOptions} = require('./options');
|
||||
const {getExtendsProps, removeKnownExtends} = require('./extends');
|
||||
const {getTypes} = require('../utils');
|
||||
|
||||
function findComponentConfig(ast) {
|
||||
const foundConfigs = [];
|
||||
@@ -167,7 +168,7 @@ function getCommandProperties(commandTypeName, types, commandOptions) {
|
||||
}
|
||||
|
||||
// $FlowFixMe there's no flowtype for AST
|
||||
function buildComponentSchema(ast, types): ComponentSchemaBuilderConfig {
|
||||
function buildComponentSchema(ast): ComponentSchemaBuilderConfig {
|
||||
const {
|
||||
componentName,
|
||||
propsTypeName,
|
||||
@@ -176,6 +177,8 @@ function buildComponentSchema(ast, types): ComponentSchemaBuilderConfig {
|
||||
optionsExpression,
|
||||
} = findComponentConfig(ast);
|
||||
|
||||
const types = getTypes(ast);
|
||||
|
||||
const propProperties = getPropProperties(propsTypeName, types);
|
||||
const commandOptions = getCommandOptions(commandOptionsExpression);
|
||||
|
||||
|
||||
+29
-37
@@ -21,27 +21,6 @@ const {buildModuleSchema} = require('./modules');
|
||||
const {wrapModuleSchema} = require('./modules/schema');
|
||||
const invariant = require('invariant');
|
||||
|
||||
import type {TypeDeclarationMap} from './utils';
|
||||
|
||||
function getTypes(ast): TypeDeclarationMap {
|
||||
return ast.body.reduce((types, node) => {
|
||||
if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') {
|
||||
if (
|
||||
node.declaration.type === 'TypeAlias' ||
|
||||
node.declaration.type === 'InterfaceDeclaration'
|
||||
) {
|
||||
types[node.declaration.id.name] = node.declaration;
|
||||
}
|
||||
} else if (
|
||||
node.type === 'TypeAlias' ||
|
||||
node.type === 'InterfaceDeclaration'
|
||||
) {
|
||||
types[node.id.name] = node;
|
||||
}
|
||||
return types;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function isComponent(ast) {
|
||||
const defaultExports = ast.body.filter(
|
||||
node => node.type === 'ExportDefaultDeclaration',
|
||||
@@ -68,27 +47,39 @@ function isComponent(ast) {
|
||||
);
|
||||
}
|
||||
|
||||
function isModule(types: TypeDeclarationMap) {
|
||||
const declaredModuleNames: Array<string> = Object.keys(types).filter(
|
||||
(typeName: string) => {
|
||||
const declaration = types[typeName];
|
||||
function isModule(
|
||||
// TODO(T71778680): Flow-type this node.
|
||||
ast: $FlowFixMe,
|
||||
) {
|
||||
const moduleInterfaces = ast.body
|
||||
.map(node => {
|
||||
if (
|
||||
node.type === 'ExportNamedDeclaration' &&
|
||||
node.exportKind === 'type' &&
|
||||
node.declaration.type === 'InterfaceDeclaration'
|
||||
) {
|
||||
return node.declaration;
|
||||
}
|
||||
return node;
|
||||
})
|
||||
.filter(declaration => {
|
||||
return (
|
||||
declaration.type === 'InterfaceDeclaration' &&
|
||||
declaration.extends.length === 1 &&
|
||||
declaration.extends[0].type === 'InterfaceExtends' &&
|
||||
declaration.extends[0].id.name === 'TurboModule'
|
||||
);
|
||||
},
|
||||
);
|
||||
})
|
||||
.map(declaration => declaration.id.name);
|
||||
|
||||
if (declaredModuleNames.length === 0) {
|
||||
if (moduleInterfaces.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (declaredModuleNames.length > 1) {
|
||||
if (moduleInterfaces.length > 1) {
|
||||
throw new Error(
|
||||
'File contains declarations of more than one module: ' +
|
||||
declaredModuleNames.join(', ') +
|
||||
moduleInterfaces.join(', ') +
|
||||
'. Please declare exactly one module in this file.',
|
||||
);
|
||||
}
|
||||
@@ -96,9 +87,12 @@ function isModule(types: TypeDeclarationMap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getConfigType(ast, types: TypeDeclarationMap): 'module' | 'component' {
|
||||
function getConfigType(
|
||||
// TODO(T71778680): Flow-type this node.
|
||||
ast: $FlowFixMe,
|
||||
): 'module' | 'component' {
|
||||
const isConfigAComponent = isComponent(ast);
|
||||
const isConfigAModule = isModule(types);
|
||||
const isConfigAModule = isModule(ast);
|
||||
|
||||
if (isConfigAModule && isConfigAComponent) {
|
||||
throw new Error(
|
||||
@@ -142,12 +136,10 @@ const TURBO_MODULE_REGISTRY_REQUIRE_REGEX_STRING = withSpace(
|
||||
function buildSchema(contents: string, filename: ?string): SchemaType {
|
||||
const ast = flowParser.parse(contents);
|
||||
|
||||
const types = getTypes(ast);
|
||||
|
||||
const configType = getConfigType(ast, types);
|
||||
const configType = getConfigType(ast);
|
||||
|
||||
if (configType === 'component') {
|
||||
return wrapComponentSchema(buildComponentSchema(ast, types));
|
||||
return wrapComponentSchema(buildComponentSchema(ast));
|
||||
} else {
|
||||
if (filename === undefined || filename === null) {
|
||||
throw new Error('Filepath expected while parasing a module');
|
||||
@@ -180,7 +172,7 @@ function buildSchema(contents: string, filename: ?string): SchemaType {
|
||||
}
|
||||
|
||||
return wrapModuleSchema(
|
||||
buildModuleSchema(hasteModuleName, moduleNames, types),
|
||||
buildModuleSchema(hasteModuleName, moduleNames, ast),
|
||||
hasteModuleName,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import type {
|
||||
} from '../../../CodegenSchema.js';
|
||||
|
||||
import type {TypeDeclarationMap} from '../utils.js';
|
||||
const {resolveTypeAnnotation} = require('../utils.js');
|
||||
const {resolveTypeAnnotation, getTypes} = require('../utils.js');
|
||||
const {unwrapNullable, wrapNullable} = require('./utils');
|
||||
const {
|
||||
FlowGenericNotTypeParameterizedParserError,
|
||||
@@ -398,8 +398,12 @@ function buildPropertySchema(
|
||||
function buildModuleSchema(
|
||||
hasteModuleName: string,
|
||||
moduleNames: $ReadOnlyArray<string>,
|
||||
types: TypeDeclarationMap,
|
||||
/**
|
||||
* TODO(T71778680): Flow-type this node.
|
||||
*/
|
||||
ast: $FlowFixMe,
|
||||
): NativeModuleSchema {
|
||||
const types = getTypes(ast);
|
||||
const moduleInterfaceNames = (Object.keys(
|
||||
types,
|
||||
): $ReadOnlyArray<string>).filter((typeName: string) => {
|
||||
|
||||
@@ -20,6 +20,25 @@
|
||||
*/
|
||||
export type TypeDeclarationMap = {|[declarationName: string]: $FlowFixMe|};
|
||||
|
||||
function getTypes(ast: $FlowFixMe): TypeDeclarationMap {
|
||||
return ast.body.reduce((types, node) => {
|
||||
if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') {
|
||||
if (
|
||||
node.declaration.type === 'TypeAlias' ||
|
||||
node.declaration.type === 'InterfaceDeclaration'
|
||||
) {
|
||||
types[node.declaration.id.name] = node.declaration;
|
||||
}
|
||||
} else if (
|
||||
node.type === 'TypeAlias' ||
|
||||
node.type === 'InterfaceDeclaration'
|
||||
) {
|
||||
types[node.id.name] = node;
|
||||
}
|
||||
return types;
|
||||
}, {});
|
||||
}
|
||||
|
||||
// $FlowFixMe there's no flowtype for ASTs
|
||||
export type ASTNode = Object;
|
||||
|
||||
@@ -95,4 +114,5 @@ function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode {
|
||||
module.exports = {
|
||||
getValueFromTypes,
|
||||
resolveTypeAnnotation,
|
||||
getTypes,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user