55 * LICENSE file in the root directory of this source tree.
66 *
77 * @format
8- * @flow strict
8+ * @flow strict-local
99 */
1010
1111'use strict' ;
@@ -26,6 +26,63 @@ const {
2626import type { ParserType } from './errors' ;
2727
2828const invariant = require ( 'invariant' ) ;
29+ const {
30+ getTypes,
31+ isModuleRegistryCall,
32+ resolveTypeAnnotation,
33+ } = require ( './flow/utils' ) ;
34+ const {
35+ throwIfIncorrectModuleRegistryCallTypeParameterParserError,
36+ throwIfModuleInterfaceIsMisnamed,
37+ throwIfModuleInterfaceNotFound,
38+ throwIfModuleTypeIsUnsupported,
39+ throwIfMoreThanOneModuleInterfaceParserError,
40+ throwIfMoreThanOneModuleRegistryCalls,
41+ throwIfUnsupportedFunctionReturnTypeAnnotationParserError,
42+ throwIfUntypedModule,
43+ throwIfUnusedModuleInterfaceParserError,
44+ throwIfWrongNumberOfCallExpressionArgs,
45+ } = require ( './error-utils' ) ;
46+ const { verifyPlatforms, visit} = require ( './utils' ) ;
47+ const {
48+ IncorrectModuleRegistryCallArgumentTypeParserError,
49+ UnnamedFunctionParamParserError,
50+ UnsupportedFunctionParamTypeAnnotationParserError,
51+ } = require ( './errors' ) ;
52+ import type {
53+ NamedShape ,
54+ NativeModuleAliasMap ,
55+ NativeModuleArrayTypeAnnotation ,
56+ NativeModuleBaseTypeAnnotation ,
57+ NativeModuleFunctionTypeAnnotation ,
58+ NativeModuleParamTypeAnnotation ,
59+ NativeModulePropertyShape ,
60+ } from '../CodegenSchema' ;
61+ import type { ParserErrorCapturer , TypeDeclarationMap } from './utils' ;
62+ import {
63+ UnsupportedArrayElementTypeAnnotationParserError ,
64+ UnsupportedEnumDeclarationParserError ,
65+ UnsupportedGenericParserError ,
66+ UnsupportedObjectPropertyTypeAnnotationParserError ,
67+ UnsupportedTypeAnnotationParserError ,
68+ } from './errors' ;
69+ import {
70+ emitBoolean ,
71+ emitDouble ,
72+ emitFunction ,
73+ emitInt32 ,
74+ emitNumber ,
75+ emitObject ,
76+ emitPromise ,
77+ emitRootTag ,
78+ emitString ,
79+ emitStringish ,
80+ emitVoid ,
81+ typeAliasResolution ,
82+ } from './parsers-primitives' ;
83+ import { throwIfPropertyValueTypeIsUnsupported } from './error-utils' ;
84+ import { nullGuard } from './parsers-utils' ;
85+ import type { Parser } from './parser' ;
2986
3087function wrapModuleSchema (
3188 nativeModuleSchema : NativeModuleSchema ,
@@ -155,11 +212,192 @@ function emitUnionTypeAnnotation(
155212 } ) ;
156213}
157214
215+ function buildModuleSchema (
216+ hasteModuleName : string ,
217+ /**
218+ * TODO(T108222691): Use flow-types for @babel/parser
219+ */
220+ ast : $FlowFixMe ,
221+ tryParse : ParserErrorCapturer ,
222+ language : ParserType ,
223+ parser : Parser ,
224+ ) : NativeModuleSchema {
225+ const types = getTypes ( ast ) ;
226+
227+ const moduleSpecs = ( Object . values ( types ) : $ReadOnlyArray < $FlowFixMe > ) . filter (
228+ //$FlowFixMe
229+ isModuleInterface ,
230+ ) ;
231+
232+ throwIfModuleInterfaceNotFound (
233+ moduleSpecs . length ,
234+ hasteModuleName ,
235+ ast ,
236+ language ,
237+ ) ;
238+
239+ throwIfMoreThanOneModuleInterfaceParserError (
240+ hasteModuleName ,
241+ moduleSpecs ,
242+ language ,
243+ ) ;
244+
245+ const [ moduleSpec ] = moduleSpecs ;
246+
247+ throwIfModuleInterfaceIsMisnamed ( hasteModuleName , moduleSpec . id , language ) ;
248+
249+ // Parse Module Names
250+ const moduleName = tryParse ( ( ) : string => {
251+ const callExpressions = [ ] ;
252+ visit ( ast , {
253+ CallExpression ( node ) {
254+ if ( isModuleRegistryCall ( node ) ) {
255+ callExpressions . push ( node ) ;
256+ }
257+ } ,
258+ } ) ;
259+
260+ throwIfUnusedModuleInterfaceParserError (
261+ hasteModuleName ,
262+ moduleSpec ,
263+ callExpressions ,
264+ language ,
265+ ) ;
266+
267+ throwIfMoreThanOneModuleRegistryCalls (
268+ hasteModuleName ,
269+ callExpressions ,
270+ callExpressions . length ,
271+ language ,
272+ ) ;
273+
274+ const [ callExpression ] = callExpressions ;
275+ const typeParams =
276+ language === 'TypeScript'
277+ ? callExpression . typeParameters
278+ : callExpression . typeArguments ;
279+ const methodName = callExpression . callee . property . name ;
280+ const callExpressionArgumentType =
281+ language === 'TypeScript' ? 'StringLiteral' : 'Literal' ;
282+
283+ throwIfWrongNumberOfCallExpressionArgs (
284+ hasteModuleName ,
285+ callExpression ,
286+ methodName ,
287+ callExpression . arguments . length ,
288+ language ,
289+ ) ;
290+
291+ if ( callExpression . arguments [ 0 ] . type !== callExpressionArgumentType ) {
292+ const { type} = callExpression . arguments [ 0 ] ;
293+ throw new IncorrectModuleRegistryCallArgumentTypeParserError (
294+ hasteModuleName ,
295+ callExpression . arguments [ 0 ] ,
296+ methodName ,
297+ type ,
298+ language ,
299+ ) ;
300+ }
301+
302+ const $moduleName = callExpression . arguments [ 0 ] . value ;
303+
304+ throwIfUntypedModule (
305+ typeParams ,
306+ hasteModuleName ,
307+ callExpression ,
308+ methodName ,
309+ $moduleName ,
310+ language ,
311+ ) ;
312+
313+ throwIfIncorrectModuleRegistryCallTypeParameterParserError (
314+ hasteModuleName ,
315+ typeParams ,
316+ methodName ,
317+ $moduleName ,
318+ language ,
319+ ) ;
320+
321+ return $moduleName ;
322+ } ) ;
323+
324+ const moduleNames = moduleName == null ? [ ] : [ moduleName ] ;
325+
326+ // Some module names use platform suffix to indicate platform-exclusive modules.
327+ // Eventually this should be made explicit in the Flow type itself.
328+ // Also check the hasteModuleName for platform suffix.
329+ // Note: this shape is consistent with ComponentSchema.
330+ const { cxxOnly, excludedPlatforms} = verifyPlatforms (
331+ hasteModuleName ,
332+ moduleNames ,
333+ ) ;
334+
335+ let filteredModuleSpec ;
336+ if ( language === 'TypeScript' ) {
337+ filteredModuleSpec = moduleSpec . body . body . filter (
338+ property =>
339+ property . type === 'TSMethodSignature' ||
340+ property . type === 'TSPropertySignature' ,
341+ ) ;
342+ } else {
343+ filteredModuleSpec = moduleSpec . body . properties . filter (
344+ property => property . type === 'ObjectTypeProperty' ,
345+ ) ;
346+ }
347+
348+ // $FlowFixMe[missing-type-arg]
349+ return filteredModuleSpec
350+ . map < ?{
351+ aliasMap : NativeModuleAliasMap ,
352+ propertyShape : NativeModulePropertyShape ,
353+ } > ( property => {
354+ const aliasMap : { ...NativeModuleAliasMap } = { } ;
355+
356+ return tryParse ( ( ) => ( {
357+ aliasMap : aliasMap ,
358+ // $FlowFixMe
359+ propertyShape : buildPropertySchema (
360+ hasteModuleName ,
361+ property ,
362+ types ,
363+ aliasMap ,
364+ tryParse ,
365+ cxxOnly ,
366+ language ,
367+ parser ,
368+ ) ,
369+ } ) ) ;
370+ } )
371+ . filter ( Boolean )
372+ . reduce (
373+ ( moduleSchema : NativeModuleSchema , { aliasMap, propertyShape} ) => {
374+ return {
375+ type : 'NativeModule' ,
376+ aliases : { ...moduleSchema . aliases , ...aliasMap } ,
377+ spec : {
378+ properties : [ ...moduleSchema . spec . properties , propertyShape ] ,
379+ } ,
380+ moduleNames : moduleSchema . moduleNames ,
381+ excludedPlatforms : moduleSchema . excludedPlatforms ,
382+ } ;
383+ } ,
384+ {
385+ type : 'NativeModule' ,
386+ aliases : { } ,
387+ spec : { properties : [ ] } ,
388+ moduleNames : moduleNames ,
389+ excludedPlatforms :
390+ excludedPlatforms . length !== 0 ? [ ...excludedPlatforms ] : undefined ,
391+ } ,
392+ ) ;
393+ }
394+
158395module . exports = {
159396 wrapModuleSchema,
160397 unwrapNullable,
161398 wrapNullable,
162399 assertGenericTypeAnnotationHasExactlyOneTypeParameter,
163400 emitMixedTypeAnnotation,
164401 emitUnionTypeAnnotation,
402+ buildModuleSchema,
165403} ;
0 commit comments